Terra Incognita: a multiplayer geography game, built in three days
A photo of a real place, a world map, and five thousand points riding on how close your pin lands. The game took a weekend. What it taught me about building with an AI agent in the loop is the part worth writing down.
Terra Incognita is a where-in-the-world guessing game. You get a photo of a real place — or a drop into Street View — and you put a pin on the world map. The closer you land, the more of the 5,000 points per round you keep.
Play it solo. Take the Weekly Expedition, where everyone gets the same five locations and the board resets on Monday. Or open a live room: the map goes up on the big screen, up to fourteen people join from their phones with a four-letter code, everyone guesses against one clock, and the reveal shows every pin at once. It is the closest thing I have made to a party game.
Empty folder to production took three days.
The bottleneck moved
I have been shipping software for a long time, and the constraint was always typing. You knew roughly what you wanted; the cost was the hours between knowing and having. Work with an AI coding agent and that cost falls close to zero — and the moment it does, a different constraint walks to the front of the queue.
The new bottleneck is specification and verification. Saying precisely what you want, and proving that what came back actually does it.
Everything below is a version of that.
Make the tests the gate, not a chore
Terra Incognita ships with 55 unit tests and 19 end-to-end browser tests. Nothing reaches production unless both suites pass: GitHub Actions runs them and only then calls the deploy. Vercel's automatic git deploy is switched off on purpose, so a red suite cannot ship — not "shouldn't", cannot.
That isn't discipline for its own sake. When code arrives faster than you can read it, tests stop being a quality ritual and become the only honest signal you have left. Velocity without them is just a faster way to be wrong.
The agent doesn't see what your users see
My favourite failure of the build. The browser pane the agent uses to preview a page reports itself as hidden, and Google Maps politely declines to render into a hidden document. So the guess map came back as a flat grey box in every screenshot I was shown, while being perfectly fine for every actual human.
The fix wasn't code. It was one line in the repo's instructions file: don't trust the preview for maps, verify with a real browser test. That generalises. When you find a way your tooling lies to you, the durable fix is writing it down where the next session will read it — not remembering it yourself.
Write down the contracts, especially the invisible ones
The game embeds its location list in the page, and the server scores your guess against the same list by position. Two copies, one order. Reorder either and every score silently becomes wrong — no error, no crash, no red anywhere. Just quietly incorrect results and a leaderboard nobody can trust.
So the rule sits at the top of the repo instructions in capitals: that array is append-only. The constraints that hurt you are never the ones a type checker catches. They are the agreements between two files that nothing enforces, and if they live only in your head they last exactly as long as your memory of them.
Constraints do design work for you
The whole game is a single self-contained HTML file. The world map is inline SVG generated from GeoJSON, the photos are static assets, the built page is about 370KB, and there is no framework anywhere in it. Multiplayer lives in a handful of small serverless functions — Redis holds live room state with a four-hour expiry, Postgres holds the all-time leaderboard.
I didn't pick that because it was minimal. I picked it because one file is trivially verifiable, costs nothing to host, and is very hard to accidentally over-engineer. The constraint made several decisions for me before I got to them.
The honest part
Three days is real. So is the fact that the last of them was barely about features. It was an accessibility pass, chasing test flakiness caused by external network calls, keeping the architecture page honest, and fixing the defaults so a new player lands somewhere sensible rather than somewhere random.
That ratio feels about right, and I suspect it is the actual shape of this work now. Generating the thing is fast. Making it correct, accessible, documented and safe to change is where the days go — and that part is still judgment, not autocomplete.
Same as oil paint, really. Anyone can cover a canvas. Sweating the craft is the whole job.
Go and lose to your colleagues
Open a live room, send the code round the office, and find out who can genuinely put a pin within 50km of Ha Long Bay. Five minutes, and the leaderboard is permanent.