Skip to content

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 cancellationscancelled_at instead 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 .ics straight 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.