The scorecard problem League Handicap couldn't reach
League Handicap automated the handicap math for course administrators. Attest goes after the step before it: the paper scorecard, and the person retyping it into Golf Genius by hand.

Where this stands
As of August 2026, Attest exists as a working Flutter app, admin dashboard, API, and Golf Genius extension with a signed Android release build, and active development has been paused since May while League Handicap gets the hours.
League Handicap solved the calculation. A course uploads a file of scores, the platform applies each league’s rules, and handicaps come out the other end. But that file has to exist first, and where it comes from is a golf assistant at a keyboard on a Monday morning.
Discovery
Josh Riches, the PGA Professional behind League Handicap, walked through the rest of the week. Members play. Someone in the group keeps the card. Players sign each other's cards, which is how league golf has verified scores for as long as there have been leagues. The cards come back to the pro shop in a pile. Then somebody types.
The obvious fix is an API. Golf Genius has one, and its read side is fine: seasons, events, rosters, rounds, courses, divisions, players. There is no endpoint for posting a score. Score entry happens through the Golf Genius app or the manager web interface and nowhere else, and Josh's read is that this is deliberate. Golf Genius is the system of record for tournament management and USGA posting, and it isn't going anywhere. Whatever Attest did, it had to feed Golf Genius rather than compete with it.
The rest of the constraints came from the course. League golfers skew 45 to 70 and up, and plenty of them have never installed an app to play golf. Cell coverage on a course is bad, frequently for an entire nine. And in a league's first week, maybe five of forty members will have the app at all, so any verification scheme that requires both players to be running it fails on the day it matters most.
Key Takeaway
The paper scorecard isn't really the problem. The retyping is. Once the build was aimed at that, the question became how a number gets from a golfer's head into Golf Genius with a witness attached and nobody transcribing it in between.
What We Built
Attest takes a score three ways and lands all of them in the same place. A member can score hole by hole during the round, one hole per screen, plus and minus buttons around a default of par, swipe to move on. A member who would rather just play can finish, photograph the paper card, and let Claude parse it into hole-by-hole scores to review and correct. A member with no intention of installing anything hands the card to an admin, who photographs it in the dashboard and submits on their behalf.
Verification replaces the signature. The version the product is named for is a Bluetooth handshake: the scorer taps Verify, their phone broadcasts a short-lived token over BLE, the partner’s phone picks it up, pulls the scorecard from its own local database, and the partner approves. Forty bytes out, sixty back. The scorecard itself never goes over the air. The server signs the attestation when it syncs and records which method produced it, so an admin looking at a season of verifications can tell an in-person tap from a remote approval.
That works in a league where everyone has the app, which no league is on week one. So the launch method is deliberately dumber: the verifier signs on the scorer's phone and types their name, the same choreography as passing a paper card across the cart. One phone per group is enough to start. Bluetooth and push-based remote verification turn on as adoption grows.
Then the scores have to reach Golf Genius, and there's no API for that. The last mile is a Chrome side-panel extension. The admin exports verified scorecards from Attest as an XLSX, opens the Golf Genius scorecards page they already have access to, and drags the file into the panel. The extension reads the round roster off the page, matches each row by Golf Genius handle, shows every match and mismatch before anything is submitted, and posts through the same form the admin would otherwise fill in by hand. It runs inside the admin's own browser session. No credentials are stored and no third party touches the course's Golf Genius account.
Underneath all of it: a Flutter app for iOS and Android, a Next.js admin dashboard, a marketing site, and a tRPC API over Postgres. Offline-first through PowerSync, because the back nine has no signal and the app can't stall mid-round waiting for a network. There's an Apple Watch companion in prototype, and a signed Android release build sitting one Play Console submission away from internal testing.
Picking It Back Up
Attest is paused. League Handicap is the product with paying courses on it, and that's where the hours have gone. Resuming Attest means finishing a short list, not starting over.
- Store submission. The Android release build is signed and the domain is owned. What's left is the Play Console listing, the data safety questionnaire, and a privacy route on attest.golf.
- Parsing accuracy on real cards. The photo parser needs a test set of actual scorecards from several courses, in both single-player and group formats, before it's trusted in a live league.
- Phone-based identity claim. Members with no email on file can't finish the OTP claim flow yet. The Twilio A2P campaign was awaiting approval when work stopped.
- One friendly league. The plan was always a small launch with the whole workflow intact end to end, entry through export, rather than a partial rollout.
- Pricing. Attest is meant to be sold to the course with members free, and that number is still open.
None of that is research work. It's a finish list against a codebase that runs today. When a course asks for it, or when League Handicap's roadmap walks into the same paper card, the work is there to pick back up.
Does your workflow end with someone retyping it?
That's usually where the errors and the hours are hiding. Let's take a look at yours.
Schedule a Conversation