Skip to main content

Frontend

The frontend is server-first: components are React Server Components by default, and 'use client' is added only when browser APIs, state, or event handlers are needed. WCAG 2.1 AA and a Lighthouse Accessibility score of 100 are hard CI gates.

Component Architecture

The structure under apps/web/src/ separates routes, owned UI primitives, feature components, and framework-glue libraries.
This page covers the customer web app (apps/webtheroyalglow.in). The admin portal is a separate Next.js app at apps/admin (served from admin.theroyalglow.in, root-path routes with no /admin prefix) — its pages, admin components, and admin data helpers all live under apps/admin/src/, not in apps/web. apps/web only keeps lib/admin-redirect.ts, which 301-redirects legacy theroyalglow.in/admin/* URLs to the subdomain.

Design System

Design Tokens

Tailwind CSS v4 design tokens are defined in apps/web/src/styles/globals.css.

Typography

Spacing & Layout

  • Max content width: 1278px (max-w-[1278px])
  • Horizontal padding: px-5 (20px) on mobile, px-8 on desktop
  • Mobile-first: customer pages designed for 375px–428px first

shadcn/ui Components

Components are copy-pasted into components/ui/ — you own 100% of the code. Built on Radix UI primitives for production-tested accessibility. Key components in use:
  • Button, Input, Label, Select, Textarea
  • Dialog, Sheet, Popover, Tooltip
  • Badge, Card, Separator, Skeleton
  • Tabs, Accordion
  • Calendar, DatePicker

Booking Dialog

The booking dialog is a 4-step modal that opens over the homepage. It is never a separate page — it’s always a modal overlay.
1

Step 1 — Branch, date & time

Branch selector plus a date and time-slot picker.
2

Step 2 — Service type & category

Salon/SPA toggle and category selection (one service type per booking).
3

Step 3 — Services

Service multi-select with a running total.
4

Step 4 — Summary & submission

Review and submit the booking.
Entry points:
  • Homepage “Book Now” button
  • /?book=1 deep-link (auto-opens dialog)
  • /?book=1&utm_source=gmb (dialog + GMB attribution)
  • /?book=1&utm_source=walkin (dialog + walk-in attribution)
The dialog has a full focus trap, aria-modal="true", and Escape key handling. It uses BookingDialogProvider (React context) to share open/close state across the page.

Animation

motion (motion.dev) handles all animations:
All animations respect prefers-reduced-motion:

Accessibility Standards

WCAG 2.1 AA compliance is non-negotiable. Lighthouse Accessibility = 100 is a hard CI gate.
  • <button> for actions (never <div onClick>)
  • type="button" on all buttons not inside a form
  • aria-label on icon-only buttons
  • Visible focus ring (focus-visible:ring-2)
  • Keyboard navigation support

PWA

The app is installable as a Progressive Web App:
  • manifest.ts — app name, icons, theme colour, display mode
  • sw.js — service worker for offline support
  • ServiceWorkerRegistrar — registers the service worker on first load
  • Offline page at /offline — shows when user is offline
Offline capabilities:
  • Service menu and prices (cached on first visit)
  • Contact information and address
  • Booking history (cached)

Performance Targets

Coding Conventions

  • Files: kebab-case.ts for utilities, PascalCase.tsx for React components
  • Server Components by default — only add 'use client' when needed
  • Zero business logic in components — presentation only
  • No any — TypeScript strict mode enforced by Biome
  • Single quotes, no semicolons — Biome formatter
  • Import sorting — handled automatically by Biome
Last modified on June 29, 2026