SaaS / Restaurant Operations
White-label Restaurant Platform
An Angular and NestJS platform for restaurant websites, menus, events and table reservations, with configurable branding and an administration dashboard.
- Context
- Independent
- Source Code
- Public source
Engineering scope
Engineering Scope
Stack: Angular 22 · TypeScript · NestJS · MongoDB · RxJS · SCSS
Inspect the source ↗Restaurant operators use this platform to manage branding, menus, events and reservations. The Angular 22 website and administration dashboard share a NestJS API and MongoDB database. The implementation covers draft editing, reactive configuration and restaurant-specific access checks.
The public repository includes implementation and regression tests. Production deployment and concurrent reservation handling are outside this case study.
01 / Configuration
Keep the last valid configuration during a refresh
A failed configuration refresh should not erase the restaurant identity already displayed. A settings form also should not publish changes before the server accepts them.
I used httpResource to load configuration and linkedSignal to retain the last valid value during a refresh. I update shared configuration only after a save succeeds, so an unaccepted edit does not change the public website.
The page may show older configuration while a request is pending or has failed. Loading and error state remain available separately. Regression tests cover first-load failures, retries and failed saves while checking that the existing palette is retained.
02 / Draft editing
Edit a draft and publish it only on Save
An editor bound directly to shared content can mutate the public page before Save, making Cancel unreliable. Generic content methods can also accept a payload for the wrong section if their types are too broad.
I kept editor changes in a separate draft and added tests confirming that Cancel leaves the original content unchanged. I typed saveSection with a section key and RestaurantContent[K], so the selected section determines the accepted payload.
The generic method catches mismatched section payloads in TypeScript. Server validation checks incoming HTTP data, while draft isolation lets users cancel an edit without changing the shared page state.
03 / Color contrast
Choose readable text for configurable brand colors
A restaurant can choose a light or dark brand color. A fixed foreground can become unreadable when the background changes.
I used a reactive effect to apply accepted colors as CSS custom properties. To choose readable foregrounds, I linearize the RGB values, calculate relative luminance and compare black and white contrast ratios for primary and button fills.
The calculation covers text on primary and button fills. Other surfaces, focus indicators and validation messages still need to be checked as part of the complete theme.
04 / Authorization
Check restaurant access on the server
An authenticated user should not gain access to a different restaurant merely by changing a client-side identifier. A configurable website needs an authorization boundary as well as a theme.
I resolved restaurant configuration from the request host and checked the authenticated user against that restaurant on the server. The authorization function verifies the JWT and user record; the client interceptor adds bearer credentials only to /api/ requests and handles expired sessions.
Host configuration is part of this authorization path, and protected endpoints need to apply the same checks. Client route guards control navigation; the server decides whether the user can access the restaurant’s data.
05 / Reservations
Confirm deletion before changing the reservation list
Removing a reservation from the screen before knowing the result can make the administrator believe an operation succeeded when the API rejected it.
I used httpResource for bookings and messages and derived their loading and error state in ReservationsStore. I remove a reservation from the local list only after the delete request succeeds, avoiding an optimistic change that would need rollback.
The list waits for the server response, avoiding an optimistic update that would need to be reversed on failure. Other administrators’ views still need a refresh to reflect the change.
System flow
Content management across the stack
- 01
Administration
An administrator edits restaurant content through the Angular dashboard.
- 02
Resource API
The NestJS API delegates requests to server-side resource handling and authorization.
- 03
Persistence
Mongoose models connect the API to MongoDB.
- 04
Public website
The Angular customer interface presents restaurant information, menus, and events.
Evidence & further reading