How It's Built
The short version
This whole thing is a weekend side project. I sat down with Claude Code (Anthropic's AI coding agent), explained the pool I wanted to run, and we built it together in conversation: I made the calls, it wrote the code. No engineers were harmed. Or hired.
The code is public. Poke around at github.com/intrater/wc2026.
The stack
- Next.js + ReactThe website itself, server-rendered on Vercel
- Tailwind CSSThe dark indigo + canary yellow design system
- SupabasePostgres database, magic-link login, row-level security
- VercelHosting, deploys on every commit, and the every-3-minutes cron
- API-FootballLive scores, fixtures, and standings for every match
- ResendEvery email: receipts, the kickoff blast, the Morning Digest
- Claude APIClaude Opus writes the digest narrative from verified stats each night
How the machine runs
- 1Every 3 minutes, a cron job pulls live scores and match results from API-Football.
- 2A scoring engine recomputes every entry from scratch on each pass. It is pure, unit-tested, and impossible to drift.
- 3When the day's last match ends, the night's stats are computed and Claude writes the Morning Digest in its trash-talking pundit voice. It can only use the verified numbers; it is not allowed to invent anything.
- 4At 7am ET the digest emails everyone who opted in, with the day's docket attached.
The chance-to-win rating
Each entry gets a ๐ฅ/๐ช/๐ฒ/๐ฑ label for its shot at finishing 1st overall. It's a real model, not a vibe. A Monte Carlo simulation plays out the entire rest of the tournament โ every remaining game, group stage through final โ 10,000 times, scores all 27 entries with the same engine the live board uses, and counts how often each one finishes on top. Your rating is the share of those 10,000 made-up tournaments you win.
Because everyone's rosters overlap, each simulated tournament is scored for the whole pool at once โ so the math knows you and your rivals are often rooting for the same teams. The knockout bracket is played out by team strength until a champion falls out the bottom.
Team strength isn't frozen in time. It starts from the pre-tournament betting odds, then reprices as games are played โ a favorite that keeps losing gets downgraded, an underdog on a run gets a bump. And for games kicking off soon, it pulls the live betting odds straight from the bookmakers, so the freshest read of each matchup feeds the sim.
The two extremes are exact, not estimated: ๐ No shot means it's mathematically impossible to catch the leader, and ๐ Clinched means first place is already locked. Both are pure arithmetic โ never a guess.
It's shown as a rough bucket on purpose, never a false-precise percentage. It's a model built on bookmakers' odds, so treat it as an informed hunch, not a prophecy โ and it re-runs as results come in, so the picture sharpens as the field thins out.
Decisions I'd defend
- โA tier draft instead of a bracket: you own 12 teams for the whole tournament, so every match day matters.
- โMagic links instead of passwords. It's a friends-and-family pool, not a bank.
- โThe daily email is strictly opt-in. Nobody gets spammed into following the World Cup.
- โLive scores are display-only and never feed the scoring engine. Points only come from final results.
- โEverything ships straight to production. The tournament is the test environment.
Yes, Claude also wrote this page. We are both aware of the recursion. Back to the pool