Case study
A rankings and tournament platform for competitive gaming communities, with Glicko-2 ratings, live brackets and start.gg and Challonge imports. It runs in production across 3 games and 10 communities.
in its first three months, built and run by one person
The problem
Competitive gaming communities track skill in spreadsheets and run brackets across three separate tools. The hard part is identity. The same player shows up under different tags on different platforms over years of events, so nobody can say who the best player is right now. Dizzy.gg gives every player one profile with moderated identity claims, calculates a rating from their full match history, and runs the tournaments that create that history.
It works for any game and any community. Games are stored as database rows, and each community has its own rating pool and moderators, so adding a new game is a config change with no migration. I've kept to that since the first schema and it still holds at 63 models and 118 migrations. That's why three games and ten communities run on it today.
My role
Just me. I came up with the idea, designed and built it, and I maintain and run every part of it.
Capture pending
What's technically interesting
Ratings come from a deterministic module with no side effects. It processes matches in date order, applies decay for inactive players, and ranks by a conservative estimate (rating − k·deviation) so a volatile newcomer can't jump above a proven player. Because it's deterministic, I can safely recalculate all 30,028 sets against the live leaderboard. The same engine runs a separate rating pool for each community, with rules for when ratings go stale and a script for full recalculation.

The build checks packages/domain and packages/contract for purity and fails on any impure import, so nobody can quietly break the rule. Typechecking runs twice, once with tsc and once with tsgo.
About 62 oRPC procedures across 15 routers, with contracts defined in Zod. The Next.js web app and an Expo React Native app share the same domain and contract packages, and a public REST API with generated OpenAPI docs is built on the same definitions. Change a contract and every client picks it up at compile time.
Capture pending
Brackets from start.gg and Challonge come in shapes that don't normalise cleanly, like single-stage double elimination, grand-final resets, and pools that feed into a bracket. Fixing these after the fact also meant writing migration scripts for old data and recalculating ratings across the whole site.

CI checks for migration drift against a clean Postgres 18 container, and production deploys take a pg_dump backup before migrating. Tests run in parallel, with each CPU worker getting its own copy of a seeded template database and a guard that refuses to touch any database not named for testing.
Capture pending
Stack
Proof