Booking & Scheduling App Template - Chronological Implementation TODO Plan (Template repo: ai-eng-template-booking-scheduling-app) ============================================================================== INTENT ============================================================================== A starting point for booking and scheduling engagements: salons, coaches, consultants, fitness studios, repair shops, tutors, photographers, and similar small-business operators who need a public booking surface, an operator console for managing appointments, and reliable reminder + calendar-sync mechanics. The template ships with the booking flow, calendar grid, availability rules, cancellation policy, and operator console pre-wired. OUT OF SCOPE: multi-location franchise operations, marketplaces with multiple unrelated providers (use a custom build), and complex resource-pool scheduling beyond "one operator, one resource per slot". High-level summary - Goal: a forkable booking app that a small operator can launch in 2-4 weeks. - Platform target: Next.js App Router, Firebase Auth + Firestore + Cloud Functions + Cloud Storage, Stripe (optional deposit/full payment), Google/Apple/Outlook calendar sync via OAuth. - Performance/security target: every slot mutation is transactional to avoid double-bookings; reminders are idempotent. - Rough delivery estimate: 2-4 weeks per customer customization. Phase 0 - Scope freeze, product definitions, and delivery guardrails (Effort: Small) Dependencies: customer discovery workshop output. [ ] Freeze template scope: - [ ] confirm the template ships with: public booking page, service catalog, availability rules (weekly hours, blocked dates), customer self-serve account (optional), cancellation and reschedule, deposit and full-payment via Stripe (optional), email + SMS reminders, calendar sync, and an operator console. - [ ] confirm explicit OUT-OF-SCOPE: multi-location, multi-staff marketplaces, multi-resource scheduling, real-time chat. Phase 1 - Repository skeleton, tooling, and CI (Effort: Small) Dependencies: scope freeze. [ ] Standard skeleton mirroring the SaaS MVP template, plus: - [ ] timezone helper (`luxon` or `date-fns-tz`) baked in. - [ ] `pnpm test:slots` script that runs the slot-allocation test suite in isolation. Phase 2 - Design system and token foundation (Effort: Small) Dependencies: Phase 1. [ ] Tokens and primitives plus booking-specific components: - [ ] CalendarGrid (week, day, month views). - [ ] SlotPicker. - [ ] AvailabilityEditor. - [ ] BookingSummaryCard. - [ ] CancellationPolicyCard. Phase 3 - Data model and persistence (Effort: Large) Dependencies: Phase 1. [ ] Firestore collections: - [ ] `services/{serviceId}` (name, duration, price, deposit, buffer). - [ ] `availabilityRules/{operatorId}` (weekly hours, exceptions). - [ ] `blockedDates/{operatorId}/dates/{date}`. - [ ] `bookings/{bookingId}` (serviceId, customerEmail, customerName, start, end, status, paymentStatus, reminderState, calendarEventIds). - [ ] `customers/{customerId}` (optional self-serve account). - [ ] `reminderLogs/{logId}` (idempotent reminder attempts). [ ] Indexes: - [ ] composite on `bookings` for `(operatorId, start)` and `(operatorId, status, start)`. [ ] Security rules: - [ ] anonymous users may create a booking only through the `createBooking` callable (never directly). - [ ] customers can read only their own bookings. - [ ] operators can read and write everything in their scope. Potential gotchas: - [ ] do NOT allow direct client writes to `bookings`; double-booking guarantees live in the Cloud Function transaction. Phase 4 - Booking flow (Effort: Large) Dependencies: Phase 3. [ ] Public flow: - [ ] `/book` -> select service -> select slot -> enter contact details -> optional payment -> confirmation. - [ ] slots derived from availabilityRules + service duration + buffer - (active bookings overlapping the slot). - [ ] timezone handling: always store UTC in Firestore, display in the operator's timezone unless the customer overrides. [ ] `createBooking` Cloud Function: - [ ] transaction reads availability + active bookings, writes the new booking only if no overlap. - [ ] writes audit entry `booking.created`. - [ ] idempotency key derived from customer email + slot + serviceId so a retry never double-books. Potential gotchas: - [ ] daylight-saving transitions on long-running recurring bookings are a classic source of bugs; cover the DST transition in unit tests. Phase 5 - Payments (Effort: Medium, optional) Dependencies: Phase 4. [ ] Stripe integration: - [ ] support deposit-only and full-payment strategies per service. - [ ] `createCheckoutSession` callable; payment status reconciled via the `stripeWebhook` HTTP function. - [ ] cancellation policy reflected in refund logic (full refund, partial, none) and surfaced in the confirmation email. Potential gotchas: - [ ] Stripe webhooks must be idempotent; persist event IDs. Phase 6 - Operator console (Effort: Large) Dependencies: Phases 3-5. [ ] `(operator)/dashboard` shows today's bookings, upcoming week, and revenue summary. [ ] `/operator/calendar` calendar view (day/week/month) with drag-to-reschedule (writes go through `rescheduleBooking` callable). [ ] `/operator/services` to manage the service catalog. [ ] `/operator/availability` to manage weekly hours and blocked dates. [ ] `/operator/customers` to view customers and booking history. Potential gotchas: - [ ] drag-to-reschedule must verify the new slot is free in the same transaction; never trust the UI's view of availability. Phase 7 - Reminders and notifications (Effort: Medium) Dependencies: Phase 4. [ ] Scheduled Cloud Function runs every 5 minutes to find bookings within the next 24h and 1h windows. [ ] Email reminders via the configured provider (SendGrid/Resend), SMS via Twilio (optional, feature-flagged). [ ] Reminder state persisted in `bookings/{bookingId}.reminderState` so retries are idempotent. Potential gotchas: - [ ] sending the same reminder twice is the most common booking-app bug; always check the reminder state before sending. Phase 8 - Calendar sync (Effort: Medium, optional) Dependencies: Phase 4. [ ] OAuth integrations: - [ ] Google Calendar (primary). - [ ] Microsoft 365 / Outlook (secondary). - [ ] Apple iCloud (via .ics feed + CalDAV optional). [ ] On booking create/reschedule/cancel, push the change to the operator's connected calendar; store the event ID in `bookings.calendarEventIds`. Potential gotchas: - [ ] OAuth refresh tokens expire silently; surface a "Reconnect calendar" banner in the operator console when the next sync fails. Phase 9 - Observability, security, accessibility (Effort: Medium) Dependencies: Phases 4-8. [ ] App Check on all callables, CSP/HSTS configured, Lighthouse a11y >= 95, structured logs with `bookingId` correlation. [ ] Privacy: customer email and phone are stored only for the configured retention window (default 24 months) with a scheduled cleanup function. Phase 10 - Testing strategy (Effort: Medium) Dependencies: Phases 3-9. [ ] Slot-allocation unit tests cover: overlapping bookings, buffer, blocked date, DST transition, timezone mismatch, double-submit idempotency. [ ] Firestore Security Rules tests for anonymous create denial. [ ] Playwright smoke: book a slot, receive confirmation, cancel from operator side, verify reminder log skipped. Phase 11 - Customization handbook (Effort: Small per customer) Dependencies: Phases 0-10. [ ] `docs/customization.md` records, per customer: - [ ] services, durations, prices, deposits, buffers, cancellation policy. - [ ] operating hours and timezones. - [ ] payment mode (none / deposit / full). - [ ] reminder channels (email only / email + SMS). - [ ] calendar sync providers enabled. - [ ] customer self-serve account on/off. - [ ] branding and domain. Phase 12 - Public showcase integration (Effort: Small) Dependencies: this plan, ecosystem Phase 26. [ ] Register in `apps/web/src/lib/showcase.ts` with id `booking-scheduling-app`. [ ] Public staging instance deployed with synthetic services and a fake operator; embedded as a sandboxed iframe on `/showcase/booking-scheduling-app`. [ ] The preview accepts bookings only against an isolated demo Firebase project that is wiped every 12 hours. Potential gotchas: - [ ] never let the showcase preview send real SMS or real Stripe charges; always run it against test credentials.