📝 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

ServiceImage/RuntimePortRôle
webNext.js 143000Frontend SSR + App Router
apiFastAPI 0.1118000REST API + auth JWT
workerCelery + RedisPDF async, emails, sync PDP
postgrespostgres:165432Base de données principale
redisredis:7-alpine6379Cache + broker Celery
caddy/traefikCoolify géré80/443Reverse 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)

PrefixRouterStatut
/api/v1/authauth.py✅ JWT access/refresh
/api/v1/clientsclients.py✅ CRUD + soft delete
/api/v1/prospectsprospects.py✅ Kanban + transitions strictes
/api/v1/eventsevents.py✅ CRUD + espaces/hébergements
/api/v1/dashboarddashboard.py✅ KPIs + calendrier + finance
/api/v1/quotesquotes.py✅ CRUD + PDF + email + IA
/api/v1/invoicesinvoices.py✅ CRUD + PDF + email + paiement
/api/v1/achatspurchase_invoices.py✅ Factures achats
/api/v1/edledl.py✅ Templates + signature + PDF
/api/v1/maintenancemaintenance.py✅ Kanban tickets
/api/v1/inventaireinventaire.py✅ CRUD
/api/v1/staffstaff.py✅ Users + planning
/api/v1/usersusers.py✅ CRUD utilisateurs
/api/v1/prestatairesprestataires.py✅ CRUD
/api/v1/parametresparametres.py✅ Articles, tarifs, espaces, gîtes
/api/v1/mediasmedias.py✅ Upload S3 + consentement
/api/v1/portailportail.py✅ Magic link + accès client
/api/v1/notificationsnotifications.py✅ CRUD + mark read
/api/v1/hebergementshebergements.py✅ Gîtes + réservations
/api/v1/searchsearch.py✅ Recherche globale
/api/v1/signalementssignalements.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)

VersionContenu
20260518_0502Initial schema (toutes tables)
20260518_1007client_id sur users
20260518_1200EDL templates
20260519_1400PDP fields + client type (assujetti)
20260520_0800date_visite_planifiee sur prospect
20260520_1000invoice_events_log
20260520_1100e-reporting fields sur invoices
20260520_1200purchase_invoices
20260520_1300signature_url sur quotes
20260520_1400client prestataire intérêts
20260520_1500signalements clients
20260520_1600plan_coords
20260520_1655programme + todos événement
20260521_0426portal_access_tokens
20260521_1000quote_recap_ia
20260521_1100space_id sur EDL

Dépendances externes

ServiceUsageTier
Backblaze B2 EUStockage fichiers + PDFs (S3 compat)~0.50€/mois
ResendEmails transactionnelsFree (3000/mois)
CloudflareDNS + CDN + TLSGratuit
HetznerVPS prod (Coolify)~7-15€/mois
Mistral AIGénération devis + emailsPay-per-use
SUPER PDPFacturation électronique B2BÀ confirmer
GHCRRegistry Docker imagesGratuit

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
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