Skip to content

PRD 01 — Workspace Foundation

Status: draft · Priority tier: P0 · Size: L · Depends on: existing auth/profile (email-OTP + Google login, JWT, user profile)

1. Summary

The base every other module hangs off: the business workspace and its locations (with rooms and equipment), opening hours, holidays, taxes, staff with roles and a permission tree, staff shift hours / resource availability, and the admin shell (sidebar, top bar, dashboard with an onboarding checklist). Nothing else (classes, bookings, sales) can be created until a location, room and staff exist, so this module is the critical path.

2. Problem & goals

Problem: a studio owner needs to describe the business once (where, when, who, tax) and then give staff only the access they need. Goals:

  • A new owner reaches "first bookable slot possible" (location + room + staff + shift) in under 15 minutes using the checklist (measure: time from signup to checklist all-done).
  • Every settings page reachable in 1 click from the settings hub; every dashboard checklist tile in 1 click.
  • Permission checks enforced server-side on 100% of new routes (CLAUDE.md: protected only via use: [auth] group). Non-goals: billing/subscription plans, payment providers, notification templates, waivers, wallet, membership rules, checkout rules (separate PRDs); multi-business "Organisation" (Out).

3. Users & roles

  • Owner: full access, created at signup; cannot be deleted or demoted.
  • Admin (system role): all permissions, assigned by the owner.
  • Custom-role staff (manager, front desk, instructor): subset defined by the permission tree.
  • Customer: no access to this module (sees location, hours and holidays on the storefront, PRD elsewhere).

4. Scope

In (v1)

  • must: Business info (name, slug, logo, contact, address, currency, timezone).
  • must: Locations with draft/active status, address, weekly opening hours, rooms (facilities) with capacity.
  • must: Staff list + add-staff wizard, role assignment, availability-for-booking flag, staff statuses.
  • must: Roles list and permission tree (view / edit per node), system Admin role.
  • must: Shift hours: assign staff to location, weekly shifts with start/end and assigned appointment services.
  • must: Admin shell: collapsible sidebar, top bar, profile menu, dashboard with Upcoming today.
  • should: Opening-hours exceptions: holidays (closed or special hours) per location.
  • should: Taxes (one per country, tax-inclusive pricing flag).
  • should: Equipment (name, location, quantity) and resource availability (weekly, facility/equipment).
  • should: Onboarding checklist with auto-complete and dismiss; dashboard quick links; trial days-left badge.
  • should: Single-day shift edit/delete, delete-all-shifts, shift end rules.
  • could: Floating WhatsApp button option, announcement banner, "what's new"/support cards, global search, staff public-profile fields (skills, hobbies, bio), location amenities/transport/video. Later (v2+)

  • Custom roles gated by plan (pricing tier: TBD); extra-staff gating (pricing tier: TBD).

  • Staff detail tabs (class, ratings, notes, assigned appointments) depend on their owning modules. Out

  • Organisation / multi-business linking (beta in recon; not observed beyond a landing page).

  • Billing, monthly statements, cancel-plan flow (separate PRD, plan model undecided).
  • Vendor live-chat bubble (use own support link).

5. User stories

  • US-01-01 As an owner, I want to enter my business details and currency/timezone, so that prices and times are correct everywhere.
  • US-01-02 As an owner, I want to add a location with opening hours and rooms, so that classes and appointments have a place.
  • US-01-03 As an owner, I want to mark holidays or special hours per location, so that customers know when I am closed.
  • US-01-04 As an owner, I want to define a tax, so that prices can include or add tax.
  • US-01-05 As an owner, I want to invite staff by email with a role, so that they log in with their own account.
  • US-01-06 As an owner, I want to build custom roles by ticking permissions, so that front desk cannot see finances.
  • US-01-07 As a manager, I want to set each instructor's weekly shifts and the services they work, so that only available staff can be booked.
  • US-01-08 As a manager, I want to set when each room and equipment item is available, so that appointments do not double-book.
  • US-01-09 As a new owner, I want a checklist on the dashboard, so that I know what to set up next.
  • US-01-10 As front desk, I want today's upcoming bookings on the dashboard, so that I see who is arriving.

6. Functional requirements

ID requirement priority evidence
FR-01-01 Business profile: logo, name, unique store slug, registered name, reg no, industry, contact email/phone/WhatsApp, address, currency, timezone; read-only business ID must S121
FR-01-02 Currency and timezone are required; changing currency after sales exist is blocked or warned must S121 (rule is our addition)
FR-01-03 Settings hub listing every settings page grouped; one click per page; breadcrumb on sub-pages must S120, F50
FR-01-04 Location CRUD with status draft/active; wizard steps About, Media, Details, Address, Timing, Rooms, Amenities; Save as draft at any step; Next disabled until step valid must S122, S122b, F52
FR-01-05 Location required fields: name, description, one image (2:1 crop), validity (lease) from/to, address line1/city/zip; slug auto from name must F52
FR-01-06 Weekly opening hours per location (7 days, closed flag, default Mon-Sun 08:00-17:00, apply-to-all) must S122b step 5
FR-01-07 Rooms (facilities) per location, optionally grouped by level: name, capacity, description, internal note, image, status must S122, S08j
FR-01-08 Amenities list, transport directions, optional video on a location could S122
FR-01-09 Holidays: description, one or more locations, optional "include online classes", closed all day or special hours, single date or range, notify-customers flag (default on) should S130, S130b, F55
FR-01-10 Holidays never cancel existing bookings; banner states this; bookings during a holiday are still listed should S130
FR-01-11 Tax: one tax per country; name, percentage, optional registration number; edit/remove with confirm; flag "prices include tax" should S123, S123b, F51
FR-01-12 Equipment: name, optional display name, location, quantity, assigned services should S124, S124b
FR-01-13 Resource availability: per location, tabs facility/equipment, weekly grid, assign resources then set availability per day should S131, S131b
FR-01-14 Staff list with filters location/role/availability, status tabs (staff, invited, locked, deactivated, draft), columns name, role, last login, invited by, availability must S140
FR-01-15 Add-staff wizard: account (name, email, role, available-for-booking), contact (mobile), personal (gender), employment (title, start date, type, default location), website display (on/off, photo, skills, bio); progress indicator; save as draft must S144, F53
FR-01-16 Staff email is login identity; invitation email via existing email-OTP flow; staff signs in with OTP or Google must S144; existing auth
FR-01-17 Staff statuses: draft, invited, active, locked, deactivated; deactivation keeps history and removes login must S140
FR-01-18 Staff detail page: account, basic, personal, employment, display-on-website, emergency contact; tabs for classes/ratings/notes/appointments filled by other modules should S146
FR-01-19 Roles list (name, type system/custom, created by/on, user count); system Admin undeletable must S141, S145
FR-01-20 Role editor: name + permission tree, each node with View and Edit; ticking Edit on parent ticks view+edit on children; unticking edit keeps view; edit implies view must S143, S143c, F54
FR-01-21 Permission tree mirrors sidebar and settings pages one-for-one (see section 11); new modules register their nodes must recon permission matrix
FR-01-22 Roles in use cannot be deleted until users are reassigned must our addition
FR-01-23 Custom-role creation and extra staff may be plan-gated; failure shows a clear banner (pricing tier: TBD) could F53, F54
FR-01-24 Shift hours: pick location, assign staff to location, weekly grid Mon-Sun per staff must S142, S195-S197
FR-01-25 Weekly shift editor: per-day on/off, multiple shifts per day, copy-to-days, assigned appointment services per shift, start immediately/next week/custom date, end on date or after N weeks must S198, S198b-d, F71
FR-01-26 Single-day shift edit/delete from grid cell; delete-all-shifts for a staff member should S199, S199b-c
FR-01-27 Staff selectable for an appointment only if they have a shift covering the slot and the service must 08 gapfill note
FR-01-28 Sidebar: collapsed icon rail, hover/pin expands with labels and business name; items filtered by the user's view permissions must S05_sidebar, S01
FR-01-29 Top bar: search (could), trial days-left badge, profile menu with greeting, profile (existing), logout should S04
FR-01-30 Dashboard: greeting, Upcoming today (filter all/class/appointment; lists bookings), quick links must S01
FR-01-31 Onboarding checklist tiles: create location, set staff, create pricing plan, create class, create schedule, set up payment; each 1 click to target; tile auto-hides when data condition met; collapse and dismiss; card hidden when all done should S01, S01c, F01
FR-01-32 Dashboard announcement banner and what's-new / support cards, content from config could S01
FR-01-33 Floating WhatsApp button toggle for storefront could S121
FR-01-34 All settings forms: Save disabled until dirty and valid; success toast; unsaved-changes guard should recon pattern

7. Screens

Modelled on original S-IDs; each has loading (skeleton), empty, filled, error states.

  • Shell: sidebar, top bar, profile menu (S01, S04, S05_sidebar).
  • Dashboard (S01): empty = "no bookings yet"; checklist visible/collapsed/dismissed/complete.
  • Settings hub (S120).
  • Business info (S121).
  • Locations list + wizard (S122, S122b); empty state with add button.
  • Taxes list + drawer (S123, S123b); Equipment list + drawer (S124); Holidays list + drawer (S130); Resource availability (S131).
  • Staff list, wizard, detail (S140, S144, S146).
  • Roles list, editor (S141, S143, S145).
  • Shift hours grid, assign-staff drawer, weekly shift modal, day modal (S142, S195-S199). Our shell uses existing web/ layout patterns; follow profile form pattern for forms.

8. Flows

Flow A, first run (target: 10 clicks plus typing to be bookable): Dashboard tile "create location" -> wizard -> publish -> tile "set staff" -> add staff -> assign to location -> set weekly shift. Flow B, add tax: Settings > Taxes > Add > name + % > Save (original ~5 clicks; target equal). Flow C, add role: Roles > Add > name > tick > Add (target 5 clicks + ticks). Flow D, shift: Shift hours > pick location > Assign staff > tick > Assign > pencil > Set weekly shift > Apply (original ~8; target 7 by defaulting end rule to "no end"). Edge cases: no location yet (dependent selects show hint with link instead of an empty dropdown, fixing a dead end seen in the original); duplicate slug; duplicate tax country; deleting a location with future sessions blocked; last owner cannot be removed; staff email already exists.

9. Data model

  • Business: id, short_code, name, slug (unique), logo, legal_name, reg_no, industry, email, phone, whatsapp, floating_whatsapp, address, country, currency, timezone, plan, trial_end (plan fields guess).
  • Location: id, business_id, name, slug, description, contact, images, status (draft/active), valid_from, valid_to, address fields + geo, amenities[], transport[].
  • OpeningHours: location_id, weekday, open, close, closed.
  • Room: location_id, level, name, capacity, description, note, image, status.
  • Equipment: location_id, name, display_name, quantity, service_ids.
  • ResourceAvailability: resource_type, resource_id, location_id, weekday/date, start, end.
  • Holiday: id, description, location_ids[], include_online, closed|special hours, date_from, date_to, start/end time, notify.
  • Tax: country, name, percent, registration_no; business.prices_include_tax.
  • User (existing): extend with staff profile (title, gender, employment fields, bio, show_on_site, available_for_booking, status).
  • StaffLocation: staff_id, location_id (default flag).
  • Role: id, name, type, permissions (map node_key -> none/view/edit).
  • Shift: staff_id, location_id, weekday or date, start, end, service_ids[], effective_from, ends_on or ends_after_weeks.
  • OnboardingState: dismissed flag per user/business; tile completion derived, not stored. Guess: permissions stored as JSON map; node keys are strings registered in code.

10. Business rules & edge cases

  • Timezone is per business; all times stored UTC, shown in business timezone.
  • A location must be active with at least one room before a class session can be scheduled there.
  • Edit permission requires view; server rejects edit without view.
  • Holidays override opening hours for the dates; special hours replace them.
  • A shift cannot overlap another shift of the same staff on the same day.
  • Staff assigned to no location cannot be given shifts.
  • Deactivated staff stay on historic bookings; future-session reassignment is flagged on deactivate.
  • Pages need skeletons: original hydrates slowly (3-8 s); target < 1 s p75 for settings pages.

11. Permissions

Nodes (each View / Edit), derived from recon matrix: Home; Schedule (no-staff, own, other calendars); Services (Classes, Appointment, Access, Courses each with bookings/definition/settings, plus "override restricted plan"); Pricing plans; Customers (+details, wallet, referrals, groups, tags); Sales (view/create/edit/refund/void etc.); Reports; Customer centricity; Marketing; Promo codes; Online store; Settings (each settings page, including Users, Roles, Shift hours). Owner and Admin: all. Default custom roles: none shipped in v1 (open question). Only users with Settings > Roles Edit can change roles; no one can edit their own role.

12. Acceptance criteria

  • AC-01: Given no location, when the owner opens the dashboard, then the checklist shows a create-location tile; after the location is saved as active, the tile disappears without reload.
  • AC-02: Given a role with Customers View only, when that user calls a customer write endpoint, then the API returns 403.
  • AC-03: Given a role editor, when I tick Edit on a parent, then all children show View and Edit ticked; when I untick Edit, View remains.
  • AC-04: Given a holiday for location L on date D with notify on, when saved, then existing bookings on D remain and affected customers are queued for email.
  • AC-05: Given a tax for the business country, when I add a second for the same country, then I get a validation error.
  • AC-06: Given staff with a Mon 09:00-16:00 shift for service X, when booking X on Mon 17:00, then that staff is not offered.
  • AC-07: Given an invalid wizard step, then Next is disabled and the missing field is named.
  • AC-08: Given a user without Settings > Roles view, then Roles is hidden from the settings hub and the route returns 403.

13. Dependencies & open questions

Depends on: existing auth/profile. Consumed by: every other PRD (location, room, staff, roles). Open:

  • Plan gating of custom roles/extra staff/locations (not decided; pricing tier: TBD).
  • Global search behaviour was disabled in the recon; not observed.
  • Result of Save on business info/checkout not exercised in recon; validation rules (slug format, reserved words) are our guess.
  • Staff status "Invited/Locked" transitions not observed; lock rule is a guess.
  • Original tile 6 on the checklist was hidden/conditional; unknown.
  • Should resource availability and shifts be appointment-only, as in the original, or also constrain classes?
  • Default custom roles to ship.

14. Evidence

See evidence/evidence.md.