📝 Note
personal/prieure/architecture
fastapinextjscoolifyhetznerceleryaiportalpdp
Architecture — prieure
Liens : Decisions · Journal
Vue d’ensemble
Monorepo fullstack déployé sur Hetzner VPS via Coolify + Docker Compose.
apps/web/ Next.js 14 App Router (port 3000)
apps/api/ FastAPI + Celery worker (port 8000)
packages/types Types TypeScript partagés web↔api
packages/ui Composants shadcn/ui customisés
infra/docker/ Dockerfile.api + Dockerfile.web
.github/workflows/ build-api.yml + build-web.yml (GHCR)
Composants principaux
| Service | Image/Runtime | Port | Rôle |
|---|---|---|---|
| web | Next.js 14 | 3000 | Frontend SSR + App Router |
| api | FastAPI 0.111 | 8000 | REST API + auth JWT |
| worker | Celery + Redis | — | PDF async, emails, sync PDP |
| postgres | postgres:16 | 5432 | Base de données principale |
| redis | redis:7-alpine | 6379 | Cache + broker Celery |
| caddy/traefik | Coolify géré | 80/443 | Reverse proxy + TLS auto |
Flux de données
Browser → Traefik (Coolify) → Next.js (SSR/SSG)
→ FastAPI /api/v1/...
→ PostgreSQL (asyncpg)
→ Redis (cache/sessions)
→ Celery worker
→ WeasyPrint → PDF → Backblaze B2
→ Resend SMTP (emails + magic links)
→ Mistral AI (devis IA, email IA)
→ SUPER PDP (sync e-invoicing)
Modules API (routers actifs)
| Prefix | Router | Statut |
|---|---|---|
/api/v1/auth | auth.py | ✅ JWT access/refresh |
/api/v1/clients | clients.py | ✅ CRUD + soft delete |
/api/v1/prospects | prospects.py | ✅ Kanban + transitions strictes |
/api/v1/events | events.py | ✅ CRUD + espaces/hébergements |
/api/v1/dashboard | dashboard.py | ✅ KPIs + calendrier + finance |
/api/v1/quotes | quotes.py | ✅ CRUD + PDF + email + IA |
/api/v1/invoices | invoices.py | ✅ CRUD + PDF + email + paiement |
/api/v1/achats | purchase_invoices.py | ✅ Factures achats |
/api/v1/edl | edl.py | ✅ Templates + signature + PDF |
/api/v1/maintenance | maintenance.py | ✅ Kanban tickets |
/api/v1/inventaire | inventaire.py | ✅ CRUD |
/api/v1/staff | staff.py | ✅ Users + planning |
/api/v1/users | users.py | ✅ CRUD utilisateurs |
/api/v1/prestataires | prestataires.py | ✅ CRUD |
/api/v1/parametres | parametres.py | ✅ Articles, tarifs, espaces, gîtes |
/api/v1/medias | medias.py | ✅ Upload S3 + consentement |
/api/v1/portail | portail.py | ✅ Magic link + accès client |
/api/v1/notifications | notifications.py | ✅ CRUD + mark read |
/api/v1/hebergements | hebergements.py | ✅ Gîtes + réservations |
/api/v1/search | search.py | ✅ Recherche globale |
/api/v1/signalements | signalements.py | ✅ Retours clients |
Pages Frontend (App Router)
(auth)/login
(dashboard)/
page.tsx (dashboard KPIs)
reservations/ (FullCalendar)
evenements/ [id]/ (espaces, hébergements, planning, documents, medias, programme, todos, prestataires)
prospects/ [id]/
clients/ [id]/
comptabilite/ (devis, factures, achats, tresorerie)
hebergements/ (etats-des-lieux/[id])
maintenance/
inventaire/
staff/
prestataires/
mediatheque/
plan/ (éditeur 2D)
notifications/
parametres/ (articles, tarifs, espaces, gites, plan, utilisateurs)
portail/ (magic link auth)
page.tsx (accueil)
documents/ programme/ hebergements/ edl/ medias/ maintenance/ todos/ prestataires/ access/
Modèle de données (tables)
users, clients, prospects
events, event_spaces, gite_reservations
spaces, gites
quotes, invoices, purchase_invoices
edl (etats_des_lieux), edl_templates
maintenance_tickets, inventaire_items
staff_planning, prestataires, event_prestataires
articles, tarifs
medias (event_medias), signalements
plan_coords, programmes, todos
portal_tokens, notifications
Migrations Alembic (16 versions)
| Version | Contenu |
|---|---|
20260518_0502 | Initial schema (toutes tables) |
20260518_1007 | client_id sur users |
20260518_1200 | EDL templates |
20260519_1400 | PDP fields + client type (assujetti) |
20260520_0800 | date_visite_planifiee sur prospect |
20260520_1000 | invoice_events_log |
20260520_1100 | e-reporting fields sur invoices |
20260520_1200 | purchase_invoices |
20260520_1300 | signature_url sur quotes |
20260520_1400 | client prestataire intérêts |
20260520_1500 | signalements clients |
20260520_1600 | plan_coords |
20260520_1655 | programme + todos événement |
20260521_0426 | portal_access_tokens |
20260521_1000 | quote_recap_ia |
20260521_1100 | space_id sur EDL |
Dépendances externes
| Service | Usage | Tier |
|---|---|---|
| Backblaze B2 EU | Stockage fichiers + PDFs (S3 compat) | ~0.50€/mois |
| Resend | Emails transactionnels | Free (3000/mois) |
| Cloudflare | DNS + CDN + TLS | Gratuit |
| Hetzner | VPS prod (Coolify) | ~7-15€/mois |
| Mistral AI | Génération devis + emails | Pay-per-use |
| SUPER PDP | Facturation électronique B2B | À confirmer |
| GHCR | Registry Docker images | Gratuit |
Auth flow
Utilisateurs internes
POST /api/v1/auth/login → access_token (15min) + refresh_token (7j, httpOnly cookie)
GET /api/v1/... → Bearer access_token → Depends(get_current_user)
POST /api/v1/auth/refresh → nouveau access_token
Portail client (magic link)
Admin → POST /api/v1/portail/send-portal-link → email → Resend (lien magic)
Client → GET /portail/access?token=<UUID> → cookie session → accès portail
portal_tokens table → token UUID réutilisable (pas single-use)
Services AI
# apps/api/app/services/
ai_quote.py # Mistral : contexte événement → lignes devis + récapitulatif
ai_email.py # Mistral : contexte événement + tone → draft email client