All work
Own product · live

Weekend Golf Warrior

Live scoring, matchups and side games for a golf trip, built for phones with one bar of signal.

Role
Sole engineer
Year
2026
Stack
React 19, Vite, Firebase Firestore, Auth and Storage, Security rules, Firebase Emulator Suite, Vitest, Vercel
Demo dataTwo signed-in phones on one emulator, recorded at real speed. Scores tapped on one phone update the match on the other through live listeners. A simulated weekend.
simulated phones play a full weekend against the real rulesCounted in the repo · source
19
security-rule tests asserting allows and deniesCounted in the repo · source
100
unit test cases across 37 filesCounted in the repo · source
590

The problem

It was built for a 19-player, three-round weekend where everyone scores on their own phone on a course with bad signal. Every phone is a writer, so lost updates, stale app versions and a reload in a dead zone are the normal case.

What I built

  1. 01A 19-phone weekend simulator: each phone is a separate process running the real client data layer against the real security rules through a proxy that adds latency and dead zones.
  2. 02A rollout test that builds the previous production client and runs old and new phones on the same weekend to prove the stale-build guard.
  3. 03Scores written one field per hole with merge, which ended lost updates between scorers in the same group and queues offline.
  4. 04A server-side stale-build guard: the rules only accept a change to the old score arrays if the write also stamps a revision only the current build knows.
  5. 05A new-version banner that checks for signal and pre-downloads the bundle before a user-initiated reload, so a reload never happens mid-hole.
  6. 06All money math in one pure module, so the leaderboard and the ceremony can never disagree and settlement always sums to zero.

More screens

Demo dataLeaderboard, skins and settle-up from the same numbers, then the trip's chat.
Four-ball matchups with hole-by-hole scorecards and the banner 'All square thru 13'
Demo dataFour-ball match play, scored hole by hole from every phone.
The scorer's By-hole card for hole 13 with four players, net scores and a Next Hole button
Demo dataOne hole, the whole group, with net scores and stroke dots.
Settle Up marked Provisional: 19 players paid in, the undecided amount held back, and who gets what
Demo dataSettle-up sums back to the pot and stays provisional until every card is complete.
The group chat with reactions and automatic score alerts for a net eagle and a net birdie
Demo dataBanter, reactions and automatic score alerts. The messages were written for the demo.
The closing ceremony with confetti: the winning team, Bogey Bros, and its round-by-round points
Demo dataFinish the weekend and every phone opens the ceremony.
An official certificate of achievement for one player with gross score, net birdies and winnings
Demo dataA certificate for every player.

Decisions

Test the network, not just the code

Unit tests cannot show what happens when a phone holds bytes in a dead zone. The simulator can, so it runs the real client through a faulty network.

One handicap module

Stroke math had been copied into 27 call sites that truncated indexes and gave plus handicaps 18 extra strokes. It now lives in one tested place.

Not claimed

  • Money features only track side games. The app never holds or moves funds.
  • AI features are off in production, and there is no App Store release yet.
  • Every screen here is a simulated weekend on the Firebase emulator running the real security rules. The players and courses are the simulator's.

Links