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 underapps/web/src/ separates routes, owned UI primitives, feature components, and framework-glue libraries.
This page covers the customer web app (
apps/web → theroyalglow.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 inapps/web/src/styles/globals.css.
Typography
Spacing & Layout
- Max content width:
1278px(max-w-[1278px]) - Horizontal padding:
px-5(20px) on mobile,px-8on desktop - Mobile-first: customer pages designed for 375px–428px first
shadcn/ui Components
Components are copy-pasted intocomponents/ui/ — you own 100% of the code. Built on Radix UI primitives for production-tested accessibility.
Key components in use:
Button,Input,Label,Select,TextareaDialog,Sheet,Popover,TooltipBadge,Card,Separator,SkeletonTabs,AccordionCalendar,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.- Homepage “Book Now” button
/?book=1deep-link (auto-opens dialog)/?book=1&utm_source=gmb(dialog + GMB attribution)/?book=1&utm_source=walkin(dialog + walk-in attribution)
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:prefers-reduced-motion:
Accessibility Standards
WCAG 2.1 AA compliance is non-negotiable. Lighthouse Accessibility = 100 is a hard CI gate.- Tab Title
- Tab Title
- Tab Title
- Tab Title
<button>for actions (never<div onClick>)type="button"on all buttons not inside a formaria-labelon 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 modesw.js— service worker for offline supportServiceWorkerRegistrar— registers the service worker on first load- Offline page at
/offline— shows when user is offline
- Service menu and prices (cached on first visit)
- Contact information and address
- Booking history (cached)
Performance Targets
Coding Conventions
- Files:
kebab-case.tsfor utilities,PascalCase.tsxfor 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