SlateCourt - Badminton Venues & Games
A mobile-first PWA for Sydney badminton — a 54-venue directory with live court availability aggregated from the venues' own public booking pages, a game ledger with bill-splitting, and a friends-and-groups social layer. A personal, non-commercial demo, soft-launched invite-only with my own playing circle.

Find a court. Remember the good ones. Settle up after.
Most venues have no booking API, so Slate never pretends to book for you — it shows what is genuinely open, sends you to the venue to book, then turns the game itself into the product: who came, what it cost, who has paid, what gear was used. Bilingual (en/zh), installable, and gated behind personal invite codes.
- Stack
- Next.js 16
- TypeScript
- FastAPI
- Python
- PostgreSQL
- Redis
- Better-Auth
- Cloudflare Workers
- Docker
- Category
- Full-stack
Why This Exists
A real product for a real circlePersonal Use Only
Demo · Invite-onlySlateCourt is a personal, non-commercial demo built for my own playing circle — registration requires an invite code. The availability feature reads only the public, log-in-free booking pages the venues themselves publish, at a low, cached cadence, and every result links back to the venue's own booking site. No venue data is republished or sold, and the project is not affiliated with any venue or booking provider.
At a Glance
By the numbers- Venues
- 54
- Live-availability Venues
- 16
- API Endpoints
- 91
- DB Migrations
- 26
- Notification Types
- 11
- Languages
- 2
Across the Stack
Seven dimensions- FE
Frontend PWA & interface
- Next.js 16
- TypeScript
- TanStack Query v5
- openapi-fetch types
- Tailwind + shadcn/ui
- PWA · offline
- BE
Backend Typed API
- FastAPI
- Python 3.14
- SQLAlchemy 2.0 async
- Pydantic v2
- 91 endpoints
- DB
Data Persistence & cache
- PostgreSQL 18
- Alembic · 26 migrations
- Redis 7
- UUIDv7 + audit columns
- ID
Auth Invite-gated
- Better-Auth
- passkey + magic link
- email + password
- JWT verified by FastAPI
- LV
Availability Scrape pipeline
- Cloudflare Worker
- 2 platform adapters
- APScheduler hot/warm
- Redis slot grids
- QA
Testing Quality gates
- pytest · 84 files
- mypy + ruff
- Playwright E2E
- Alembic drift check
- OPS
DevOps The layer that ships everything
- Docker
- Dokploy
- Traefik
- Postgres 18
- Redis 7
GitHub Actions- ruff
- mypy
- pytest
- typecheck
- build
- deploy
See It Live
Desktop · Mobile

How Live Availability Works
Scrape pipelineMost venues publish no API, but their public booking pages render date-parameterised HTML any visitor can open. Adding a venue is configuration, not code.
Trade-offs
Decisions that heldA game ledger, not a booking engine
Next.js + FastAPI split monorepo
Better-Auth up front, JWT verified behind
Reading public pages via a Cloudflare Worker
Want the full walkthrough?
Happy to talk through the architecture, the decisions, and the trade-offs behind this build.


