Building The Beautiful Game: a World Cup tracker I actually wanted, in an evening
These posts are live but still drafts — I'm figuring out how to write well with AI, and the tone and structure may shift as I go.
The World Cup is on right now (the bracket is filling in as I type) and I’m following it on a website I mostly built in one evening.
The itch was Apple Sports. If you have an iPhone, you know it: the best-designed way to follow live scores that exists, fast and quiet and correct. I wanted exactly that for the World Cup. Except Apple Sports is an iPhone app, full stop. There’s no website, no Windows app (which stings, because that’s where I spend my day), and not even an iPad app: open it on an iPad and the best you get is a widget, a keyhole view of the real thing. The rest of the field made me feel punished for liking soccer: score sites where the bracket is buried four taps deep under an ad for a crypto exchange and a quiz about which midfielder you are. Somewhere, a product manager is A/B testing how many banner ads a person will scroll past to learn whether France won. For me the answer turned out to be zero, because I left and built my own.
The bar I wanted was simple but accurate: a premium, minimalist tracker on the open web, on any screen. So one Wednesday evening, I made one.
Pretending this was hand-carved would violate the whole spirit of the thing, so here’s the actual workshop: Antigravity 2.0 for front-end prototyping (it is genuinely excellent at this), Claude Code to build the backend properly, and Cursor for bug fixes. Next.js on Vercel’s free tier, auto-deploying from GitHub. My infrastructure bill is zero dollars a month. After that first evening, most of the iteration happened from my phone, on vacation, poking at the code between swims.
I keep waiting for the fun to wear off and it hasn’t, and I think I finally understand why: vibe coding is genuinely fun when you have a problem you care about. The tool isn’t the joy. The joy is watching the thing you wished existed assemble itself in front of you, while the group stage is actually running.
The hard part had nothing to do with code. The hard part was data. Specifically, finding sources that would do what I wanted for free.
Every zero-budget side project eventually runs what I call the Free-Tier Gauntlet: an obstacle course in which every vendor’s free plan is generous, well-documented, and missing exactly the one thing you need. And you never find out at signup. You find out after the integration is built.
I built the entire live-score layer on API-Football. Clean docs, proper key, comfortable quota. Then I asked it for the 2026 season, and it replied, verbatim: “Free plans do not have access to this season, try from 2022 to 2024.” I had built a live World Cup tracker whose data source was only licensed to tell me about World Cups that had already happened. I had wired the whole house before checking that the power company served my street.
The fix came from the sports-nerd forums. ESPN runs an undocumented, keyless API (the same one their own site uses) and it covers the 2026 tournament completely: live scores, team stats, starting lineups, key events, full play-by-play. No key. No quota. No invoice. Finding it felt less like engineering and more like discovering the stadium has an unlocked side door.
The architecture is the one place I refused to vibe. A tracker that dies in the round of 16 is worse than no tracker at all, so I wanted this thing robust and durable on purpose: a live source, a backup, and a memory. Three sources, each with one job. The schedule (fixtures, venues, kickoff times) lives as static files in the repo, because fixtures don’t change and you shouldn’t pay anyone to tell you what’s already printed. ESPN is the live layer, refreshed on a 60-second poll. openfootball, a community-maintained open dataset, is the backup: it backfills goal scorers and stands underneath the unofficial API as the safety net. And then the piece I haven’t seen other hobby trackers bother with: a scheduled job that archives the data as it lands, so the tournament accumulates into a permanent record I own. If ESPN changes their API tomorrow, every match already played is safe on my side of the wall, and the site degrades gracefully instead of going blank.
Honesty requires a caveat here, so: an undocumented API is a handshake deal. It can change without notice, and it isn’t licensed for public redistribution. Fine for a personal project, not fine for a real product. If this ever becomes one, the live layer swaps to a licensed provider; that migration is already wired and dormant, one setting away. I deferred the decision deliberately. Ship it, decide later.
The desktop experience. Open it during a match window and everything I wanted from Apple Sports is there, on the big screen, on any platform: live scores ticking along, the full schedule in your time zone or the venue’s, group standings, goal scorers with the minute they scored, and the piece I care about most: a comprehensive knockout bracket where winners propagate through automatically as results land.
None of it is flashy, which is the point. Taste, in trackers as in most things, is subtraction: show the score, the time, the state of the tournament, and delete everything else. No ads. No parlays. No quiz. The thing I set out to test was whether one person with AI tools could get near an Apple-level UX bar on the open web. I got closer than I expected, in evenings.
That’s the part worth generalizing. The gap between “I wish this existed” and “this exists and I’m using it” used to be a team, a sprint plan, and a budget. For a working prototype of a consumer-grade experience, it is now roughly one free Wednesday and a data source you’re willing to hunt for. The Gauntlet is still real (the free tier will still betray you at the worst moment) but the building itself has stopped being the bottleneck. Caring is the bottleneck. The projects that get finished are the ones where you actually want the thing.
There’s a version of you that has wanted some specific tool for years: the tracker, the dashboard, the little site that works the way your brain works. The distance between you and it is shorter than it has ever been.
The final is on July 19. The match will be on the TV like always, and the bracket that got us there will be open on the thing I wished existed. Then the World Cup goes away for four years, and the tracker goes quiet with it. The joy of building doesn’t. It just looks around for the next itch, and there’s always another free Wednesday.
The Beautiful Game is live at worldcup.tylergray.app, or see the project page.