Product DesignFull-StackSupabaseReactAPI Integration

Sunday Money

A self-serve fantasy golf platform. It replaced seven years of broken spreadsheets and ran a full season across all four Majors.

2026·Design, development and product·View live
Landing, sweepstakes framed as a social ritual, not a product

Landing, sweepstakes framed as a social ritual, not a product

Outcome

Season one ran all four Majors: 246 players across 9 countries, 35 captain-created leagues, 474 entries and 2,844 picks. All of it word of mouth, none of it marketed. 43% of players came back for another Major and a core group played all four, which is the number I actually care about. A launch headcount says people tried it. Coming back says it worked. Built solo in evenings and weekends with Claude Code.

246

Players in season one

4

Majors run end to end

43%

Came back for another

9

Countries

Live leaderboard. DataGolf scores syncing every 5 minutes

Live leaderboard. DataGolf scores syncing every 5 minutes

Pick flow. 6 golfers plus a wildcard for tiebreakers

Pick flow. 6 golfers plus a wildcard for tiebreakers

Captain admin. Fees, deadlines and payment tracking, no handholding

Captain admin. Fees, deadlines and payment tracking, no handholding

Wildcard countback, the third tiebreaker layer, all at the DB level

Wildcard countback, the third tiebreaker layer, all at the DB level

Entries view. Captains can see who's paid and who hasn't

Entries view. Captains can see who's paid and who hasn't

Design decisions

01

Design me out of the loop

Seven years of running it by hand made the constraint obvious: any flow needing me caps the product at the leagues I can babysit. The captain owns everything (league creation, entry fee, deadline, invite code, payment tracking) and there is no admin path back to me. Ten of the sixteen Masters leagues came from people I have never spoken to.

02

The leaderboard is a Sunday-afternoon object

People check this standing in a kitchen or on a course, not at a desk, usually for ten seconds while something else happens. Mobile is the primary design, the live position is the first thing on screen, and everything explanatory sits below it. Scores refresh on a five-minute sync so the number is current without the page fighting the reader.

03

Make the tiebreaker legible, not just correct

Three layers of tiebreak (5th pick, 6th pick, wildcard countback) is exactly the kind of rule that starts arguments in a group chat. Resolving it in the database was the easy half. The harder call was surfacing why a tie broke the way it did on the leaderboard itself, so the result explains itself and the captain never has to adjudicate.

04

Money looks local or it does not get paid

Entrants across eight countries will not chase an unfamiliar payment method for a tenner. Currency auto-detects from the captain's country and the payment options shown are the ones that region actually uses (PayPal, Venmo, Zelle, IBAN, BSB) rather than a single global default. Payment conversion landed at 85% with no chasing from me.

Process

I made captains fully self-serve. A captain creates a league, sets the entry fee and deadline, gets an invite code and tracks payments. I never touch it, so the platform grows without me as the bottleneck. Ten of the sixteen Masters leagues came from people I have never spoken to. It now runs three formats off one engine: pick six and count the best scores, a sweepstake draw, and a salary cap where every golfer is priced on form. Scoring syncs live and resolves withdrawals, cut lines and a three-layer tiebreaker (5th pick, 6th pick, wildcard countback) at the database level, with a monitor that emails me if a sync stalls mid-round. Currency detects from the captain's country and payment methods surface by region (PayPal, Venmo, Zelle, IBAN, BSB). Vite, React and TypeScript on Vercel, Supabase for auth, database, RLS and edge functions, branded email through Resend.

Context

I ran the office Masters sweepstake on a spreadsheet for seven years. It broke every Saturday, scores went missing and it could not scale past one league. The leaderboard was a Google Sheet I updated by hand between meetings. I wanted something that runs itself across a whole season and lets anyone start a league without me.