Back to Work

THE M4JORS Sweepstake • Personal

A golf pool that started as a spreadsheet and a group email. Six years later, it's a real-time web app with automated scoring, an admin panel and 67 entries at the last count.

The M4jors is a golf sweepstake I've been running since 2020, timed around the four Major golf championships each year. The format came from my Dad, who'd been part of a similar competition with colleagues in America. He sent me it and I immediately wanted to run my own version.

The rules are specific, which is part of what makes it interesting: five players per team, one must come from the world's current top 5, the worst-performing pick is automatically dropped, but if two or more of your picks miss the cut your team is eliminated entirely.

The email that started it all

There wasn't one breaking point. There was a slow accumulation of friction: manual work that scaled badly, a frontend (spreadsheet) that looked terrible on mobile and processes that depended entirely on me being available to run them. The pool grew from 18 participants in 2020 to the mid-40s by 2022 entirely by word of mouth but the backend hadn't kept pace.

No budget and only my own personal time. Users ranging across age and technical comfort, most accessing everything on their phones. An event that runs four times a year, four days at a time, with a hard deadline I couldn't move. And real stakes — people paid money and would notice immediately if scoring was wrong. Participants weren't shy about telling me when something wasn't working either.

I was also learning as I built. Phase 1 was a spreadsheet because that's what I knew. Phase 5 is a React app with Firebase and a live ESPN API integration. Each version had to run a real competition while I worked out what came next.

Phase 1 was pure necessity: get something working. I built formulas so player scores cascaded through to every entry that had picked them and sent nightly email updates summarising the standings that I had manually input myself.

Phase 2 moved team submission to a Google Form — better for me, no real difference for participants other than a nicer interaction than over email. Score entry was still manual each night.

Phase 3 came out of a constraint. The 2022 Masters coincided with a holiday in Morocco. I wasn't going to manually update scores from my phone between day trips, so I automated the backend before I left: IMPORTHTML pulling the ESPN leaderboard into the spreadsheet, a Google Apps Script running on a timer updating every five minutes. I came back from Morocco and the spreadsheet had run itself the whole time.

Phase 4 addressed the mobile problem. A large shared spreadsheet is objectively bad on a phone. I built a basic frontend reading from Google Sheets via API, deployed through Firebase. Finally, participants could check standings on their phones in a more responsive and reliable way. One manual pain point survived: the day 2 cut still required me to swap formulas for every player who'd missed it. Depending on the field, this could mean dozens of manual cell changes.

Phase 5 changed everything. I replaced the Google Form, the spreadsheet, the scraper and the basic frontend with a proper React app, a live ESPN API integration, a real admin panel and an invite-only access model — built and documented like a product, not a side project.

Google Form entry
Google Sheet

The Google Form entry — functional, but no validation or guardrails

The spreadsheet that ran four years of competitions — nightly manual updates until Morocco changed that

The current version is a React app backed by Firebase: Firestore, Google Sign-In auth, Cloud Functions for the ESPN field sync, deployed as a Progressive Web App (PWA). Live scores pull from ESPN's public API every 60 seconds — no scraping, no intermediary server, no manual intervention.

The entry flow puts the rules first, deliberately. People pay real money. They should understand the format before they pick. The leaderboard handles cut detection automatically, state-changes eliminated teams, shows a live prize estimate per entry and expands to show your team as well as which of your five picks was dropped.

The access model was a deliberate call: invite-only, Google Sign-In for authentication, manual approval before anyone can enter. I get a push notification when someone new signs up. It keeps the pool private without me maintaining a password list or fielding reset requests from people who use the app once a year.

The entry flow
Admin panel

The entry flow — five steps, no spreadsheet

The admin overhead that used to take hours now takes minutes

The pool has grown from 18 participants in the first-ever competition in 2020 to 67 entries at the 2026 Masters — entirely by word of mouth, no promotion. The trajectory maps almost exactly to the product improvements: growth was slow while the experience was a Google Form and a spreadsheet and accelerated once the app launched.

18

First competition (2020)

67

2026 Masters

+34%

Growth since app launch

My admin overhead during a live tournament went from a couple of hours a day to near zero. I set a tournament ID, click sync, open submissions and the app runs for four days without me. That matters — the manual version was starting to feel like an obligation. The automated one feels like something I'm proud of.

Live leaderboard during tournament

The leaderboard during the most recent live tournament — updated every 60 seconds, no intervention required

I'd have committed to the frontend rebuild sooner. The gap between having a solid automated backend (Phase 3) and shipping the proper app (Phase 5) was longer than it needed to be. I ran Phase 4 through multiple tournaments knowing it wasn't good enough, because building Phase 5 required time investment and upskilling that I kept deprioritising.