--- name: salon-mvp-roadmap overview: High-level roadmap to bring the existing Salon Django/React codebase to a reliable MVP aligned with Phase 1 goals in AGENTS.md, plus a review of current architecture and major risks. todos: - id: backend-providers-readiness content: "Harden backend providers: implement at least one real SMS/WhatsApp provider and clarify Moyasar capture/refund behavior for MVP." status: pending - id: async-and-observability content: Decide on async task infrastructure and observability basics for OTP, notifications, and payments, and document the choice. status: pending - id: frontend-structure-and-routing content: Refactor frontend into routed pages with separated components/hooks for search, auth, booking, and payments. status: pending - id: auth-and-booking-flows content: Implement phone-first auth and end-to-end booking flows on the frontend using existing backend APIs. status: pending - id: payments-and-notifications-ux content: Integrate payment initiation and booking lifecycle notifications into user-facing flows, including success/error handling. status: pending - id: tests-for-critical-flows content: Expand backend and frontend tests to cover auth, booking, payment, and notification critical paths for MVP reliability. status: pending isProject: false --- # Salon MVP Roadmap And Architecture Review ## Purpose / Big Picture This plan reviews the current Salon codebase (Django backend, React/Vite frontend), highlights architectural and design risks, and lays out a pragmatic roadmap to reach an MVP that aligns with **Phase 1: Core MVP Reliability** in `AGENTS.md`: phone-first auth with OTP, robust booking integrity, Moyasar payments, booking lifecycle notifications, localization foundations, and tests for critical flows. The roadmap assumes a KSA-focused first launch (phone auth and Riyadh timezone defaults) with a clean path to expand later. ## Current State Summary ### Backend (Django, DRF) - **Project**: `salon_api` in `[backend/salon_api](backend/salon_api)` - `settings.py` configures `AUTH_USER_MODEL = "accounts.User"`, DRF + SimpleJWT, KSA locale defaults, and custom settings for OTP, notifications, and payments. - URLs route to app-level APIs at `/api/auth/`, `/api/salons/`, `/api/bookings/`, `/api/payments/`. - **Auth & Accounts** (`[backend/apps/accounts](backend/apps/accounts)`) - Custom `User` model with phone-first capabilities (`phone_number`, `is_phone_verified`, `preferred_language`, `role`). - Phone normalization services tuned for KSA numbers (`[backend/apps/accounts/services/phone.py](backend/apps/accounts/services/phone.py)`). - OTP domain + service layer with rate limits, cooldowns, expiry, and hashed codes (`[backend/apps/accounts/services/otp.py](backend/apps/accounts/services/otp.py)`). - Phone-first auth endpoints that issue JWT tokens on successful OTP verification, plus basic email/password registration. - Social login endpoint is a placeholder that always returns 501. - **Salons & Catalog** (`[backend/apps/salons](backend/apps/salons)`) - Models for `Salon`, `Service`, `StaffProfile`, `StaffAvailability`, `Review`, `SalonPhoto`. - Read-only APIs for salon search, services, staff, and reviews. - **Bookings** (`[backend/apps/bookings](backend/apps/bookings)`) - `Booking` model ties together salon, service, staff, customer, time window, price, and status. - `validate_booking_request` in `[backend/apps/bookings/services.py](backend/apps/bookings/services.py)` enforces staff membership, duration matching, availability windows, and overlap prevention for pending/confirmed bookings. - `BookingViewSet` in `[backend/apps/bookings/views.py](backend/apps/bookings/views.py)` applies role-based access and hooks into notifications on create and relevant status changes. - **Payments (Moyasar)** (`[backend/apps/payments](backend/apps/payments)`) - `Payment` model tracks provider, status (fine-grained transitions), amount, idempotency key, external ID, payload, and timestamps. - `MoyasarGateway` in `[backend/apps/payments/services/gateway.py](backend/apps/payments/services/gateway.py)` can create payments via HTTP but has `capture_payment`/`refund_payment` as TODOs. - `create_payment_for_booking` in `[backend/apps/payments/services/payments.py](backend/apps/payments/services/payments.py)` enforces provider choice (Moyasar only), idempotency, and maps webhook events into internal statuses. - Webhook view in `[backend/apps/payments/views.py](backend/apps/payments/views.py)` authenticates via shared secret and applies provider events idempotently. - **Notifications** (`[backend/apps/notifications](backend/apps/notifications)`) - `Notification` model records booking-related notifications and enforces uniqueness per booking/recipient/event/channel. - Services in `[backend/apps/notifications/services.py](backend/apps/notifications/services.py)` reuse OTP providers to send SMS/WhatsApp messages for booking created/confirmed/cancelled events, with localization via `preferred_language`. - Booking views call `notify_booking_lifecycle` / `notify_on_status_change` to trigger notifications for customers and staff. - **Testing** - Solid tests around: - Phone normalization, OTP rate limiting, and phone auth flows (`[backend/apps/accounts/tests](backend/apps/accounts/tests)`). - Booking integrity and overlap rules (`[backend/apps/bookings/tests](backend/apps/bookings/tests)`). - Payment idempotency and Moyasar webhook handling (`[backend/apps/payments/tests](backend/apps/payments/tests)`). - Booking notifications on create/status change (`[backend/apps/notifications/tests](backend/apps/notifications/tests)`). - `docs/risks.md` explicitly tracks several known gaps around auth, booking, payments, data/UX, and ops. ### Frontend (React, Vite) - **Structure** - Vite React app at `[frontend](frontend)` with entry in `[frontend/src/main.jsx](frontend/src/main.jsx)` and single top-level component in `[frontend/src/App.jsx](frontend/src/App.jsx)`. - No `react-router` or multi-page routing; the entire experience is one composed screen. - **Current Features** - **Salon search** - Text search field calling `/salons/?q=` via a small API client in `[frontend/src/api/client.js](frontend/src/api/client.js)`. - Renders responsive list of salons with rating, city, and phone. - **Localization/i18n** - `react-i18next` setup in `[frontend/src/i18n/index.js](frontend/src/i18n/index.js)` with `en` and `ar-sa` translations. - Locale preference stored in `localStorage`; applies `lang` and `dir` on the document. - **Payments beta** - A form in `App.jsx` that sends payment creation requests to `/api/payments/` using the Moyasar-style payload, with configurable `booking_id`, source type, token, and callback URL. - Optionally includes a Bearer token from a manually-entered access token field. - On success, can redirect to `redirect_url` and shows the raw JSON response. - **State & Tests** - All state is local to `App.jsx` via `useState`/`useEffect`; there is no centralized state management or domain hooks yet. - A single test file `[frontend/src/App.test.jsx](frontend/src/App.test.jsx)` covers hero copy and locale/RTL behavior, but not search or payments. ## Glaring Design And Architectural Issues ### Backend Risks - **Incomplete provider implementations for production-critical flows** - Twilio/Unifonic providers in `[backend/apps/accounts/services/otp.py](backend/apps/accounts/services/otp.py)` are stubs with `NotImplementedError` for send methods, yet they are the backbone for both OTP and booking notifications. - `MoyasarGateway` lacks `capture_payment` and `refund_payment` implementations, limiting payment lifecycle coverage. - **Risk**: Code reads “production ready” at the API level, but the underlying integrations are not, which could cause outages if deployed naively. - **Tight coupling between OTP and notifications** - Notification services import the OTP provider mapping and default `NOTIFICATION_PROVIDER` to `OTP_PROVIDER`, binding booking notifications to auth configuration. - **Risk**: Changing OTP providers or adding a second channel for marketing/ops notifications will be harder and could have unintended side effects. - **Synchronous IO-heavy work in request/response path** - OTP sends, booking notifications, and payment gateway calls all occur synchronously inside view methods (`perform_create`, `create`, etc.). - **Risk**: Slow or flaky providers will degrade API latency and user experience; retries and backoff are hard to implement without background jobs. - **Cross-app domain coupling without a clear orchestration layer** - `apps.bookings` depends on salons and notifications; notifications depend on accounts (OTP providers) and bookings; payments depend on bookings. - **Risk**: As you add more lifecycle rules (e.g., auto-confirm booking on payment, send reminders, handle refunds), the spaghetti of cross-imports will grow unless you introduce clearer service boundaries. - **Auth model vs login patterns** - `User.USERNAME_FIELD` is email, while phone-based JWT issuance happens via custom endpoints. - **Risk**: This split can confuse clients and admin tooling and may complicate future flows like social login or SSO unless you standardize on an identifier strategy. - **Docs drift around ExecPlans** - `AGENTS.md` references `docs/execplans/payments-moyasar.md` as the active plan, while `PLANS.md` names `docs/execplans/booking-notifications.md`. - **Risk**: Contributors may follow different “active” plans, causing architectural inconsistency. ### Frontend Risks - **Monolithic `App` component with no routing** - `App.jsx` mixes hero/search, salon listing, payments, and locale controls. - There is no `react-router` or notion of separate flows (auth, booking, profile, payments). - **Risk**: Extending to full MVP flows (auth, booking, history, management) will quickly become unmanageable without a routing/page system and domain separation. - **Domain logic embedded in UI components** - API payload construction, validation rules (e.g. for source types), and error handling are implemented directly in `App.jsx` rather than reusable hooks or service modules. - **Risk**: Code reuse, testing, and evolution (e.g., adding booking pages or admin consoles) will be painful. - **Minimal test coverage for critical flows** - Only i18n and hero copy are tested; search behavior, API integration, and payments are untested. - **Risk**: Regressions in search, booking, and payments UX will slip through as MVP grows. - **Styling & layout fragility** - `frontend/src/styles.css` uses `::root` instead of `:root`, which likely breaks intended global CSS variables or base styles. - Global CSS is tightly bound to the monolithic `App` layout. - **Risk**: Visual regressions and layout churn when introducing additional pages or components. - **Ad hoc auth token handling** - The “access token” is a free-form text field that gets persisted as `auth_token` in `localStorage` and injected into payment requests. - **Risk**: This is a placeholder pattern that does not scale to full auth (refresh tokens, logout, token rotation) and will need to be replaced. ### Cross-Cutting Risks - **Lack of async/background processing** - No Celery/RQ or similar job queue; all side effects are synchronous. - **Risk**: Scaling SMS/WhatsApp notifications, email, and payment webhook fan-out will be difficult. - **Observability and admin tooling gaps** - Errors for payments and notifications are recorded in model metadata but not clearly surfaced in logs, dashboards, or admin views. - **Risk**: Operational debugging during MVP rollout will be slower and more error-prone. - **Internationalization strategy vs future markets** - Phone normalization and defaults are tailored to KSA, which is correct for MVP, but `docs/risks.md` already notes the need to broaden later. - **Risk**: Without clear boundaries between KSA-specific logic and generic logic, future expansion may require invasive changes. ## MVP Roadmap (Aligned To Phase 1) This roadmap assumes “MVP” is equivalent to **Phase 1: Core MVP Reliability** in `AGENTS.md`, with a thin but robust frontend on top. ### Phase 0 – Architecture & Production Readiness Hardening - **Finalize critical provider implementations** - Implement at least one real SMS/WhatsApp provider (Twilio or Unifonic) end-to-end, behind the existing provider abstraction in `[backend/apps/accounts/services/otp.py](backend/apps/accounts/services/otp.py)`, and wire it into `[backend/apps/notifications/services.py](backend/apps/notifications/services.py)`. - Implement or deliberately fence off `capture_payment` and `refund_payment` in `[backend/apps/payments/services/gateway.py](backend/apps/payments/services/gateway.py)` so that the MVP either fully supports or explicitly does not support partial captures/refunds. - **Clarify and document boundaries** - Add a short architecture section in `README`/docs describing how `accounts`, `salons`, `bookings`, `payments`, and `notifications` interact, and what each service is responsible for. - Resolve the ExecPlan drift by making `AGENTS.md` and `PLANS.md` agree on the current active plan. - **Introduce minimal async infrastructure (optional but recommended)** - Decide whether MVP will ship with a task queue (e.g., Celery with Redis) or keep everything synchronous for the initial launch. - If yes, introduce a thin task layer for OTP sends and booking notifications while preserving current APIs; if not, at least add clear timeouts/logging to external calls. - **Frontend scaffolding for growth** - Introduce `react-router` and refactor `App.jsx` into route-based pages (e.g., `HomePage`, `BookPage`, `PaymentPage`, `ProfilePage`), with shared layout and navigation. - Extract salon search, payment form, and locale controls into dedicated components and hooks. ### Phase 1 – Core MVP Features (Backend + Frontend) - **Phone-first auth UX** - Backend: reuse existing phone auth endpoints; ensure error messages and rate-limit responses are predictable and localized. - Frontend: - Build OTP-based login/registration screens that drive `/api/auth/phone/request/` and `/api/auth/phone/verify/`. - Introduce an auth context (or similar) to store access/refresh tokens, current user profile, and handle logout. - Defer social login beyond MVP, but keep API surface ready for it. - **Booking search and creation** - Backend is largely ready (booking validation and role-based access); review booking serializers in `[backend/apps/bookings/serializers.py](backend/apps/bookings/serializers.py)` to ensure they expose all fields needed for frontend booking forms. - Frontend: - Build a **booking flow**: pick a salon → choose service → select staff (optional) → select date/time slot (based on availability endpoints) → confirm booking. - Add a “My bookings” page showing upcoming and past bookings, tied into the existing `/api/bookings/` endpoints. - **Payments via Moyasar** - Backend: confirm `create_payment_for_booking` contracts (inputs/outputs) are stable and documented. - Frontend: - Evolve the payments beta UI into a **post-booking payment step** that starts from a selected booking and guides the user into Moyasar’s hosted flow, then shows a status page. - Handle callback/return from Moyasar (even if via manual redirect URL in MVP) and surface payment success/failure to the user. - **Booking lifecycle notifications** - Backend already sends notifications on booking create and status changes; align messaging templates with product UX and ensure localization strings exist. - Frontend: surface notification results implicitly via booking status changes and explicit messages on the booking details page. - **Localization foundations** - Backend: ensure `UserLocaleMiddleware` and translation strings cover all user-visible errors in auth, bookings, payments, and notifications. - Frontend: expand `en/ar-sa` translations to cover auth, booking, and payment flows; verify RTL layouts on the new screens. - **Tests for critical flows** - Backend: extend tests where needed to cover new booking/payment edge cases (e.g., tying booking status to payment status if/when introduced). - Frontend: add Vitest tests for: - Phone auth screen flows (request/verify success + errors). - Booking flow (form validation, happy path, displaying server-side errors). - Payment initiation from an existing booking. ### Phase 2 – Manager Ops Lite (Post-MVP, partially covered now) - **Salon and staff management UI** - Use existing salon and staff models to build basic management pages for salon owners/managers (create/update services, staff, availability). - **Calendar views and rescheduling** - Provide calendar views for staff/managers to view daily/weekly bookings and reschedule or cancel within defined rules. - **Reviews and ratings** - Implement review submission and rating recalculation on the backend, with corresponding frontend components. - **Reporting basics** - Lightweight reports for managers (upcoming bookings, simple revenue summaries based on payment status) using existing payments data. ### Phase 3 – Scale & Compliance (Later) - **Audit logging** for admin actions and booking/payment state changes. - **PDPL/GDPR retention policies** and data export tooling. - **Observability**: structured logging, metrics, and basic dashboards for auth failures, OTP send failures, payment errors, and notification outcomes. ## Architecture Overview Diagram A simplified view of the target MVP data flow: ```mermaid flowchart LR user["User (web/mobile)"] --> frontend["ReactFrontend"] frontend --> api["DjangoAPI"] api --> accounts["AccountsApp"] api --> salons["SalonsApp"] api --> bookings["BookingsApp"] api --> payments["PaymentsApp"] api --> notifications["NotificationsApp"] accounts --> otpProviders["OtpProviders"] notifications --> otpProviders payments --> moyasar["MoyasarGateway"] bookings --> notifications bookings --> payments salons --> bookings ``` This diagram clarifies current coupling and highlights where future refactors (e.g., a dedicated messaging service or payment orchestrator) could sit. ## Validation And Acceptance For This Plan - The roadmap is accepted when: - It clearly maps current backend and frontend capabilities to the Phase 1 MVP goals in `AGENTS.md`. - It identifies the highest-risk design/architecture issues that could impede MVP reliability or future evolution. - It provides a phased, concrete sequence of work packages that can be implemented via ExecPlans (e.g., booking notifications, Moyasar payments, phone auth UX). - Each major feature area (auth, bookings, payments, notifications, localization, tests) should have or adopt an ExecPlan under `docs/execplans/` in line with `PLANS.md` before implementation begins.