A full-stack event ticketing platform that allows organizers to create and manage events, attendees to purchase tickets, and staff to validate tickets using QR codes β all secured with Keycloak and JWT authentication.
flowchart TD
User[User Browser]
Frontend[React Frontend]
Keycloak[Keycloak Auth Server]
API[Spring Boot REST API]
DB[(PostgreSQL)]
QR[QR Code Service]
%% Authentication
User -->|Login| Frontend
Frontend -->|OIDC Login| Keycloak
Keycloak -->|JWT Access Token| Frontend
%% Authorized API Calls
Frontend -->|JWT in Authorization Header| API
API -->|Validate JWT & Roles| Keycloak
%% Organizer Flow
API -->|Create / Update Events| DB
API -->|Manage Ticket Types| DB
%% Public Events
Frontend -->|Browse Published Events| API
API -->|Fetch Published Events| DB
%% Ticket Purchase Flow
Frontend -->|Purchase Ticket| API
API -->|Pessimistic Lock TicketType| DB
API -->|Create Ticket| DB
API -->|Generate QR Code| QR
QR -->|Store QR Code| DB
%% Attendee Flow
Frontend -->|View Tickets| API
API -->|Fetch Tickets & QR Codes| DB
%% Staff Validation Flow
Frontend -->|Scan QR / Manual Code| API
API -->|Validate Ticket| DB
API -->|Store Validation Result| DB
-
Organizer
- Create, update, publish, and delete events
- Manage ticket types
- View and manage owned events
-
Attendee
- Browse and search published events
- Purchase tickets
- View owned tickets & QR codes
-
Staff
- Validate tickets (QR code or manual entry)
- Multiple ticket types per event
- Secure ticket purchasing with pessimistic locking
- QR code generation per ticket
- Manual & QR-based ticket validation
- Prevents duplicate validation
- Keycloak for authentication & authorization
- JWT-based stateless API security
- Role-based endpoint access
- Custom JWT role converter
- List published events
- Full-text search (PostgreSQL
tsvector) - Public event browsing without authentication
- Modern React UI
- Role-based dashboards
- QR code scanning
- Responsive & clean design
- Java 21
- Spring Boot
- Spring Data JPA
- Spring Security (OAuth2 Resource Server)
- MapStruct
- PostgreSQL
- H2 (testing)
- ZXing (QR code generation)
- React 19
- Vite
- TypeScript
- Tailwind CSS
- Radix UI
- React Router
- OIDC (Keycloak)
- QR Scanner
- Keycloak
- Docker & Docker Compose
The platform models:
- Users (Organizer / Attendee / Staff)
- Events
- Ticket Types
- Tickets
- QR Codes
- Ticket Validations
Relations include:
- One organizer β many events
- One event β many ticket types
- One user β many tickets
- One ticket β one QR code β many validations
Each purchased ticket generates a unique QR code, stored in the database and linked to the ticket.
- Ticket is valid
- Not previously used
- Validation recorded in the database
- Invalid QR code
- Already validated
- Rejected by backend validation rules
GET /api/v1/events
POST /api/v1/events
GET /api/v1/events/{id}
PUT /api/v1/events/{id}
DELETE /api/v1/events/{id}
GET /api/v1/published-events
GET /api/v1/published-events/{id}
GET /api/v1/published-events/search
POST /api/v1/events/{eventId}/ticket-types/{ticketTypeId}/tickets
GET /api/v1/tickets
GET /api/v1/tickets/{ticketId}
GET /api/v1/tickets/{ticketId}/qr-codes
POST /api/v1/ticket-validations
- PostgreSQL (no volume β easy reset)
- Adminer
- Keycloak (with persistent volume)
docker compose up -d- DTO-based validation
- Centralized
@RestControllerAdvice - Consistent error response format
- Safe Optional handling in service layer
- DTOs for every request & response
- Stateless REST API
- Pessimistic locking for ticket purchase safety
- Orphan removal for ticket types
- Separate published vs organizer event flows
- MapStruct for clean mapping