- Entry lists
- Race weekends
- Sessions
- Standings
- Marshal signup
- Circuits
- Reservations
- Stripe Connect
- Gear ledger
- Messaging
- ADR-governed
- Apache-2.0
- 97Prisma models
- 58Migrations, deployed on build
- 213Vitest suites
- 11GitHub Actions workflows

STAGE 01Overview
Paddock operations, as software.

A club season runs on entry lists, licence numbers, emergency contacts, session timetables, marshal rosters and who has paid. Most of it lives in spreadsheets, group chats and email chains. Spartan replaces those with one source of truth that a team administrator, a championship secretary and a circuit operator can all sign into.
Four kinds of organisation share the platform. Race teams keep rosters and respond to rounds. Championships own divisions, rounds with practice, qualifying and race sessions, entry confirmation, standings, documents, gear and messaging. Circuit operators manage venues, surfaces, operating hours, schedule blocks, reservations and card payments. Anyone can host a signup event with role-limited slots for drivers, marshals, scrutineers and officials.
The engineering is as deliberate as the product: every mutation is a Server Action behind Zod, every decision that shaped the architecture is a numbered record in the repository, and the release pipeline runs quality gates, smoke tests, deployment validation and uptime checks on a schedule.
Entry lists
Drivers and crew with licence numbers, contacts and emergency details; email invitations with unique signup links.
Race weekends
Rounds with practice, qualifying and race sessions, circuit and scrutineering details, and Going / Not going / Maybe from every entrant.
Marshal signup
Signup events with per-slot capacities that are never oversold, priority windows for members, FIFO waitlists with claim windows.
Gear ledger
Pooled and tagged inventory, team requests, allocations, custody handoffs and an immutable activity ledger with an email outbox.
Circuits
Venues with surfaces, operating hours, schedule blocks, reservations, lesson offerings and Stripe Connect payments.
Decision records
Twelve ADRs, linted and integrity-checked in CI, from Server Actions as the mutation surface to motorsport-only scope.
STAGE 02Decisions
Written down before built.

| RANK | ADR | Decision | Why |
|---|---|---|---|
| 1ST | 0001 | Record decisions as versioned markdown in git | Reviewable, diffable, linted |
| 2ND | 0002 | Server Actions as the primary mutation surface | One validated path for every write |
| 3RD | 0003 | PostgreSQL only through Prisma on Neon serverless | No raw SQL; checked in CI |
| 4TH | 0004 | MUI as the primary component library | Accessible, themeable, dense |
| 5TH | 0005 | Bun as the development and CI toolchain | Fast installs, one runtime |
| 6TH | 0006 | League gear as ledger projections with an outbox | Auditable custody, durable email |
| 7TH | 0007 | Canonical venue reservations for occupancy | One truth for who holds a surface |
| 8TH | 0009 | Delegate authority through scoped role grants | Chief marshals without super admins |
| 9TH | 0010 | Object storage through a provider seam | S3 or Vercel Blob, signed reads |
| 10TH | 0011 | Race weekends as rounds with sessions and open volunteer signup | The motorsport shape of a weekend |
| 11TH | 0012 | Motorsport-only platform | One domain, done properly |
STAGE 03Under the hood
Three flows that carry a weekend.
A round from creation to confirmed grid, a signup event from slots to waitlist, and the gear ledger that knows where every helmet is.

> From a date to a confirmed grid
Create the round
Circuit, paddock and scrutineering details, then sessions: practice, qualifying, race, each with its own time and notes.
Invite the entry list
Every team member on the round's entry list is emailed; a Going, Not going or Maybe lands instantly on the admin's summary.
Accept the waiver
Round waivers are versioned; an acceptance is recorded per entrant before the weekend.
Open marshal signup
Volunteer needs with capacities and credentials; assignments and reminders go out on a cron.
Enter results
Race results per session feed the championship standings and the day sheet.
Pieces · LOOT
- RaceRound · RaceSession
- RaceEntry · RaceResult
- RoundWaiver · Acceptance
- VolunteerNeed · Assignment
- RSVP · Invitation
- /api/cron/rsvp-reminders
- day-sheet
> A SignUpGenius that cannot oversell
Define slots
Thirty drivers, forty marshals, four scrutineers, eight officials: per-slot capacities enforced under concurrent registration.
Choose visibility
Private, invite-only by email, link-only with a regenerable unguessable link, or public with rollup onto circuit and association pages.
Run priority windows
Members register first; when a phase opens to the public, the waitlist makes FIFO offers with time-boxed claim windows and a cron backstop.
Take payment
Venmo, Zelle, cash instructions with paid, unpaid and waived tracking, or online cards through Stripe Connect with refunds.
Form the day
Grid and marshal-post formation from signups with reserves, session rotations, posted entry lists and a participants-only media gallery.
Pieces · LOOT
- SignupEvent · SignupSlot
- EventRegistrationPhase
- EventInvitation · EventManager
- EventGame · Participant
- EventMediaItem
- Stripe Connect
- /api/cron/event-waitlist
> Where every item is, and was
Catalogue and stock
Pooled stock per storage location and tagged units with their own identity.
Request and allocate
Teams raise needs; administrators approve and allocate from pool or unit, each as a command with a projection.
Hand over
Custody handoffs record who holds what, including partial returns.
Pledge in kind
A public wishlist takes pledges without money, photos or QR codes; receipts land in inventory.
Notify durably
Every gear email goes through an outbox with retry and reminder sweeps.
Pieces · LOOT
- GearCatalogItem · GearUnit
- GearPoolStock · StorageLocation
- TeamGearNeed · Command
- GearAllocation · Handoff
- GearWishlist · Pledge
- GearActivity ledger
- NotificationOutbox
STAGE 04Key screens
From the landing page to the day sheet.
The front door
A marketing site in the same build: the problem, the four kinds of organisation, how it works in three steps, and a free signup. Pricing is honest: the core is free and provider-portable by decision.
- Features, pricing, security and docs pages
- MDX documentation with guides and an API reference
- Umami analytics, no advertising

A championship dashboard
Divisions, teams, upcoming rounds, open invitations and messages for one championship, with role-scoped navigation for administrators, team administrators and members.
- LeagueUser roles per championship
- Scoped role grants for chief marshals and coordinators
- Public association page with schedule feed

A race round
Sessions in order, the circuit, waiver status, the entry list with each entrant's response, volunteer needs and the day sheet.
- Practice, qualifying, race sessions
- Entry confirmation summary
- Marshal assignments and reminders

Standings
Derived from race results per session, per division. Age-gated where a championship configures it, so junior classes publish participation without a points table.
- Results feed standings
- Per-division tables
- STATS_MIN_AGE_LEVEL gate

The calendar
A grid on a desktop and a list on a phone, across every team and championship a member belongs to, with an ICS feed for the association.
- Responsive grid and list
- ICS export per association
- Sessions, practices and signup events together

Platform admin
User moderation with an approval kill-switch, and an audit log of every write across the platform.
- approved as a suspension switch
- AuditLog per mutation
- Rate-limit buckets per action

STAGE 05Pit wall
Built for the paddock.
Mobile first by design: a marshal confirms from the post, a team administrator checks the grid from the pit wall.

Dashboard on a phone

A round on a phone

Calendar on a phone

Standings on a phone

Landing on a phone
STAGE 06Engineering
What keeps it honest.
Quality gates5/5
- Type-check, lint and Vitest on every push
- A raw-SQL check that fails the build on a bypass of Prisma
- ADR lint, integrity and review-date checks
- Smoke tests and deployment validation after a release
- Weekly uptime monitoring and version checks
Security5/5
- Zod on every form and action input
- bcrypt at cost 12; JWT sessions in HTTP-only cookies
- Rate-limit buckets on sign-in and sensitive actions
- Email verification and an approval kill-switch
- Signed, expiring reads from private object storage
Stack19/99
- Next.js 16
- React 19
- TypeScript
- MUI v7 · Emotion
- Tailwind v4 (marketing)
- Prisma 7
- Neon Postgres
- Auth.js v5
- Zod
- Bun
- Vitest
- Sentry
- Stripe Connect
- AWS SES · Brevo · Mailchimp
- S3 · Vercel Blob
- dnd-kit
- date-fns
- MDX
- Umami
Operations5/5
- Migrations deploy during the Vercel build
- Provider seams for email and storage
- Five cron routes for reminders, waitlists, gear and batches
- Release workflow tags and publishes from main
- Docs site under /docs from MDX

STAGE 07More screens
The rest of the paddock.
GAME CLEAR!


