WC26 Pool
A private World Cup prediction pool with two game modes — per-match predictions and a full knockout bracket — that replaced a manual WhatsApp workflow for 6 friends.

Overview
Six friends used to run a World Cup prediction pool entirely on WhatsApp — someone posted daily matches, everyone replied with scores, and someone else tallied points by hand. WC26 Pool replaced that entire workflow with a web app covering two distinct game modes: per-match score predictions with immutable submissions, and a Pick'em bracket where each participant picks the winner of every knockout round up to the champion — all feeding into a single unified leaderboard.
Features
- Daily match schedule with live scores updated in real time
- Per-match prediction system with immutable submissions — locked on send
- Auto-reveal logic: predictions stay hidden until all 6 submit or kickoff
- Pick'em bracket: predict the full knockout tree from quarters to champion before a fixed deadline
- Bracket consistency validation: a team can only advance if picked in the prior round
- Lazy per-slot scoring: each pick is evaluated only when that team's specific match concludes
- Live leaderboard merging points from both modes into a single ranking
- Upcoming calendar showing the next 7 days of matches grouped by date
- Knockout stage support with extra time and penalty shootout predictions
- Mobile-first design
The Challenge
The two hardest problems were rate-limit management — six users polling a free-tier football API simultaneously would burn through the quota in minutes — and adapting the scoring system mid-tournament when the group added knockout stage rules that required tracking match duration and penalty outcomes separately from regular time. The pick'em bracket introduced a third constraint: scoring picks lazily per-slot rather than all at once, to accurately reflect that each team's fate is determined by a different match at a different time.
Scoring Rules
Group Stage
| 2 pts | Exact scoreline |
| 1 pt | Correct result (win / draw / loss) |
| 0 pts | Wrong result |
Knockout Stage (Round of 32+)
| 3 pts | Correct scoreline (full time + extra time) + correct penalty winner |
| 2 pts | Correct scoreline (full time + extra time) |
| 1 pt | Correct team advancing, regardless of how |
| 0 pts | Wrong team advancing |
Only the highest applicable tier is awarded per match — not cumulative. When predicting a draw in the knockout stage, selecting the penalty winner is mandatory.
Key Technical Decisions
No login system
Six known participants make full auth unnecessary — managing passwords or OAuth flows would be overkill. Instead, name selection on first visit is persisted in localStorage with a switch-user option for corrections. Zero friction, zero accounts.
Backend as API gateway for football data
The frontend never calls the football API directly. An ASP.NET Core BackgroundService polls the external API on a smart schedule and caches everything in PostgreSQL. All six users hit the backend, not the rate-limited external API. Polling intervals adapt to context: every 20 minutes when no match is imminent, every 2 minutes when kickoff is within 30 minutes, every 1 minute while a match is live.
Immutable predictions
Once submitted, predictions cannot be changed — replicating the WhatsApp dynamic. Enforced at the database level with a unique constraint on (ParticipantId, MatchId). Duplicate submissions return a 409 response. The UI reflects this by locking the form immediately on submit.
Knockout stage adaptation mid-tournament
Scoring rules were extended during the tournament without breaking existing data. The system was updated to track duration (REGULAR / EXTRA_TIME / PENALTY_SHOOTOUT), regularTimeScore, and penaltyScore as separate fields. The scoring service branches on the match stage field to apply the correct rule set, so group stage matches and knockout matches are scored independently.
Pick'em bracket with lazy slot scoring
The bracket stores 7 picks per participant (4 quarter-finalists, 2 semi-finalists, 1 champion). Each pick is evaluated independently when the team it references plays — not when the bracket closes. The PickemScoringService runs after every confirmed match result, checks which picks reference that specific team and round, and propagates only the delta to TotalPoints. This prevents double-counting across successive scoring calls and keeps the leaderboard accurate at any point mid-tournament.
Results
The app was actively used by all 6 participants throughout the 2026 World Cup. Per-match predictions ran from the group stage through the final; the pick'em bracket launched at the quarter-finals with deadline enforcement and progressive scoring. Both modes fed into the same leaderboard without conflicts.