Next.js 16, Prisma, PostgreSQL, Stripe, BullMQ, Docker
Koncertügynökség
Full-stack · In development
A production-grade ticketing platform for a concert agency's MVM Dome events. The MVM Dome has no public ticket API — the organizer runs its own inventory, gate export, and invoicing. This system is the single source of truth for sector, seat, and standing inventory: browse, hold, pay, invoice, transfer, and gate export in one stack. The buyer picks seats on a two-level SVG arena map or an EAA/WCAG-equivalent list view, holds the cart for ten minutes, pays via Stripe Checkout, and receives a named ticket with QR and PDF in their account while számlázz.hu issues the e-invoice automatically. Race-safe inventory uses a unique seat-hold index, SELECT FOR UPDATE on GA zones, and a partial unique index on sold tickets — no double-selling under concurrent on-sale demand.
Buyer → event browse (hu/en/de/sr)
→ SVG seat map or accessible list picker
→ 10-minute cart hold → Stripe Checkout
→ named QR/PDF ticket + számlázz.hu e-invoice
Super admin:
event/pricing/layout CRUD · occupancy heat map · row closures
KPI dashboard · refunds/chargebacks · audit log · gate CSV export
Stack:
Next.js App Router · Prisma/PostgreSQL 17 · Redis/BullMQ worker
Docker Compose VPS · web replicas for on-sale spikes · GitHub Actions CDDeep dive
Why a custom platform
Arena concerts at the MVM Dome need seat-level control the venue's public box office does not expose. The organizer owns the full lifecycle: inventory, pricing tiers, row open/close, named tickets, Hungarian e-invoicing, chargebacks, and a CSV export shaped for the venue's gate system. One database is the authority — not a third-party ticketing API with opaque holds.
Race-safe inventory
On-sale spikes are the hard part. Seat holds get a DB-level unique index; GA standing zones use SELECT FOR UPDATE; sold tickets sit behind a partial unique index so two checkouts cannot claim the same seat. Holds expire after ten minutes and release back to inventory automatically.
Customer flow in four languages
The storefront ships HU, EN, DE, and SR via next-intl. Accounts require e-mail verification; billing address and per-ticket holder names are collected before checkout. Paid ticket transfer lets buyers reassign a named ticket without bypassing the gate export. The accessible list picker mirrors the SVG map for EAA/WCAG-equivalent seat selection.
Super-admin operations
Operators manage events, pricing, sector layout, and row closures from a super-admin surface: occupancy heat map, KPI dashboard, refund and chargeback handling, append-only audit log, and beléptetési CSV export for the venue gate system. Admin auth runs through Better Auth with e-mail plus 2FA.
Production architecture
Next.js 16 App Router and React 19 on the frontend; server actions and Route Handlers with Zod on the backend; Prisma 7 over PostgreSQL 17. Stripe Checkout webhooks drive a state machine; számlázz.hu Számla Agent handles e-invoice and storno asynchronously via BullMQ workers on Redis. QR tickets and PDFs use pdf-lib; charts use Recharts. Docker Compose on a VPS with Caddy TLS, GHCR images, web replicas for on-sale load, and GitHub Actions CI/CD.