Fobly
Football manager
I’ve always enjoyed playing football manager games with friends. Eventually, I wanted to build one myself. Fobly grew out of that love of the game and the fun of building things.
- Role
- Solo development
- Focus
- Simulation & Product
- Platform
- Web app



01 · The players
Generating and developing players
What makes a good player? And how do they get better? I started with attributes, talent and statistical distributions. Before building the simulation, I tested different player generators and compared their results with those distributions. Normally distributed talent ratings give players different starting points. Age, training, playing time and performance determine how each attribute develops. Together, those attributes produce a rating for each position. Two players with similar talent can end up on very different paths.
Talent ratings and how likely they are
Players are generated with normally distributed talent ratings. Ratings near the middle are more common, while very low and very high ratings are rarer.
Luca
Age 19 · CM · Talent 7/10
2 matches per week
Emil
Age 19 · CM · Talent 7/10
Training without matches
An example run locally with the real XP engine. Both players have the same talent and train in midfield every day. Luca also plays matches, with an assumed performance rating of 7/10. The curve above illustrates how talent is distributed.
02 · The match engine
How individual actions add up to a match
Once I had the players, I built the match engine. It simulates matches minute by minute, following connected sequences of play. The ball’s position, the players involved and the previous actions shape what happens next. A player’s abilities affect their chances of success, so a good pass is more likely but never guaranteed. When two players compete for the ball, the engine weighs their relevant attributes against each other. A sequence of play can continue into the next minute.
17′ · From buildup to goal
Pass
Nico Richter
→ Milan Berger
Event sequence from a local demo simulation, seed 20261033. Ball positions and success probabilities come from the match engine. Ball trajectories and shot speeds use the same visualisation as live matches in Fobly.
03 · Balancing
Making differences in strength feel right
The hardest part was getting better players to make smarter decisions without letting them dominate the game. I adjusted parameters and ran batches of 1,000 to 10,000 simulated matches. I put generated teams up against each other and compared the results and match events with real football statistics. A lot of it was trial and error. What mattered was whether differences in team strength showed up in a believable way, while the game still felt right.
Two teams · 10,000 simulated matches
160
Avg. positional rating108
Avg. positional rating| FC Morgenrot | Statistic | SV Abendlicht |
|---|---|---|
| 3.40 | Goals per match | 0.98 |
| 11.88 | Shots per match | 4.54 |
A new set of simulations using the current engine, with both teams in the same formation. 10,000 matches, seeds 20261011–20271010. All averages are per team.
04 · The product
Understanding the squad and making decisions
Once the game mechanics were in place, I started on the interface. What do I want to see after signing in? How do I make sense of my squad? From the team overview, you can open each player’s profile. Fitness, positional ratings and season stats show how they’re doing in matches. Talent, traits and position-specific attributes explain their strengths, helping you make informed lineup and training decisions. I kept refining these screens as I went.



05 · Under the hood
Connecting simulation, backend and interface
The backend releases precomputed matches and handles transfers.
The journey of a match
From pre-simulation to the final whistle.
The engine computes each match in advance using the lineup and tactics.
Results, actions and the effects of each match are stored in separate staging tables.
The backend imports the match and timeline into the regular tables.
The match goes live and the stream becomes available.
Fastify sends the precomputed actions to the web app on a timed schedule via SSE.
The backend updates the standings and players, then clears the staging data.
The journey of a transfer
From auction listing to changing clubs.
The backend creates the listing and the auction on Base.
The contract holds the bid funds and refunds anyone who is outbid.
Confirmed bids update the price; late bids extend the countdown.
The monitor checks the expiry time and auction state on Base.
The backend triggers payment and waits for blockchain confirmation.
The player joins the winning club and the transfer is recorded.
Instant purchases are handled by a separate transaction monitor.