Aller au contenu principal

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.tsorigin: ['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 le localStorage actuel (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/api gé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.tsfrontend-admin, services/api/teacher.tsfrontend-teacher.
  • Mapping direct avec les branches d'intégration frontend/public·learner·teacher·admin (cf. workflows — Branches).

Migration incrémentale :

  1. Extraire packages/ui (déplacements git mv, la SPA actuelle l'importe — aucune régression).
  2. Scaffolder les 4 apps (Vite + index.html + main.tsx + App.tsx réduit à ses routes ; pages déplacées par git mv).
  3. Auth & CORS : rendre le CORS backend configurable (var d'env, multi-origines en dev), valider la redirection post-login en origine unique.
  4. Build & déploiement : scripts racine par app, config reverse-proxy, maj operations/deployment.md.
  5. 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 → localStorage valable), 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.