How I shipped a production app by managing AI agents like a team
Six weeks from spec to production, a tennis-league app with live standings, brackets and offline sync. I wrote almost none of the code. I ran the team that did.
League60 started the way most side projects do: with a real annoyance. Community tennis leagues run on WhatsApp threads and a spreadsheet somebody regrets owning. Standings lag, courts double-book, and the organiser is the single point of failure. I wanted the boring version of a miracle, a league that runs itself.
The interesting part isn't the app. It's how it got built. I'm one person with eleven years in analytics and strategy, not a career software engineer. The way through wasn't learning to hand-write React at a professional level. It was noticing that the job had changed shape: AI agents can now produce production-grade code, but only inside a management structure that treats them as what they are. A team. Talented, tireless, and perfectly happy to ship you something confidently wrong.
So I ran them like a delivery organisation: specs, routing, verification, release discipline. Six weeks later the league was in production.
The org chart
Two agents, two roles, and half the job is routing between them.
The senior is the surgeon with the medical record. It holds context across the whole codebase, remembers prior architectural decisions, and can refactor across many files without breaking the ones it isn't looking at. Anything touching the data model, security, or several surfaces at once goes to the surgeon. So does anything where taste matters.
The junior is fast and precise on clean, mechanical work: a pure function, type definitions from a settled schema, unit tests for something that already exists. The escalation rule is mechanical too, the moment a task touches more than one file, or any shared state, it stops being a junior task. And when the junior's first instinct is wrong, you don't coax. You reassign. Anyone who has managed people will recognise more of this than they expected to.
Spec, requirements written as prompts
Every piece of work ships as a written brief precise enough that a machine can build from it, which, it turns out, is simply a good spec. Three rules carry most of the weight.
One verifiable outcome per brief. Two outcomes is two briefs. Small and sequenced beats big and clever, because small is what keeps review honest.
Name every file in scope. The list is a contract. If the work turns out to need a file that isn't on it, the scope was wrong, stop and re-scope rather than silently expand.
Put the don't-touch list in writing. Some files encode correctness that is expensive to get right and easy to break, the tennis scoring engine, the standings tiebreakers. Agents love to "improve" these in passing, the way a new hire loves to reorganise the shared drive. So they're protected: named at the top of any brief that goes near them, off-limits without an explicit instruction.
And every brief ends the same way: walk me through what changed and why, before you save.
Verify, gates, not vibes
Here is the uncomfortable truth about managing AI: the work always comes back looking finished. Confidence is free. So the whole system rests on one convention:
Every batch of work returns with evidence, not assurances:
gate B, the test suite's numbers, delta in words: 1,191 → 1,197, six new, zero regressions
gate C, the targeted test or check that proves this outcome
gate D, grep proofs, both directions: the old path is gone and the new one exists
"Tests pass," without the numbers, doesn't clear a gate. Then I verify against the real files anyway, never assume the agent finished the job. Each batch ends in a written report, and the reports become the durable record: a reader should be able to trust the work without re-running it.
If that sounds like bureaucracy, it's the opposite. The loop is deliberately small, one brief, one outcome, one report, precisely so that checking stays cheap and nothing rides on trust.
Ship, deploys are boring
If the gates pass, it goes live. That's the whole ceremony. Boring deploys are the point: the drama is supposed to have happened earlier, in the spec and at the gates. Production discipline for a team of one looks exactly like production discipline for a team of forty, with the meetings deleted.
What managing machines teaches you
The failure mode has a name: scope generation running ahead of validation. Agents make building feel free, and free building is a trap, you can produce features faster than you can prove anyone needs them. The counterweight is structural. One outcome per batch. Adjacent bugs and tempting refactors get surfaced in the report, not silently fixed. Speculative features get removed after real use. Cutting scope is progress.
The other lesson is about words. The quality bar is binary, it works, it's safe, it's understandable, it's presentable, and "understandable" is enforced with a deliberately humbling rule: a seven-year-old should be able to read every word on a primary screen. Sport jargon out. One obvious next action per screen. Errors written as sentences with verbs in them. Machines didn't need that rule. I did.
Where this leaves analytics
I spent eleven years producing analysis that ended, as analysis usually does, at the recommendation, a deck, a model, a memo that somebody else might build. This method removes the excuse. The same discipline that runs an AI build team, spec, route, verify, ship, takes a recommendation the rest of the way to a deployed, working thing.
That's the thesis of this site, and the exhibits are the receipts: a break-even model you can argue with and a Eurostat dashboard that writes its own analyst's notes, built by the same pipeline that built the league. Most analytics careers end at the recommendation. Mine ends at deployment.