Architecture
High-level architecture of the Royal Glow Salon & Spa platform.
Architecture
Royal Glow is a monolithic modular monorepo, not microservices. Strict layer boundaries give the modularity of microservices without the ops burden — and three hard conventions hold everywhere: money is integer paise, IDs are app-generated text, and business logic never imports the database or framework.
Layered monorepo
The Bun + Turborepo workspace holds five apps/packages workspaces:
Prop
Type
The codebase enforces a strict dependency direction so business rules stay testable and framework-agnostic. Each layer may only import inward.
Prop
Type
API routes are thin orchestrators: parse → validate with Zod → call business logic → return JSON. No database queries live in route handlers.
Hosting topology
The platform spans Cloudflare's edge, a Render origin, and a Cloud Run service, backed by Neon. Pick a concern below.
Cloudflare Workers (deployed via the OpenNext adapter, @opennextjs/cloudflare — not Pages, not next-on-pages) run the customer site (rgss-web) and admin portal (rgss-admin) globally, with Cloudflare KV caching the service catalog (5-min TTL) at the edge. Sub-100ms responses worldwide. Deploy with wrangler deploy / opennextjs-cloudflare deploy.
Render (Singapore) hosts the Payload CMS (rgss-cms) — a Node.js runtime, closest free region to India. The @rgss/invoicing PDF render service runs on Cloud Run.
A single Neon project with four branches (prod, pprd, test, dev). The CMS owns its own tables, disjoint from the app's Drizzle schema.
Cloudflare R2 for media (S3-compatible, zero egress). Upstash Redis + QStash for cache and queue. Ably for realtime.
Observability
Five layers, each on a free tier.
Prop
Type
All third-party browser scripts load only after explicit cookie consent and only when their keys are configured.
Conventions
These hold across the whole monorepo and are covered in depth on the Conventions page.
- Money is stored as integer paise; never floating point.
- Timestamps are
timestamptz(stored UTC, displayed IST). - Dates display as DD/MM/YYYY and currency in Indian grouping (₹1,00,000.00).
- Every external integration is a guarded extension point: with no key configured it no-ops and logs, so the whole monorepo builds and runs locally without secrets.
Related Pages
Conventions
Money, dates, layering, and the API response envelope
Tech Stack
Every technology and why it was chosen
System Design
Formal HLD and LLD documents
Was this page helpful?