- Status
- In development; first season 2027
- Role
- Sole developer (Aaron Perkel LLC)
- Timeline
- Sep 2026 – present
- Stack
- Next.js 16, TypeScript, PostgreSQL (Neon), Drizzle ORM, Auth.js, Stripe, Resend, Vercel, Vitest, Playwright
Overview
Red King Tabulation is a nonprofit that runs results for Irish dance competitions (feiseanna) — about 350 dancers per feis, three feiseanna a year. This app replaces a third-party registration service. Families register dancers into competitions, pay through Stripe, and get competitor numbers and schedules by email; feis chairs and admins handle setup, waitlists, check-in, and exports from an admin console.
How it works
Auth
Passwordless sign-in with Auth.js magic links, sent through Resend and rate-limited per address. The emailed link opens a confirm page and only signs you in on a button press, so mail scanners that prefetch links can’t burn the token. Database sessions and three roles — parent, admin, and feis chair — with chairs scoped to their own feis.
Data model
Families own dancers; a registration ties a dancer to a feis, and entries tie a registration to individual competitions. Composite foreign keys keep every entry inside its own feis, CHECK constraints guard valid states, and unique indexes enforce competitor numbers, dancing order, duplicate-dancer detection, and one active waitlist spot per family. Money is integer cents with non-negative checks.
Payments
Stripe Checkout for registration. The signed webhook is the only thing that marks a payment paid, and every event is recorded insert-on-conflict so Stripe’s retries are no-ops. Waitlisted families save a card with a SetupIntent and are charged off-session, with an idempotency key, when a spot opens. Fee rules — per-competition fees, a capped family fee, date-based late fees — live in one pure, tested module.
Capacity
A per-feis dancer cap with 15-minute holds, evaluated when it’s read rather than by a cleanup job — there’s no cron to fail.
Admin and exports
Feis setup (competitions, stages, running order, schedule, waiver), payments including cash and check, waitlist release, competitor numbers, and duplicate review. Exports to the .xlsx format the tabulation workbooks already use, plus PDF check-in sheets. Every admin change writes an audit-log row in the same transaction.
Migrations and tests
16 Drizzle SQL migrations. 79 Vitest files run against in-memory Postgres (PGlite) — fee rules, database constraints, migrations, a concurrent cap race, the webhook — plus 8 Playwright end-to-end specs.