Projects
Room Booking System — Symfony 7 + Nuxt 4
2026
Decoupled REST API with SPA frontend: race-condition-free conflict checking, approval workflows, iCalendar export, and 42 PHPUnit tests.
- Symfony 7
- Doctrine
- JWT
- Nuxt 4
- TypeScript
- Docker
- PHPUnit
The brief
A meeting-room booking system built as a work sample: manage rooms, check availability, create and move bookings — with admin approvals and a clean API. Deliberately built as a decoupled system: Symfony 7 REST API and Nuxt 4 SPA, connected over HTTP only.
The most interesting problem: double bookings
Two users book the same room at the same time — a classic race condition. The solution: a transaction with an overlap query before the INSERT.
SELECT * FROM booking
WHERE room_id = :room
AND cancelled_at IS NULL
AND start_at < :newEnd
AND end_at > :newStart
SQLite serializes writes (one writer at a time in WAL mode), which makes the check-then-insert inside a transaction race-condition-free. The trade-off is documented: moving to PostgreSQL/MySQL would require SELECT FOR UPDATE at room level.
Other decisions
- Stateless JWT auth (RSA-256) — horizontally scalable with no session storage; the trade-offs (token revocation, cookie scope) are recorded in the decision log.
- Soft delete for cancellations —
cancelled_atinstead of DELETE preserves history for reporting. - Approval workflows — bookings by basic users start as
pending; admins approve bookings and room change requests. - iCalendar export (RFC 5545) — every booking downloads as an
.icsstraight into the calendar. - Cross-room availability search — “which room is free Tuesday 2–4 pm for 8 people?” as a single API call.
Quality & handover
42 PHPUnit tests (repositories, controllers, services), a one-command Docker Compose setup, and a docs/ folder with Mermaid architecture diagrams, an API reference, and a requirements checklist. That is what handover looks like with me — even on small projects.