milan44.dev
← back to work

Solo product · gamescore.cards

GameScore

A production PWA for tracking board-game scores: offline-first, fast, and wired into BoardGameGeek search across 100,000+ titles — with a paid Pro tier. Designed, built, shipped and operated solo, with Claude Code as the force multiplier.

Offline
first PWA, no account
Solo
design → ship → operate
Pro
paid tier (€4.99, Lemon Squeezy)
20
curated game templates

The problem

Board-game groups keep score on scraps of paper and half-broken apps. The good ones assume you're always online; the offline ones can't find your game. I wanted something that loads instantly at a kitchen table with no signal, knows essentially every game in print, and turns a finished match into something worth sharing.

Constraints that shaped the build

  • Offline-first is non-negotiable — scoring happens where Wi-Fi isn't. All state lives on-device; there are no accounts and no cloud sync, with JSON export/import for backup.
  • Adding a game pulls metadata from BoardGameGeek's API — that lookup must be fast and must never block scoring, so each game's details are snapshotted locally the moment it's added.
  • It's a solo project with a real cost ceiling — the infrastructure had to be cheap to run and near-zero to operate.
  • A paid Pro tier means real payments, license checks and a feature boundary that can't leak.

Key decisions

I built on Nuxt 4 for a single TypeScript codebase across rendering, routing and server endpoints, with Pinia for state. The core is local-first: Dexie over IndexedDB holds matches, players and snapshotted game data, so scoring never blocks on the network. BGG search runs through a small Nuxt server route that proxies and parses BoardGameGeek's XML API; the fields that matter are denormalized into the match, so a game's name and box art stay available offline once it's been added.

The whole thing runs on Vercel — Nuxt server routes for BGG search and license verification, with Vercel KV holding Pro license keys (there is no user database). Payments are a one-time €4.99 through Lemon Squeezy, which also handles EU VAT. Pro features sit behind a server-verified license check so the boundary holds even though the app is otherwise offline-capable. Victory Cards are rendered client-side with html-to-image into shareable 1080×1920 images people actually post.

Architecture at a glance

  • Client: Nuxt 4 PWA (@vite-pwa/nuxt), installable, with a service worker caching the offline shell + assets.
  • Local data: Dexie / IndexedDB as the source of truth for in-progress and historical games — no accounts, no server DB.
  • Game search: BoardGameGeek XML API via a Nuxt server route (fast-xml-parser); results snapshotted locally on add.
  • Backend: Vercel-hosted Nuxt server routes; Vercel KV stores Pro license keys.
  • Monetization: one-time €4.99 via Lemon Squeezy; license verified server-side and fenced behind that check.
  • Victory Cards: generated client-side with html-to-image (1080×1920); Sentry for monitoring, Umami for analytics.

Where the AI workflow earned its keep

GameScore is the clearest proof of the workflow I write about: a single engineer carrying design, frontend, edge backend, data modelling and ops. Claude Code, driven by the context-engineering and agentic-orchestration setup I publish in claude-setup, is what made that scope tractable solo — planning loops for features, AI-assisted refactors with guardrails, and a typed memory system so the model kept the thread across long sessions.

Outcome

A live, production PWA with a paid tier — shipped and operated by one person. It's the answer to the only question that matters in an interview: can you take something from nothing to in-production, end to end? Here it is, and you can click it.