← Back to Home

Golf Practice Plan

A 12-week structured golf practice tracker with cross-device sync and mobile-first UX.

View Live App ↗ Live
Workers KV Hono TypeScript

The Problem

Existing golf apps track scores but not structured practice. I wanted a system that runs a weekly drill program, saves progress across devices without requiring an account, works perfectly on mobile, and costs nothing to run.

No app store, no backend server, no database subscription. Just a URL I open on my phone at the range.

What I Built

A mobile-first web app that runs a structured 12-week practice program with 26 drills across putting, chipping, approach play, and driving. Each drill has a goal, scoring type, and pass threshold. Progress is tracked per-session with a confirm workflow — you enter your number, tap the checkmark, and the result is logged.

Cross-device sync uses Cloudflare KV with a PIN-based model. On first visit, you set a practice PIN (e.g., mack2026). That PIN keys your progress in KV. Open the same URL on another device, enter the same PIN, and all your history loads instantly. No account, no OAuth, no email verification.

The app went from v1.0 to v4.2 in three days — four complete architectural rewrites driven by real usage at the driving range.

Mobile view of a golf drill in progress with confirm button and scoring Practice history and stats view showing completed sessions

Architecture

┌─────────────────────────────────────────────────┐
│              Cloudflare Edge                     │
│                                                  │
│  ┌──────────────────┐    ┌────────────────────┐  │
│  │  Workers (Hono)  │───▶│  KV Namespace      │  │
│  │                  │    │                    │  │
│  │  - TypeScript    │    │  progress/[pin]    │  │
│  │  - SSR HTML      │    │  = [drills, hist]  │  │
│  │  - API routes    │    │                    │  │
│  └──────────────────┘    └────────────────────┘  │
│                                                  │
│  plan.macksportreport.com                        │
│                                                  │
│  Client:                                         │
│  - localStorage (offline fallback)               │
│  - Debounced KV sync (500ms)                     │
│  - PIN stored in localStorage                    │
└─────────────────────────────────────────────────┘
Technical Deep Dive

Session Model

On page load, confirmed drills reset to made=0, confirmed=false (new session). Unconfirmed in-progress values survive page close. History entries always append — multiple sessions on the same day produce multiple rows. This means you can practice twice in a day and see both sessions in your history.

KV Merge Strategy

On load: fetch KV data, merge with local data. KV wins on conflict (it's the authoritative source), local fills gaps (for data saved offline). This simple rule handles all edge cases: phone dies mid-practice, switch devices, clear browser data — KV always has the truth.

PIN-Based Auth

Instead of OAuth or email verification, users set a PIN on first visit. The PIN becomes the KV key: progress/[pin]. It's stored in localStorage for zero-friction return visits. This is the right pattern for a personal tool — no signup flow, no password reset, no infrastructure. The tradeoff (PINs aren't secure) is acceptable for practice statistics.

Version History: v1 to v4.2 in 3 Days

  • v1.0 — Basic drill list with local-only tracking. No sync.
  • v3.0 — Full rewrite: progress tracking model, accuracy mode, history charts.
  • v4.0 — Second rewrite: universal confirm flow for all 26 drills, session-based model.
  • v4.2 — KV sync with PIN, offline fallback, merge strategy, sync status indicator.

Each version was driven by real usage at the driving range — v1's local-only storage failed when I switched phones, so v4.2 added KV sync. v3's auto-complete was frustrating when I wanted to edit, so v4 switched to explicit confirmation.

Cloudflare Products Used

Workers — Application runtime with Hono micro-framework. Routes, SSR, and API handlers in a single TypeScript file. Zero cold starts, instant deploys.

KV — Cross-device progress sync. Progress keyed by PIN, debounced writes (500ms), offline-tolerant merge on load. Sub-10ms reads globally.

Wrangler — Single-command deploy pipeline. wrangler deploy pushes to 300+ cities. No CI/CD, no Docker, no build pipeline.

What I Learned

Career Relevance