Off the radar  /  №02  /  06.22.26

A game in the dormant slot.

The blog had an empty WebAssembly slot I wired months ago and left dark on purpose. This week I filled it with Asteroids: Rust compiled to a single file the browser runs like native code.

When I stood this blog up as a proof of concept, I left one thing deliberately empty. The page template had a slot for a WebAssembly module, wired in and shipping nothing, with a comment that said drop a module here later. It was a promise to myself that the static-first rule had a pressure valve. This is later.

The ask was simple and a little nostalgic: a classic arcade game, Asteroids, running entirely as WebAssembly, wearing the look of an old toy I'd built before, and hosted right here on the same static site you're reading. No new server, no app store, no plugin. A link.

What WebAssembly is, for the rest of us

Browsers have always run one programming language: JavaScript. WebAssembly, or WASM, is the second thing they learned to run. It's a compact binary format that languages like Rust, Go, and C can compile down into, and the browser executes it at close to the speed of a normal installed program, inside the same locked room it runs everything else in. You don't install it. It arrives as a file over the same connection as the page, and it can't reach any further into your machine than the webpage already could.

For a game, that's the whole pitch. The physics, the collisions, the rendering all run as compiled code instead of interpreted script, and the entire thing is one .wasm file sitting on disk next to an HTML file. That's it. The browser fetches it like an image and runs it like an app.

The boring choices, made on purpose

I could have reached for a game engine. I didn't. Asteroids is a few hundred lines of vectors and arithmetic; talking to the browser's drawing surface directly keeps the dependency list nearly empty and the download tiny, about sixty kilobytes of compiled code. That's the same rule the rest of this system runs on. Boring is a feature; every moving part has to argue for its place.

The look was the interesting part. The CRT shimmer I wanted, all scanlines and digital rain bent around a curved glass tube, lived in that old toy as a tangle of framework code driving a graphics shader. I kept the shader, the small program that actually paints each pixel, and threw away everything around it, rewriting the scaffolding so it runs straight from Rust. The part worth carrying forward was the look, not the machinery that happened to be under it the first time.

Then I opened the first build on my phone, which has no arrow keys, and the game was unplayable. So it grew thumbs before it grew almost anything else: on-screen rotate, thrust, and fire pads that lay themselves out to fit whatever screen you're holding. Mobile wasn't a port I did at the end. It was the second thing I built.

It ships like everything else

The finished game is four files: the compiled code, a little loader, a page, and a stylesheet. They sit in the blog's static assets exactly like a photo would. Publishing the blog copies them up untouched, and the thing that serves this site, a plain file server pulling a git repository every thirty seconds, now hands out a real-time arcade game with precisely zero new infrastructure. The compiler ran on my laptop. Nothing built on a machine I don't own.

The two real detours weren't the game at all. My Rust install flatly could not target the browser, and I spent an hour teaching the toolchain a trick it ought to have known out of the box. And I managed to poison my own preview image by checking its address one second before it existed, so a cache somewhere dutifully remembered the absence for a day. Both are the kind of tax you pay once and only notice because everything around it was quiet.

That's the lesson hiding in a toy. Static-first was never static-only; the discipline was leaving a labeled, empty slot and trusting myself to fill it on purpose, a deliberate island in water I keep calm by default. The blog that proves I don't have to remember my infrastructure now has a game in it. Same repository, same thirty-second pull, one more file.

It's in the nav, up top, under Arcade. Go fly it.