Skip to content

Embedded reference demo

The React demo at /demo is an actual API consumer included in every application image. It does not import server internals or keep a second state model. Persona changes exchange a public demo persona for a short-lived, HttpOnly session cookie; every later request passes through the normal API authentication, authorization, tenant scoping, and MySQL store.

Fixture and reset model

Canonical content lives in demo-data/harbour-yoga.json. The runtime validates the file before writing it. Change that file to adjust people, locations, durations, recurring events, products, entitlements, or roster bookings.

sh
npm run build
DATABASE_URL="<mysql-url>" npm run db:migrate:runtime
DATABASE_URL="<mysql-url>" npm run demo:reset:runtime

demo:reset:runtime replaces all application state and is used for CI and pull requests. demo:seed:runtime removes and recreates only the account whose slug is harbour-yoga-demo; production demo deployment uses this mode so other sandbox accounts in the demo database remain intact.

Environment boundary

  • The real production container has DEMO_AUTH_ENABLED=false and uses the production database.
  • A second production-demo container has DEMO_AUTH_ENABLED=true, DEMO_PUBLIC_API_BASE=/demo/api, and uses the dedicated demo database.
  • Caddy sends /demo and /demo/api to that second container.
  • PRs use their isolated database and reset it before every redeploy.
  • GitHub Actions starts MySQL 8.4, migrates, resets, starts the compiled application, and captures Playwright evidence from /demo before reports are generated.

Email delivery and MobilePay are the only mocked boundaries in CI, previews, and the canonical production demo. The API still creates real payment, entitlement, and booking records in the applicable demo database.

Booking SaaS implementation documentation