Case study N° 04 · Sports
SimWorld Sports platform
The league website, the coaches' live game-day portal and the media desk for a simulated basketball league network.
Sample data, runs in your browser
Live coaching hub, signed in as a fictional coach
- One site and one portal
- 2leagues
- SWU plays halves and SW Prep plays quarters; schedules, box scores and brackets handle both.
- Per base-strategy reset
- 27engine calls
- Sent in seven batches, then logged to coaching_actions. A timeout also posts to the team’s Discord.
- Region pairs priced for recruiting
- 15,799pairs
- An offer’s cost is one lookup, from the player’s home region to the team’s.

Two leagues, one website
SimWorld Sports ran a simulated basketball world with a college league (SWU) and a prep league (SW Prep). The public site is a Next.js app on Postgres. It has a schedule for every day, conference standings with last-five records and streaks worked out in the API, team pages, box scores and tournament brackets.
- Records at tip-off. Each game stores both teams’ records at the time it was played, so old box scores read the way they did that night.
- Brackets from data. A bracket template is stored as JSON. Games carry a round and a slot, and the page fills the template from them.
- Two scoring formats. SWU plays halves and SW Prep plays quarters, and the same box score component handles both.
A coach’s adjustment, end to end
Coaches signed in with Google or Discord. Only emails already in the league’s users table got in, and middleware checked each coach’s role and league. During a live game, Coaches Corner is the sideline. Every button runs the same four steps:
- Check in Postgres that the game is live and the team is in it.
- Send the settings to the game engine. Resetting to the coach’s base strategy is 27 requests in seven batches: points of emphasis, offensive sets, coach sliders, 17 defensive settings and the defensive game plan.
- Post a line to the team’s Discord locker room, as the coach.
- Log a row in
coaching_actionswith the request, the engine’s reply and the Discord message.
Before tip-off, coaches set presets for each player: starter, scoring option, ball handler, minutes and touches. They also set the team’s on-ball philosophy, pick-and-roll coverage and pressure.
Recruiting on a budget
Coaches recruit with a budget. An offer’s cost depends on how far the player is from the program, so it’s a single lookup in a 15,799-row table of home region to program region. The recruiting page lists the open offers, the players still available and what each one would cost.
The media desk
Before the web platform, I built the SimWorld Media Control Panel for the media team. It was a cross-platform Python desktop app (Kivy) for writing and publishing league content.
- Recaps and graphics for all 32 teams, drafted with the OpenAI API from league data in Google Sheets.
- Images hosted on Imgur and files kept in Google Drive.
- A separate scheduler for recurring posts, plus installer scripts so non-technical staff could set it up themselves.
How these demos run
Both demos are the original apps, exported as static sites. The league data is invented: teams, arenas and events come from the repo’s own SQL, and every player, coach and score is generated.
- The website. Its API routes and SQL ran unchanged at build time, against Postgres compiled to WebAssembly (PGlite). Their responses are served as JSON, with dates moved so that today always has games.
- The coach portal. Its route handlers run in your browser against that same embedded Postgres. Requests to the game engine and to Discord are captured in a “Behind the scenes” panel instead of being sent.
Getting the old code running turned up bugs, now fixed:
- Strategy page crash. It read the team from React state before that state was set, so it crashed in production builds.
- Team schedule never loaded. Its data effect ran before the coach id was read from the URL.
- Hook order. A hook came after an early return, which React rejects.
- Missing columns. One stats route queried columns the players table doesn’t have.
- Wrong links. Prep coaches’ dashboard links pointed to the college league’s pages.
- Dates off by one. Game dates were shown a day early in US time zones.
Result
The site and the coach portal were built for the league’s fourth season. The player hub was never finished, so the demo shows its in-progress design on mock data.
Figures



Methods
- Stack
- Next.js 15, React 19, TypeScript, PostgreSQL (AWS RDS), NextAuth (Google, Discord), Tailwind, Discord webhooks, Python, Kivy, OpenAI API.
- Data
- The demo runs in your browser on sample data; nothing is sent anywhere.
- Status
- Shipped Oct 2025. SWU and SW Prep coaches, fans.