Problem
The project started as a database management course assignment: a normalized MySQL schema for an event-ticketing platform, with triggers, stored procedures, and views enforcing business rules at the database layer. That schema had no front end and nothing deployed. The goal afterward was to turn it into a real, running application: a public site people could browse, an admin surface with real CRUD, and an actual ticket-purchase flow backed by a payment provider, not a mock.
Approach
The build ran as 9 phases: API, auth, frontend, payments, AWS deployment, and CI/CD. Each one was tested against the live running stack, not assumed to work from code review alone.
The backend is Express + TypeScript over the original MySQL 8 schema, with JWT-based auth for login/register, session-aware nav, and route protection on both the API and frontend. An admin role gets full CRUD on events, venues, tickets, and categories, enforcing real business rules: capacity limits, status gating, and blocks on suspended users. The public side is a Next.js 14 (App Router) + TypeScript + Tailwind frontend for browsing and filtering events by category, with detail pages showing live pricing and capacity.
Ticket purchasing is a reservation-based flow with a 15-minute hold: a Stripe PaymentIntent is created on reservation, confirmed via webhook, and presented through a themed Stripe Payment Element (test mode) rather than a redirect to Stripe's hosted page. Overbooking is prevented with row-level locking and transaction-scoped capacity checks inside MySQL, verified under concurrent load rather than just single-request testing.
Deployment is Docker Compose for both local dev and production, running on AWS EC2 behind nginx with Let's Encrypt TLS. GitHub Actions builds and pushes images to GHCR on merge to main, and the EC2 host pulls and redeploys automatically — no manual SSH-and-restart step.
Outcome
Eventify is live at eventify.social: public browsing, an authenticated purchase flow, and an admin back office, all running on a deployed, CI/CD'd stack. The database layer that started as the course deliverable still does the heavy lifting on correctness. Capacity is guaranteed by MySQL transactions, not application-level checks, and that logic is now wrapped in a real application people can actually use.