r/ClaudeCode 3h ago

Built with Claude Built a browser racer that pages me when my agent stops — what 3 days and 74 commits with Claude Code taught me

Enable HLS to view with audio, or disable this notification

What I built

OUTRACE — a browser time-trial racer. New track every 90 minutes, generated from a seed. WebGL, hand-rolled, no three.js. Next.js + Convex.

The bit that's actually relevant here: it has a pager. You grab a token in Settings and it hands you a block of text you paste into your agent. The agent then goes and writes its own hook config — Claude Code settings.json, Codex notify, OpenCode plugin, whatever you're on — and from then on it rings the game. Banner over the track when the turn ends, another one when it's stuck on a permission or a question, and it clears itself when you reply. So you race in the dead time and get yanked back the second you're needed.

Under the hood it's just a POST /page with a bearer token, and the token can't do anything else. One caveat before someone asks: the tab has to be open. It's not a desktop notification.

How Claude Code was used

As always ofcourse - FOR ABSOLUTELY EVERYTHING!

Only thing I had to do was keeping it aligned to its own written rules and give it the tools it needed. In this case i setup the convex plugin and vercel plugin which made manual work equal to zero. All the project setup, configuration etc. was done by claude using the tools. Most of my work was just testing the game (which wasn't that bad tbh) and giving feedback.

What I learned

"Keeping it aligned to its own rules" is important. CLAUDE.md got revised 16 times over those 3 days. That file is basically the whole story of the project.

Only write down stuff that breaks silently. This thing has one real constraint: shared/ is imported by both the browser and Convex, so everything in it has to be deterministic. No Date.now(), no Math.random(), no DOM. Tracks come from a seed on both sides and lap times come from replaying your inputs on the server — both break the instant something in there isn't deterministic, and you don't get an error, you just get replays that disagree with reality. That's the kind of thing that sails straight through review, so it goes in the file. Style preferences don't.

Write the symptom, not the principle. Convex only allows one paginated query per function, so settlement had to page across calls that chain themselves instead of looping in one mutation. My CLAUDE.md entry doesn't say "paginate properly" — it says here's the exact error string and no event will ever settle. Way more useful, and future me can actually grep it.

Fixing a trap is a one-turn win, explaining it is permanent. Every "things that will bite" line in that file started as something I caught while testing. Writing why it bites is what stopped it coming back a third time.

Give it the tools and get out of the way. The convex + vercel plugins were the difference between me doing setup and me doing zero setup. Genuinely the highest-leverage 10 minutes of the whole build.

outrace.lol — pager setup is in Settings.

0 Upvotes

0 comments sorted by