0054 — Frontends séparés par rôle (origine unique)
Date : 2026-06-17 Statut : Acté
Contexte
Le frontend est aujourd'hui une SPA unique (apps/frontend, ~2 Mo, sans lazy-loading) regroupant les quatre espaces : public, apprenante, formatrice, admin. L'audit montre une séparation déjà nette : zéro import croisé entre les pages des rôles, ~40 % de code réellement partagé (primitives UI Radix/shadcn, services/api génériques, AuthContext, tokens.ts).
Le besoin exprimé couvre les quatre axes à la fois : UX distincte par rôle, allègement du bundle, déploiements indépendants et dépôts/équipes isolés par espace. Seule une découpe en apps séparées satisfait les deux derniers ; elle est aussi un sur-ensemble des deux premiers.
L'enjeu sensible est la session : aujourd'hui le refresh token vit dans localStorage (mombiz.refresh), donc lié à l'origine. Le CORS backend est figé sur une seule origine (apps/api/src/main.ts → origin: ['http://localhost:5173']), et la redirection post-login route par rôle au sein de la même app.
Décision
Découper le frontend en 4 applications dans le monorepo, alimentées par un package UI partagé, le tout servi sous une origine unique derrière un reverse-proxy :
apps/
frontend-public/ # landing, login/register, catalogue public → /
frontend-learner/ # espace apprenante → /learner
frontend-teacher/ # espace formatrice → /teacher
frontend-admin/ # back-office admin → /admin
packages/
ui/ # @app/ui — composants, AuthContext, services génériques, tokens, types
contracts/ # (existant)
- Origine unique (
/learner,/teacher,/admin,/derrière proxy) : conserve lelocalStorageactuel (session partagée sans cookie cross-domaine), CORS inchangé en logique (une origine), risque minimal. Écarte la variante sous-domaines. packages/ui(@app/ui) : extraction unique du code partagé —components/ui(primitives),components/shared(UserSpaceLayout,TopHeader,BottomNav,ProtectedRoute,Logo,PageContainer),contexts/AuthContext,services/apigénériques (client,auth,tokens,courses,enrollments,progress,quizzes,certificates,payments),tokens.ts,types.- Services spécifiques rapatriés dans leur app :
services/api/admin.ts→frontend-admin,services/api/teacher.ts→frontend-teacher. - Mapping direct avec les branches d'intégration
frontend/public·learner·teacher·admin(cf. workflows — Branches).
Migration incrémentale :
- Extraire
packages/ui(déplacementsgit mv, la SPA actuelle l'importe — aucune régression). - Scaffolder les 4 apps (Vite +
index.html+main.tsx+App.tsxréduit à ses routes ; pages déplacées pargit mv). - Auth & CORS : rendre le CORS backend configurable (var d'env, multi-origines en dev), valider la redirection post-login en origine unique.
- Build & déploiement : scripts racine par app, config reverse-proxy, maj
operations/deployment.md. - Retirer
apps/frontend.
Conséquences
- ✅ Déploiements et cycles de release indépendants par espace ; équipes isolées alignées sur les branches
frontend/*. - ✅ Bundles par rôle (l'apprenante ne télécharge plus le code admin/formatrice).
- ✅ UX/thème par rôle conservés via les tokens
RC.*+data-role. - ✅ Session inchangée (origine unique →
localStoragevalable), pas de SSO cross-domaine à bâtir. - ⚠️ Dépendance partagée
@app/ui: un changement peut impacter les 4 apps — versionner/tester avec soin. - ⚠️ Reverse-proxy requis (dev et prod) pour router les sous-chemins vers les bonnes apps.
- ⚠️ Build/CI multi-apps (4 builds) ; coût d'outillage initial.
- Variante sous-domaines (cookie domaine parent) écartée : reportée si une vraie séparation réseau devient nécessaire.