4 min read

One rule, forty AI sessions: how PlayTab stayed one app instead of several

PlayTab has been built across somewhere around forty separate AI coding sessions — different days, different weeks, sometimes a different mood entirely about what the app should feel like. None of those sessions remember the one before it unless I hand it something to read first. And yet every section label on every setup screen is the same lime green. Every picker with more than a couple of options is the same bottom sheet. There is not one avatar anywhere in the app, despite how naturally "let's add a little circle with their initial" suggests itself the moment you're laying out a player list.

That consistency isn't luck, and it isn't me reviewing every screen by eye before it ships. It's a project file the AI is required to read before it touches anything — and being genuinely strict about what's allowed to live in it.

A rule with an exception is a rule that comes back

The easy version of "keep it consistent" is a sentence like "don't use avatars in the stats tables." That sentence has a gap in it the size of every screen it doesn't mention, and the gap gets found. Avatars showed up anyway — not in the stats tables, but in session match cards, in the new-session player list, in the player picker, quietly imported into two Splitwise screens that never even rendered them. The rule wasn't wrong, it just wasn't total, and a rule that's true "in the tables" but silent everywhere else invites exactly the kind of screen it never mentioned.

The fix wasn't a longer sentence. It was deleting the avatar component's file entirely, so there was nothing left to reintroduce by accident. A rule that can't be half-followed doesn't get half-followed.

The color that got reverted on purpose

Not every correction in the project file is a bug fix. Some of it is a taste call that a technically-correct pass got wrong, and that's worth keeping too.

The muted grey-green used for secondary text sits below the contrast ratio a standard accessibility pass wants. An audit flagged it and "fixed" it — lightened it to something that measured better. It got reverted within the same session: the new tone read as worse, not better, on this app's specific dark background, full stop, no further debate needed. What went into the project file afterward wasn't "leave the contrast alone forever" — it was the much more specific instruction to never re-propose that exact fix without being asked, because the numbers being technically better doesn't mean the outcome is. A style guide that only records what's measurably correct will keep re-litigating a call that was already made on purpose.

The other half: a list of scars, not just a list of styles

Design rules stop the app from looking like several different apps stitched together. They don't stop the app from repeating a bug it already paid to fix once. That's a separate list, and it turned out to matter just as much.

One entry: a match's forfeit flag used to survive being overwritten. Score a match, forfeit it, then go back and enter a real score to correct it — the FORFEIT badge stayed on the card forever, because fixing the score only ever touched the score fields, never the flag that controlled the badge. The rule that came out of it wasn't "remember to clear forfeit_winner" — it was broader and more reusable than that single field: whenever a fix overwrites a row's main value, check every other column a previous state of that row could have set, and clear it explicitly in the same update. That's a shape of bug, not a one-off, and writing down the shape is what stops the next instance of it rather than just the one that already happened.

What a session actually looks like

Concretely: before an AI session touches a single line, it reads the project file — the tech stack, the section-header color convention, the bottom-sheet-for-more-than-two-options rule, the running list of exactly what's gone wrong before and why. I describe what I want changed in plain language, not in CSS, because the consistency rules already answer "what should this look like" for anything that's a variant of something that already exists. And the file gets updated at the end, not just with what got built, but with what almost went wrong.

The takeaway

Consistency across forty sessions isn't something the AI develops on its own — it has no continuity between them to develop it in. It's a property of what you make it read before it starts, and it only holds if that file is treated as strict enough to actually be followed, not just consulted.

Next: a bug that only ever showed up for people who'd already used the app successfully before — which made it almost impossible to catch by testing, since testing is exactly what a person who's already used the app successfully does.