Buddy Cup

MVP
Next.jsTypeScriptNeon PostgresDrizzle ORMClerk AuthClaude APIOpenAI APITanStack QueryTailwind CSSSwiftUIVercel
Work with me
Coming soon to theApp Store
An arcade matchup card: two players from Hacks face two from Chunkers as pixelated NBA Jam-style portraits, with handicap-driven rating bars

122 commits in the last 90 days · 346 all-time

Run your trip. Crown your champion. Buddy Cup is a multi-tenant Ryder-Cup-style platform that brings real match-play scoring to the buddy golf trip — courses, players, tee times, matchups, live leaderboards, and the surrounding chaos, all managed from one phone.

The idea

Every buddy golf trip has the same problem: someone becomes the human spreadsheet. Tee times live in a group text, matchups on a napkin, and nobody can actually score match play with handicaps — so the "cup" gets settled by vibes. Buddy Cup replaces all of it. From signed-up to first tee shot in an afternoon: create the trip, invite your buddies, snap your scorecards, schedule your cup, and plan the surrounding chaos — flights, shuttles, dinners, the post-round bar stop — all on one shared, day-by-day timeline next to the golf.

The trip itinerary: a day's hotel check-in, three 2v2 match-play tee times with each player's handicap, and the welcome dinner
The whole trip on one day-by-day timeline.

Inside a trip

Here's what a four-day cup looks like from the inside. Pick a day: the cup score updates through that day, every match shows its result or its live status, and every player's net score for the round sits beside it. Saturday is mid-round, so four singles matches are still live.

Pinehurst Cup · sample trip

Hacks

6½

vs

Chunkers

4½

Through Sat · 10 pts left · 4 live

Pinehurst No. 4Aug 22 · Singles · live

Matches

  • 7:24 AMFinal

    10.4Ian

    VS

    Dan11.2

    Hacks win 2&1+1 Hacks
  • 7:24 AMFinal

    24.5Munley

    VS

    Mallon25.1

    Chunkers win 1 UP+1 Chunkers
  • 7:36 AMLive

    16.0Andy

    VS

    Kyle15.5

    Chunkers 1 UP thru 15
  • 7:36 AMLive

    13.2Carty

    VS

    Marino11.8

    Hacks DORMIE · 3 UP thru 15
  • 7:48 AMLive

    16.9Truant

    VS

    Lusty16.2

    AS thru 12
  • 7:48 AMLive

    14.8Fran

    VS

    Musket22.1

    Hacks 2 UP thru 10

Individual · net to par

  1. 01IanF-1
  2. 02Cartythru 15-1
  3. 03Franthru 10E
  4. 04MallonF+1
  5. 05Kylethru 15+1
  6. 06Truantthru 12+1
  7. 07Lustythru 12+1
  8. 08DanF+2
  9. 09MunleyF+2
  10. 10Andythru 15+2
  11. 11Musketthru 10+2
  12. 12Marinothru 15+3
A sample trip. Tap a day.

Signature features

Live cup standings: Hacks 8½, Chunkers 6½ with 9 of 15 matches in the books, above an individual leaderboard
The leaderboard that fits in your back pocket.
The trip feed: a posted round at Pinehurst No. 2, trash talk, and emoji reactions
Trash talk, photos, and receipts.
  • Real match-play scoring — not stroke-play with a coat of paint. The engine speaks the actual language of the Ryder Cup: DORMIE, AS, 3&2. Handicap strokes are allocated USGA-style against each hole's stroke index, net scores are compared per hole, and closeouts are detected the moment a match becomes mathematically over. Supports singles, 2v2 best ball, two-man aggregate, scramble, and house formats — with multiple handicap methods selectable per match
  • AI scorecard reader — adding a course used to mean typing 54+ numbers. Now you photograph the scorecard and Claude's vision model extracts par, stroke index, and per-tee yardage/rating/slope for all 18 holes — with validation that falls back to manual entry rather than ever writing garbage data
  • Arcade matchup portraits — players upload a photo and an AI image pipeline returns a 1994-NBA-Jam-digitizer version of them: pixelated, palette-crushed, transparent background, composited onto gold-framed matchup cards with team-color glows, CRT scanlines, and handicap-driven rating bars. Matchup reveals feel like a fight card
  • The feed — a team chat built for the trip, not for productivity. Score posts, hole-tagged photos, emoji reactions, and trash talk — auto-moderated by an image-moderation service so admins don't have to babysit
  • Live cup scoreboard — broadcast-graphics hierarchy: team total on top ("8½ – 6½, 6 points left"), per-match status cards and an individual leaderboard below, updating as holes post
  • Lazy-claim roster — the admin seeds every player slot with email, nickname, and handicap; players claim their slot on first login via magic link. The trip is fully operational on day one even if half the group never signs in

More games than the cup

A buddy trip isn't only the cup. Every round can carry its own side action, scored by the same engine and kept separate from cup points:

  • Formats: singles, 2v2 best ball, two-man aggregate, scramble, and stroke play, resolved by match play, Stableford, or stroke
  • 30 Ball and 40 Ball: each side commits a budget of balls hole by hole, with a pace rule that keeps the budget reachable and scores net against par
  • Bingo Bango Bongo, plus a game pack with Skins, Vegas, and Quota and a named Nassau preset
  • Presses: match-play side bets tracked per match, never counted toward the cup

On the course: iPhone and Apple Watch

A native SwiftUI iPhone app shares the website's Clerk sign-in and covers the trip end to end: the cup, the schedule, the feed, score entry, and even building matches and new events. An Apple Watch companion lets you pick your group and enter hole scores from your wrist, without pulling out your phone mid-round.

Build strategy

  • The scoring engine is a pure-function package: match-play math is the most algorithmically important code in the app, so it lives in its own workspace package with zero database or framework dependencies — inputs in, results out — covered by unit and property-based tests that make exotic formats safe to add
  • Multi-tenant from day one: every domain table was trip-scoped while v1 served a single real 12-man trip. That insurance paid off: the trip-creation wizard, invites, and trip kinds (multi-day trips, one-day outings, single matches) shipped as routing and forms, not a rewrite
  • Permissions in the application layer: all authorization cascades through one set of helpers — platform admin → trip admin → captain → self — so a permission rule is one function, not a policy scattered across tables
  • AI with a safety net: the scorecard reader validates its output and falls back to manual entry, and portrait generation never destroys the source photo. AI accelerates the happy path; it never gatekeeps it
  • Polling-first realtime: golf doesn't need millisecond updates. TanStack Query polling keeps the leaderboard live with a fraction of the infrastructure of WebSockets — architecture matched to the actual problem
  • Built against a real trip: the whole product is pressure-tested by an actual 12-man, 6-round cup — real handicaps, real tee times, real trash talk. Nothing ships that wouldn't survive contact with 12 opinionated golfers

Technical Stack

Next.js (App Router) with TypeScript and React Server Components — client components only where interactivity demands it. Neon serverless Postgres with Drizzle ORM (schema-as-code as the single source of truth); Clerk magic-link auth with a layered permission model. AI: Anthropic Claude (vision + extended thinking) for scorecard extraction, OpenAI gpt-image-1 for arcade portraits, Sightengine for feed moderation. UI: Tailwind CSS v4, Framer Motion, dnd-kit, and TanStack Query for server state and polling-based live updates. Vercel hosting with Vercel Blob storage, Sharp image processing, and Resend + React Email for delivery.

Planned Features

  • Trip Memoir Engine — every hole-tagged photo, score, and feed post is already structured to fuel AI-generated nightly recaps and a post-trip highlight video (Remotion-based), with narrated audio
  • GHIN integration, trophy room, and record book — season-over-season rivalry history
Work with me

Want something like this built?

I take on client work — sites, apps, AI systems, and devices. Tell me what you're imagining and I'll tell you how I'd build it.

Work with me →