Introduction
Welcome to the Booking Management System — a modern, multi-tenant hotel booking platform built for property managers, front-desk staff, and hospitality teams who need reliable, real-time control over their operations.
What Is the Booking Management System?
The Booking Management System (BMS) is a full-stack web application that handles the complete lifecycle of hotel operations: room management, guest bookings, invoicing, payments, expense tracking, and analytics — all within a multi-organization framework. Whether you manage a single boutique hotel or a portfolio of properties, BMS provides a unified interface with organization-scoped data isolation.
Who Is It For?
| Role | What They Do |
|---|---|
| Property Owner / Admin | Configure the organization, manage users & roles, view analytics |
| Front-Desk Staff | Create bookings, check guests in/out, manage room availability |
| Accountant | Track invoices, payments, expenses, GST filings, credit notes |
| Manager | Monitor occupancy, revenue trends, outstanding balances |
Key Concepts
Organizations
Every piece of data in BMS is scoped to an organization (orgId). An organization represents a single property or hotel. Users belong to one or more organizations and switch between them seamlessly.
Organization
├── Users (with assigned Roles)
├── Rooms (grouped by Categories)
├── Bookings (linked to Guests, Rooms, Invoices)
├── Guests
├── Invoices & Payments
├── Expenses & Vendors
└── Settings (Taxes, Email Templates, Series)Users & Roles
BMS uses a Role-Based Access Control (RBAC) model. Each user is assigned a role within an organization, and that role defines exactly which actions they can perform.
- Roles are fully customizable per organization — you define the permissions.
- A user can have different roles in different organizations.
- Permissions are checked on every API request via middleware.
Bookings
A booking is the central entity. It connects a guest to one or more rooms for a date range, and automatically generates invoices for billing.
Rooms & Room Categories
Rooms are organized into categories (e.g., Deluxe, Suite, Standard). Categories define pricing and amenities. Individual rooms within a category can be toggled available/unavailable independently.
Guests
Guest records store contact information, ID details, and booking history. Guests can be linked to multiple bookings over time.
System Architecture Overview
BMS follows a modern three-tier architecture with real-time capabilities:
graph TB
subgraph Client["Frontend (Next.js + shadcn/ui)"]
UI[React Components]
State[State Management]
WS_Client[Socket.IO Client]
end
subgraph Server["Backend (Express 5.1 on Bun)"]
API[REST API Layer]
Auth[PASETO V4 Auth]
RBAC[RBAC Middleware]
Controllers[Controllers]
WS_Server[Socket.IO Server]
end
subgraph Data["Data Layer"]
Firestore[(Firebase Firestore)]
Redis[(Upstash Redis Cache)]
Blob[Azure Blob Storage]
end
UI -->|HTTP Requests| API
WS_Client <-->|Real-time Events| WS_Server
API --> Auth
Auth --> RBAC
RBAC --> Controllers
Controllers --> Firestore
Controllers --> Redis
Controllers --> Blob
Redis -.->|Cache Layer| Firestore
WS_Server -.->|Broadcast Updates| WS_ClientHow It Fits Together
Frontend — A Next.js application with shadcn/ui components. Communicates with the backend over REST APIs and receives real-time updates via Socket.IO.
Backend — An Express 5.1 application running on the Bun runtime. Handles authentication (PASETO V4 tokens), role-based authorization, business logic, and data persistence.
Firestore — The primary database. All documents are scoped by
orgIdfor multi-tenant isolation.Redis — An Upstash Redis instance used as a caching layer. Frequently-read data (room lists, categories, dashboard stats) is cached with TTLs and invalidated on writes.
Socket.IO — Powers real-time features: instant booking updates, notification delivery, and live dashboard refreshes.
Azure Blob Storage — Stores uploaded files like guest ID documents and organization logos.
Multi-Tenancy Model
BMS implements logical multi-tenancy — all organizations share the same database infrastructure, but every query is filtered by orgId.
graph LR
subgraph Firestore
direction TB
B1["bookings<br/><small>orgId: hotel-a</small>"]
B2["bookings<br/><small>orgId: hotel-b</small>"]
R1["rooms<br/><small>orgId: hotel-a</small>"]
R2["rooms<br/><small>orgId: hotel-b</small>"]
end
U1["User (Hotel A)"] -->|orgId: hotel-a| B1
U1 -->|orgId: hotel-a| R1
U2["User (Hotel B)"] -->|orgId: hotel-b| B2
U2 -->|orgId: hotel-b| R2Key guarantees:
- Every API request includes the user's active
orgId(extracted from their auth token). - Every database query filters by
orgId— there is no way to accidentally read another organization's data. - Redis cache keys are prefixed with
orgIdto prevent cross-tenant cache leaks. - Socket.IO rooms are namespaced by
orgIdso real-time events only reach the correct audience.
What's Next?
| Guide | Description |
|---|---|
| Architecture | Deep dive into the tech stack, auth flow, and data model |
| Dashboard | Understanding the analytics dashboard and its widgets |
| Bookings | Complete booking lifecycle — create, check-in, checkout, cancel |
| Rooms | Managing room categories, individual rooms, and availability |