Inspiration

Most web games hide everything about their state inside memory you can't see or touch. I wanted the opposite: a game where the browser itself — the address bar, your history, the Back button — is the controller. Not a UI skin sitting on top of a normal game engine. The actual game state, in plain sight, editable by hand.

What it does

404 is a puzzle game played entirely inside your browser's address bar.

  • Your position, key, and progress live in window.location.hash — no hidden state. Hit a wall? The game tells you its exact coordinate. Edit x= in the address bar yourself to get past it.
  • The browser's real Back button doesn't leave the page — it rewinds time and leaves an echo of your past position behind. Stand on a pressure plate, walk away, press Back, and your echo keeps it held down while you move on.
  • A locked door hides its key in the URL for a couple of seconds, then redacts it. Miss it? Press Back — history remembers what the current page forgot.
  • Every run is procedurally generated — the walls, the plates, the key, none of it repeats. Replay it and difficulty escalates: a second wall to edit past, a second plate that needs two separate echoes held down at once.
  • There's a hidden room, not linked anywhere in the game — you have to type your way there yourself.
  • Fully playable on desktop and on a phone (on-screen touch controls), with zero shipped image or audio assets.

Play it: https://four-oh-four-three.vercel.app/

How I built it

TypeScript, Vite, and the Canvas 2D + Web Audio APIs — nothing else. Every visual is drawn live on a canvas; every sound effect (footstep, door thud, rewind whoosh, key chime, win chord) is synthesized in real time with oscillators and filtered noise, so the shipped bundle has zero image files and zero audio files. The whole game is under 11 KB gzipped.

Game state is parsed from and serialised back to the URL hash on every frame, and a small router tracks browser history depth to tell a genuine Back-button rewind apart from a manual URL edit — that distinction is what makes the "echo" mechanic possible at all.

Room layouts are generated with a seeded PRNG so difficulty can scale (second walls, second plates, narrower margins, shorter reveal windows) while staying provably solvable — every generated room is covered by automated tests checking the geometry always leaves a valid path through.

Challenges I ran into

  • Getting the Back-button "echo" timing exactly right took several iterations — browser history commits have to happen at precisely the right moment (the start of a movement, not the end) or the position you meant to rewind to gets silently overwritten before you ever press Back.
  • Making sure every procedurally generated room is actually solvable, not just "probably fine" — solved with generation rules that guarantee minimum gaps between every obstacle and the door, backed by tests across many seeds and every difficulty tier.
  • Real mobile support without abandoning the "keyboard + address bar" identity of the game — on-screen touch controls that only appear for genuine touch input, never guessed from device type alone.

What I learned

How much can be built with nothing but the platform itself — no asset pipeline, no external libraries for rendering or audio, just the browser's own APIs pushed a little further than usual.

What's next

A "share this run" mode using a seed embedded in the URL, so a player could send a friend the exact same generated dungeon to race against.

Built With

Share this project:

Updates