BracketLab
Fantasy tennis bracket challenge with live scoring, private groups, and global leaderboards.
- Web App
- Consumer Product
- UI/UX
Fantasy tennis, without the spreadsheet
BracketLab is a March Madness-style bracket challenge for Grand Slam tennis. Players predict every match in the men’s or women’s draw, join private groups, and watch their picks turn into points as the real tournament unfolds.
I wanted it to feel like a consumer sports product rather than a statistics dashboard. Most people arrive through a friend’s invite link, often on their phone, and may never have filled out a tennis bracket before. The interface had to explain itself quickly, make a very large prediction feel manageable, and remain interesting long after the picks were locked.
- 500+
- active players
- 15+
- countries represented
- 24h
- after launch
- 127
- picks per draw
Within 24 hours of launch, more than 500 active players from over 15 countries had used the platform. More encouragingly, completion held up late in the picking flow, and engagement continued after submission as players returned for results and standings.
Making 127 picks feel manageable
A full tennis draw contains 127 matches. Showing all of them at once creates a beautiful poster and a terrible mobile interface. I divided the draw into four quarters and a finals section, so each screen has a clear local task while still preserving the logic of the bracket.
Picking is tap-only—there is no drag interaction to learn. The selected player advances into the next round immediately, progress updates continuously, and saves happen in the background. An optional auto-fill advances the better seed through every empty matchup, giving casual players a useful starting point without making choices for people who want to build the whole draw themselves.
The subtle difficulty is correction. If someone changes an early-round winner, every later pick that depends on that player may now be impossible. BracketLab walks up that player’s advancement path and removes only the invalid descendants. The user can revise one decision without rebuilding unrelated parts of the draw.
Scoring every round fairly
Correct picks are worth 1, 2, 4, 8, 16, 32, and 64 points as the tournament progresses. Doubling the value each round creates a useful balance: there are fewer opportunities to score late, but the total number of available points remains exactly 64 in every round. Early knowledge matters, and a great finals prediction can still reshape the leaderboard.
In code, the rule is compact: points = 2^(round − 1) for each correct pick. The harder part is producing a stable ranking when hundreds of brackets share similar outcomes. BracketLab sorts by points, then correct picks, then a final-score tiebreaker. Identical results share the same competition rank.
For the tiebreaker, each player predicts the final set by set. I compare that prediction with the real score using game-level distance across aligned sets, plus a 13-point penalty for every missing or extra set. Thirteen represents a full set at its largest legal distance, so predicting the wrong match length cannot accidentally beat a structurally correct score. The same validator understands the different best-of-three and best-of-five formats for the women’s and men’s draws.
Turning picks into a live competition
Submission is only the beginning of the product. Players can create private groups, share an invite link, compare brackets, and move between group and global leaderboards. During the tournament, a match ticker connects each real result to the player’s pick and shows the points gained or the path that was lost.
Picks and champion predictions stay sealed until the tournament locks. This matters socially: nobody can wait, inspect the field, and copy a rival’s strategy. The lock is checked against server time, and row-level security keeps other players’ data private rather than merely hiding it in the interface.
I treated small feedback states as part of the game. Correct picks become visibly successful, eliminated paths recede, ranks use country flags and clear numeric hierarchy, and the leader’s position feels distinct without turning the experience into a casino. The tone is competitive, but still closer to an editorial tennis special than a betting app.
Built for the tournament spike
Bracket products have an unusual traffic shape: a rush of signups before the draw locks, then repeated leaderboard reads whenever matches finish. I built BracketLab with Next.js and Supabase, keeping game logic in typed server code and the database focused on durable invariants.
The scoring layer reads normalized brackets, picks, results, players, and tiebreakers, then computes complete leaderboard rows. That expensive, viewer-independent result is cached once per data change. A lightweight privacy pass is applied afterward for the current viewer, so hiding sealed champion picks does not require rescoring the entire field on every request.
Server actions authenticate every write and enforce ownership, tournament lock times, and bracket completeness. Database constraints and triggers provide a second backstop: they reject inconsistent picks and clear dependent results even if application code fails. Reads page beyond the data provider’s default row limit, so the architecture is not quietly capped at the first thousand records.
What I took away
BracketLab was a lesson in designing for sustained participation. Getting someone to register is easy compared with getting them through 127 decisions and giving them a reason to return for two weeks. The launch numbers mattered, but the low late-stage drop-off and continued engagement were better signals that the core loop worked.
The most successful decisions joined product and engineering: dividing the draw into manageable sections, clearing impossible picks automatically, keeping every round valuable, and making live scoring fast enough to feel immediate. None of those features is ornamental. Together, they make a complicated tournament feel like a simple game.