Progress reports

Devlog

I am building an iOS app called TAG. This is the log: what got built, what broke, what I decided and why.

TAG — where the app is right now

It is out, and people are playing it. TAG is on TestFlight, the external beta passed Apple's review in a matter of hours, and the link is public: join the beta. You need the TestFlight app, that link, an invite code from a gang, and Always on the location question. The invite mail from Apple has a habit of landing in spam.

Five testers on the first build, thirty-one sessions between them before I had finished writing this. It is a real game now rather than a thing that compiles.

Build 2 went out to everyone today and took five new things with it: the whole gang on the home screen, protests after the fact, a location requirement you cannot quietly opt out of, anonymous tips to whoever is it, and a gang chat. Apple let it through without another review, since it stays inside what was already approved.

The week's other work was less fun and more important. I went through the database asking not what the rules allow, but what a modified app could do around them. Four holes, all the same shape: a table where the permissions were wider than any rule justified. One of them let a gamemaster rewrite the history of who caught whom. All four are shut, and a test now fails if any table is ever given a write permission without a policy to justify it.

Migrations 1 to 36 in production. 74 unit tests, 538 database assertions, and four interface tests that play the real game against the real backend.

Next: screenshots, review notes, and the App Store itself.

A notification got through

I bought the developer account, and within a day the app was signed onto a real phone, push was arriving for real, and version 1.0.0 was sitting in App Store Connect. Also: the most unhelpful error message I have ever been handed.

Read it

I went looking for holes on purpose, and found thirteen

The rules were right. The seams between them were not. A week of asking the database questions it had never been asked, including one where saying nothing wins you the season.

Read it

The playground got rebuilt in a night

This site went up, got nine games, and then got torn down to the studs and rebuilt in a completely different style. All in about six hours.

Read it

Stage 2: UAVs, truces, Bluetooth, and an album of evidence

Everything that makes the month worth playing rather than just surviving — plus two things production taught me that no local test could.

Read it

The hunt, and the test that ate its own notification

Your phone now wakes up on its own and tells you someone is within a kilometre. Getting the test to agree took four wrong theories and one uncomfortable realisation.

Read it

Two phones, one real tag

A test that creates two accounts, puts them a few metres apart and plays the game against the live backend. It found a bug on its second run.

Read it

Stage 1, shift B: the rules moved into the database

The app stopped deciding whether a tag counts. Postgres decides now, the app just asks — and that closed the only real cheat path in the game.

Read it

Stage 1, shift A: the countdown runs

The first version that actually launches. Four countdown states, a design system, and 15 tests on the one piece of logic that has to be right.

Read it

Stage 0: rules first, code later

One commit, no app code. Just the rulebook, the database schema, the privacy rules, and a clickable prototype of seven screens.

Read it

Why I'm building an app for a game of tag

A group chat is a terrible referee. So I am building one that never forgets, never sleeps, and cannot be argued with.

Read it