9 KiB
9 KiB
Architecture — Desi Clans
Version: 1.0
Last updated: 2026-04-04
1. System context
┌─────────────┐ HTTPS ┌──────────────┐ SQL ┌────────────┐
│ Browser │ ──────────────► │ FastAPI API │ ◄──────────► │ PostgreSQL │
│ (React) │ │ + static │ └────────────┘
└─────────────┘ │ media │
│ └──────┬───────┘
│ │
│ optional ▼
└──────────────────────► S3 / CDN (prod media)
- Monorepo:
frontend/,backend/,docs/. - Deployment unit: API container + static frontend (CDN or same origin) + managed Postgres.
- No microservices in v1. One API process, clear router boundaries for future split.
2. Architectural principles
- API-first content — Public UI never hardcodes event copy or images.
- Thin client — Business rules (inventory, check-in) live in the backend.
- Explicit phases — Ship discovery + admin before native payments if needed.
- Boring tech — Stack locked to PRD; no extra frameworks without ADR.
- Security defaults — JWT for auth, parameterized SQL via SQLAlchemy, validated Pydantic I/O.
3. Repository layout (target)
DESI-CLANS/
├── frontend/
│ ├── public/
│ ├── src/
│ │ ├── api/ # Axios clients, types mirroring API_SPEC
│ │ ├── components/ # UI primitives + composites
│ │ ├── hooks/
│ │ ├── layouts/
│ │ ├── pages/ # Route-level views
│ │ ├── styles/ # Tailwind entry, tokens
│ │ ├── utils/ # seo, dates, formatters
│ │ ├── animations/ # GSAP contexts, ScrollTrigger setup
│ │ ├── App.jsx
│ │ └── main.jsx
│ ├── index.html
│ ├── vite.config.js
│ ├── tailwind.config.js
│ └── package.json
├── backend/
│ ├── alembic/
│ ├── app/
│ │ ├── routers/ # public, auth, admin, share, analytics, orders (future)
│ │ ├── services/ # domain logic
│ │ ├── models.py
│ │ ├── schemas.py
│ │ ├── auth.py
│ │ ├── config.py
│ │ ├── database.py
│ │ └── main.py
│ ├── scripts/ # seed, migrate helpers
│ ├── tests/
│ ├── Dockerfile
│ └── requirements.txt
├── docs/
└── README.md
4. Backend layers
| Layer | Responsibility |
|---|---|
| Routers | HTTP, status codes, dependency injection, no business logic |
| Services | Transactions, orchestration (editions, media, tickets, email) |
| Models | SQLAlchemy ORM, enums |
| Schemas | Pydantic request/response; never expose hashed passwords |
Cross-cutting
config.py— settings from environment (see.env.examplewhen added).auth.py— JWT create/verify,get_current_admin, futureget_current_user.- Migrations — Alembic only; avoid
create_allin production (dev convenience may exist temporarily).
5. Frontend layers
| Layer | Responsibility |
|---|---|
| Pages | Data loading per route, SEO hooks, layout composition |
| Components | Presentational; accept props, no direct Axios in leaf components |
| api/ | Base Axios instance, interceptors for admin token |
| animations/ | GSAP timelines registered once; respect prefers-reduced-motion |
Routing (React Router)
- Public:
/,/events,/events/:slug,/subscribe(optional dedicated page) - Admin:
/admin/login,/admin/*(protected) - Account (phase):
/account,/account/tickets/:id - Check-in (phase):
/admin/check-inor staff-only route
SEO
- Vite SPA: use
react-helmet-asynconly if needed; prefer minimal approach:- Default meta in
index.html - Per-route
document.title+ meta updates in pageuseEffect - Backend
/share/events/{slug}HTML for crawlers (already planned in API)
- Default meta in
6. API boundaries
| Namespace | Auth | Purpose |
|---|---|---|
/api/public/* |
None | Read editions, config, subscribe, outbound redirect, calendar |
/api/auth/* |
Credentials | Admin login (attendee login added with ticketing) |
/api/admin/* |
Admin JWT | CRUD editions, media, links, users, subscribers |
/api/admin/analytics/* |
Admin JWT | Click summaries |
/share/events/{slug} |
None | OG HTML for social crawlers |
/api/orders/* (future) |
User JWT | Checkout, my tickets |
/api/check-in/* (future) |
Staff JWT | Validate QR, mark checked in |
Public reads are cache-friendly (CDN Cache-Control on GET editions list with short TTL).
7. Media pipeline
- Admin uploads via multipart → service stores file.
- Local:
upload_dirserved at/media/... - Production: S3 bucket + public or signed URLs; store
file_pathkey in DB. - Optional thumbnails generated on upload (service layer); expose
thumb_urlin API.
8. Ticketing architecture (target)
EventEdition ──< TicketTier
│
Order ──────────────┼──< OrderLine (tier, qty, unit_price)
│
└──< Ticket (code, qr_secret, status, checked_in_at)
Checkout flow (native)
- Client POST order intent with tier + quantity.
- Server validates window, inventory; creates
pendingorder; returns payment session (phase B). - Webhook confirms payment → status
paid→ issue tickets with unique codes. - Email service sends QR (PNG or link to ticket page).
QR validation
- Payload:
ticket_id+ HMAC signature (server secret). - Scan endpoint: verify signature, edition match, status
issued→checked_in.
Outbound mode (per edition flag)
ticketing_mode: outbound | native- Outbound uses existing
bookmyshow_url,district_url, etc., via/api/public/goclick tracking.
9. Security
- Passwords: bcrypt via passlib.
- JWT: HS256,
ACCESS_TOKEN_EXPIRE_MINUTESconfigurable. - CORS: explicit origin list from env.
- Rate limit: add at reverse proxy (nginx/Cloudflare) for public POST subscribe and auth login.
- Admin actions audited via structured logs (user id, action, entity id).
10. Performance requirements
| Area | Target |
|---|---|
| Public GET editions | p95 < 300ms @ warm DB |
| Image delivery | WebP/AVIF where supported; width variants |
| Frontend bundle | Route-based code splitting for admin |
| DB | Indexes on slug, event_type, is_published, event_date |
| Animation | GSAP only on hero/key sections; disable heavy ScrollTrigger on mobile low power |
11. Observability
- Health:
GET /api/public/health - Structured JSON logs (request id, path, status, duration)
- Production: disable OpenAPI UI (
openapi_url = Nonewhenenvironment=production)
12. Coding conventions
Python (backend)
- Python 3.11+
- Type hints on public functions
rufforflake8+black(pick one formatter in CI)- Router functions: max ~30 lines; delegate to services
- Enums in
models.pyfor DB enums; mirror in Pydantic where needed
JavaScript (frontend)
- React 18 functional components only
- Named exports for components; default export for pages optional
- Tailwind for styling; no CSS-in-JS library
- Axios instance with
baseURLfromimport.meta.env.VITE_API_URL - Env vars prefixed
VITE_only for client-safe values
Git
- Conventional commits encouraged:
feat:,fix:,docs: - One Alembic revision per schema change
13. Implementation phases
Phase 0 — Constitution (current)
Documentation only; no new application features.
Phase 1 — Public experience + admin content
- Vite + React + Tailwind + Router
- Wire public API: home, list, detail, subscribe, outbound go links
- Admin: login, edition CRUD, media upload
- Share previews + basic SEO
- Aligns with partial backend already in repo
Phase 2 — Polish & performance
- GSAP hero + scroll sections with reduced-motion guard
- Image lazy loading, skeleton states
- Accessibility pass (focus, contrast, aria labels)
Phase 3 — Native ticketing
- DB: tiers, orders, tickets
- Attendee auth
- Checkout + payment webhook
- Ticket page + QR generation
- Staff check-in UI
Phase 4 — Hardening
- E2E smoke tests, load test on read paths
- CDN, backup strategy, runbooks
14. ADR policy
Significant deviations (new dependency, new service, auth model change) require a short docs/adr/NNN-title.md before implementation.