5.5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Goal
A salon booking platform for KSA (Saudi Arabia) with Django REST API backend and React/Vite frontend. Optimized for phone-first auth (OTP via SMS/WhatsApp), Moyasar payments, Arabic locale (ar-sa), and Riyadh timezone.
Commands
Backend
# Setup (from repo root)
python3 -m venv venv && source venv/bin/activate
pip install -r backend/requirements.txt -r backend/requirements-dev.txt
cp backend/.env.example backend/.env
# Migrations and dev server (from backend/)
cd backend
python3 manage.py migrate
python3 manage.py runserver
# Seed demo data
python3 manage.py seed_demo
# Run all tests (from backend/ with venv active)
cd backend
python3 -m pytest
# Run a single test file
python3 -m pytest apps/accounts/tests/test_otp_limits.py
# Run a single test
python3 -m pytest apps/accounts/tests/test_otp_limits.py::TestClassName::test_method_name
# Run external/integration tests (hits real third-party services)
PYTEST_ADDOPTS='' python3 -m pytest -m external
Authentica E2E Testing
Set these env vars before running external tests:
AUTHENTICA_E2E=1AUTHENTICA_API_KEY=...AUTHENTICA_E2E_PHONE=...(phone that will receive OTP)AUTHENTICA_E2E_CODE=...(OTP code received)
Frontend
# From frontend/
cd frontend
npm install
npm run dev # dev server at localhost:5173, proxies /api to localhost:8000
npm run test # vitest
npm run build
Architecture
Backend (backend/)
Django project lives in backend/salon_api/ (settings, root urls, wsgi/asgi). All domain apps are under backend/apps/:
| App | Responsibility |
|---|---|
accounts |
Custom User model, phone/OTP auth, JWT tokens, locale preferences |
salons |
Salon catalog, services, staff profiles, availability windows, reviews |
bookings |
Booking lifecycle, availability/overlap validation, status transitions |
payments |
Moyasar integration (create, capture, refund), webhook reconciliation, idempotency |
notifications |
Booking lifecycle SMS/WhatsApp messages, stored for auditability |
Service layer pattern: Business logic lives in apps/<app>/services/ (not in views). Views are thin — they validate input, call services, return responses. Keep it this way.
OTP providers (apps/accounts/services/otp.py): pluggable via OTP_PROVIDER env var. Active providers: console (dev), twilio, authentica. unifonic is a scaffold. Authentica is the recommended production provider and uses a server-side OTP flow (uses_provider_otp = True) — it generates and verifies the code itself, so the DB stores a placeholder hash.
Payment gateway (apps/payments/services/gateway.py): MoyasarGateway implements BasePaymentGateway. Amounts are always in minor units (halalas). MOYASAR_SECRET_KEY and MOYASAR_PUBLISHABLE_KEY are required.
Sync-only (MVP): All external calls (OTP sends, notifications, payment gateway) run synchronously in the request path. No task queue. See docs/adr/0001-synchronous-external-calls-mvp.md.
Database: SQLite for local dev (default), PostgreSQL via DATABASE_URL env var for production. Tests use TEST_DATABASE_URL if set.
Localization: Default language ar-sa, timezone Asia/Riyadh. UserLocaleMiddleware applies per-user locale preference.
Frontend (frontend/)
React 18 + Vite app. Entry: src/main.jsx → AuthProvider wraps App.
- Routing:
react-router-domv7 with pages insrc/pages/ - Auth: JWT tokens managed via
src/contexts/AuthContext.jsx;src/components/ProtectedRoute.jsxguards private pages - API:
src/api/client.jsis the axios/fetch wrapper - Hooks: Domain logic extracted into
src/hooks/(e.g.,useSalonSearch,usePaymentForm) - i18n:
react-i18nextconfigured insrc/i18n/index.js; supportsar-saanden
Tests use Vitest + Testing Library. Setup in src/test/setupTests.js.
Key Env Vars
Backend (backend/.env):
DJANGO_SECRET_KEY,DJANGO_DEBUG,DATABASE_URLOTP_PROVIDER—console|twilio|authentica|unifonicAUTHENTICA_API_KEY,AUTHENTICA_BASE_URL,AUTHENTICA_SENDER_NAMETWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN,TWILIO_FROM_NUMBER,TWILIO_WHATSAPP_FROMMOYASAR_SECRET_KEY,MOYASAR_PUBLISHABLE_KEYNOTIFICATION_PROVIDER— defaults toOTP_PROVIDEROTP_EXPIRY_MINUTES,OTP_MAX_PER_WINDOW,OTP_WINDOW_MINUTES,OTP_RESEND_COOLDOWN_SECONDSCORS_ALLOWED_ORIGINS
Testing Conventions
- Backend tests live beside their apps:
apps/<app>/tests/test_*.py pytest.inimarksexternaltests as opt-in; default runs skip them- Frontend tests: Vitest + Testing Library; test files colocated with source (
*.test.jsx) - Minimum coverage: auth flows, booking validation, payment state transitions
ExecPlans
For complex features, use an ExecPlan (see PLANS.md for the full spec and active plan pointer). ExecPlans are living documents in docs/execplans/. The active plan is listed in PLANS.md. Update docs/risks.md when opening or closing a significant gap.
Coding Conventions
- Business logic in service layers; keep views thin
- Predictable error responses: HTTP status code +
detailfield - Comment intent, edge cases, and non-obvious business rules; skip obvious comments
- Payment and booking flows must be idempotent and auditable
- Phone auth must be rate-limited (enforced in
otp.pyviaOtpRateLimitError/OtpCooldownError)