OK, so this one starts on YouTube, at like 11pm, watching a video I definitely should’ve closed an hour earlier.
I’ve been on a bit of a AI ProgBr kick lately — Igor Oliveira’s other channel, not the career-advice one. His format is simple: a new AI model drops, and he reacts to it live, poking at what it can actually do. It’s not a rigorous benchmark or a proper model-vs-model test — it’s closer to “okay, THIS just came out, let’s see.” And one of his go-to moves, when a new model lands, is asking it to recreate a classic game on the spot. Angry Birds. Doom. 3D Pinball Space Cadet — yes, THAT one, the one that came free with Windows and single-handedly destroyed a generation’s productivity during lunch breaks.
Watching grown adults get nostalgic over software is a hell of a drug, by the way. I don’t recommend it if you have anywhere to be the next morning.
In one of his videos, Igor ended with a call to action: comment which game you’d want to see an AI rebuild next. And my brain didn’t even hesitate. It didn’t go to some big AAA title or a genre I love. It went straight to a little DOS football manager I hadn’t thought about in probably fifteen years.
The Game Nobody Outside Brazil Has Heard Of
Elifoot was — is, I guess, since it still technically exists — a Brazilian soccer management sim. You picked a club, you managed the roster, you set your tactics, and then you watched a text-based simulation of a match scroll by, praying your midfield held. No 3D pitch, no fancy graphics. Just numbers turning into commentary turning into whether you got promoted or relegated that season.
I typed “Elifoot” into the comment box. My thumb hovered over post. And then I stopped.
Why am I asking someone else to rebuild this? I’m a developer. I could just… build it.
So instead of leaving the comment, I closed the tab and opened my editor.
One Backend, Every Sport
Here’s the thing about soccer management games, though — the second I actually sat down to plan it out, I realized I wasn’t really building a soccer game. I was building a shape that soccer happens to fit into.
Think about it: a soccer league and a basketball league and a volleyball league are all doing the same dance underneath. Teams. Divisions. Players with attributes. Matches that produce a winner and a loser and some numbers to argue about at the bar afterward. The sport is just the skin on top of that skeleton.
So I didn’t build a soccer backend. I built a sport-agnostic one, with a single interface — ISportRules — that owns everything sport-specific: what attributes a player has, what counts as a legal squad, how a match actually simulates. Football is just the first thing plugged into that socket. Adding basketball later means writing a new implementation of that interface, not touching the API, the database layer, or a single React component. The frontend for each sport is its own themed app; the backend underneath doesn’t care which one is talking to it.
It’s the same idea as a board game engine that knows how turns, pieces, and boards work in general, and then lets Chess and Checkers each define their own piece movement rules on top. Nobody rewrites “whose turn is it” for Checkers.
The Knob You Can Turn Without Opening the Box
The part I’m weirdly proudest of, though, is smaller than the plugin architecture. It’s about how the match simulation actually decides who wins.
Early on I hardcoded the weights — how much attack matters versus defense, how much the goalkeeper swings things, all that — directly in the simulation code. Which meant every time I wanted to tune how “swingy” a match felt, I had to touch code and redeploy. That’s the kind of friction that quietly kills a side project, because tuning “does this feel fun” turns into a whole pull request.
So I moved those weights into the database instead. One row per sport, in a match_simulation_configs table. Now tuning the game feel is a SQL update, not a deploy. It’s the difference between adjusting the volume with a dial versus opening the back of the radio and re-soldering something every time a song’s too quiet.
Nobody Signs Up for a Demo
The last decision worth telling you about is the one that almost wasn’t a decision — it kind of happened to me.
My original plan had authentication front and center. Sign up, create your club, manage your squad, persisted in Postgres, the whole “real product” experience. Which, sure, that’s the eventual season mode. But I kept picturing someone clicking a link to try it and hitting a login screen first, and just… closing the tab. Nobody signs up for a demo. I wouldn’t.
So I pivoted the whole entry point to a trial mode: no account, no database row, everything in memory. You land on the splash screen, hit “play demo,” and thirty seconds later you’re allocating attribute points and picking a lineup against a CPU opponent that got generated just for you. Refresh the page and it’s gone — and that’s fine, because the point was never persistence. The point was letting you feel the game before asking you to commit to it. The authenticated squad-management mode still exists underneath, fully built, just quietly waiting for the day I wire it back into the app for people who want their club to actually stick around.
Anyway
I never did post that comment. Igor’s never going to know that his video is the reason a fifteen-year-old memory of a DOS soccer game turned into a real, working thing with a database and a plugin architecture and an opinion about goalkeeper weighting.
Funny, though — I spent an evening watching someone ask AI to rebuild games, and ended up building one myself with an AI’s help anyway. Just not the way the comment section expected.
Elifoot never really left. I just had to go get it.