Case study
NavisSedes
Live system serving paid and free events with interactive seating, 10-minute holds, Stripe checkout, QR tickets, and role-based admin check-in.

Proof points
- 10-minute atomic seat holds
- Paid + free checkout paths
- Versioned seating plans (Draft → Published)
- Vitest + Playwright coverage
Problem
A church concert series needed reliable seat reservations, payments, invoicing, and door check-in — not a generic ticketing SaaS.
Approach
Next.js 16 + Prisma/Neon domain model (Venue → Plan → Seat), atomic seat holds, Stripe webhooks with mock fallback, QR tokens, admin scanner, Vitest + Playwright.
Challenge
Concurrent seat selection and hold expiry had to stay consistent under checkout races without overselling.
Trade-off
Chose optimistic locking + short holds over websockets — simpler ops, clearer failure modes, easier to test under load.
Architecture decisions
- Venue → SeatingPlan → Section → Bench → Seat
- AVAILABLE → HELD → sold/released lifecycle
- Stripe Checkout + webhook (mock fallback for local/dev)
- QR tokens without PII + staff scanner roles
How I tested this
Vitest covers domain/services; Playwright covers booking and admin flows — quality is part of the delivery pipeline, not a afterthought.
What I owned
End-to-end product ownership: seating plans, checkout, payments, tickets/invoices, role-based admin, and automated regression coverage.
What I'd do differently
Next I would add stronger observability around hold expiry/webhook retries and a staging seed that mirrors production seating density.
Product walkthrough


