The FA needs a desk of its own
Every game world like this needs a football association behind it. Someone has to move the season on, put leagues into the database, look up a manager who says their squad has gone missing, and take the world offline when something needs fixing. For a while that someone was me with a terminal and a decent memory. That works right up until it doesn't.
So in May the FA got its own desk: the admin console, a separate Angular app, talking to admin API surfaces gated behind Firebase admin claims. Seasons and clock controls in one place. Seeding. User lookup. Queue visibility with a retry for jobs that failed. Maintenance mode. And on anything genuinely dangerous, a dry-run preview first — preview, then apply, as the default posture rather than something I remember to do when I'm being careful.
The other half of that PR was pushing the game and admin apps onto shared do-* UI primitives. Which sounds like tidying, until you think about where operator mistakes actually come from. They come from two screens that look nearly the same and behave differently. A shared layout language is cheap insurance against clicking the confident-looking button on the wrong page.
There is a limit to how much of this I will write about publicly. An admin console wants to grow into runbooks, queue internals and host-specific shortcuts, and none of that belongs in a devlog. The surface is the interesting part anyway: claim-gated tools, previews before mutations, and a settings hub that would later hold the economy and transfer knobs.
The alternative was bolting admin routes into the game app behind a nav item only I could see. That always ends the same way: the trust boundary ends up living in a template, and a hidden link is not a permission. Keeping FA tooling in its own app means managers never see operator chrome, and I stop pretending the game client is a control plane. The cost is a second frontend to keep honest about design and auth. Worth it.