← Back to work

Case study 01 — Live platform, solo-built

A four-app data platform for a sports league, from schema to sideline

Designed, built and deployed solo: tournament brackets, live standings, an offline-first scoring PWA, and a team lineup tool — all reading and writing the same governed Postgres schema.

Role
Sole developer & architect
Timeframe
10 weeks, ongoing
Scale
~24,600 lines · 4 apps
Status
Live, field-validated

1The problem

A recreational sports league was running entirely on spreadsheets, paper score sheets and group texts. There was no live way to see a tournament bracket update, no shared source of truth for standings, and — the sharpest pain point — referees on the field had no reliable way to score a game and have it show up anywhere else. Anything that needed to be "live" wasn't.

Constraint Whatever scored a live game had to work for non-technical volunteer referees, standing on a field, sometimes with patchy signal — reliability and offline support weren't optional.

2The approach

Rather than one monolithic app, I split the problem by who uses it and how they read/write data, and built four independently deployable apps sharing one data layer:

All four sit in a pnpm monorepo sharing two internal packages — a typed Supabase client factory and a shared UI kit — consumed as TypeScript source with no build step between them. The Postgres schema (internally called GRIMMERIE) is documented with a DBML/Mermaid ERD and versioned through ten hand-written, idempotent migrations — deliberately no ORM, so every change is a reviewable, reversible SQL file rather than a generated diff.

CI is deploy-gating, not deploy-owning: GitHub Actions runs typecheck and lint on every push to main, and Cloudflare Pages — five separate projects off the same repo, one per app plus a tournament-config variant — owns the actual deploy. That split kept each app independently shippable without a shared release train.

Screenshot / short demo clip of the live scoring PWA and bracket view — drop in here once captured.

3The outcome

4

apps live in production, sharing one governed Postgres schema.

10tracked migrations, no ORM
~24.6Klines of TypeScript

All four apps are live and field-validated — the scoring PWA has been used by real referees to score real games under real field conditions, not demoed once and shelved. The tournament site's config-flag pattern let a second tournament format ship from the same codebase without a fork. And because the schema was designed up front for four different access patterns, adding the lineup tool later meant zero changes to the existing three apps.

4What I'd take into a team

This project is the clearest evidence I have of end-to-end ownership with no safety net — scoping, data modelling, building, deploying and supporting real users, alone. It's also where most of my current front-end fluency comes from: I lean on dbt/SQL for the pipeline side day to day, but this is where I keep the React/TypeScript muscle live.

TypeScriptReactVite PWA / offline-firstSupabase / Postgres pnpm workspacesGitHub ActionsCloudflare Pages
← All work Next: Devon Corporation BI dashboard →