Architecture
Architecture de haut niveau et principaux modules techniques.
Vue d'ensemble
Yayaw utilise le Next.js App Router avec des routes préfixées par la locale
(/en, /fr). Le produit est organisé autour d'un tableau de bord multi-tenant
authentifié, d'un runtime CMS public et d'un plan de contrôle (control plane)
réservé au serveur pour l'automatisation de confiance.
Parcours de lecture clés:
- Tableau de bord pour le shell applicatif authentifié et les racines de sections
- Catalogue des pages, Catalogue des sections et Modèles de données CMS pour le runtime CMS
- Aperçu de la facturation pour les abonnements, les achats ponctuels et l'accès au code
- Plan de contrôle pour MCP et l'automatisation
Principaux blocs de construction
Frontend et routage
- Routes applicatives dans
src/app - Middleware de locale et routage dans
src/i18netsrc/lib/middleware - Blocs UI du tableau de bord sous
src/blocks - La configuration partagée de routes/navigation pilote la barre latérale, le menu de commande, les fils d'Ariane et la visibilité des routes.
Convention de nommage du tableau de bord
- Le titre de page définit le sujet de la page (par exemple:
Media,Billing,Authorization). - Le titre de bloc définit l'entité gérée et implique l'action (par exemple:
Assets manager). - La description de bloc explique, en une phrase courte, ce que les utilisateurs peuvent faire dans ce bloc.
Authentification et autorisation
- Configuration Better Auth dans
src/config/better-auth.config.ts - Intégration serveur auth dans
src/lib/server/services/auth/auth-drizzle.ts - Les clés API Better Auth sont activées pour l'accès au plan de contrôle avec
des permissions explicites
control-plane:read,control-plane:write,control-plane:publishetcontrol-plane:admin - Les capacités d'administration Better Auth incluent l'usurpation contrôlée et
le provisionnement SCIM (
@better-auth/scim) - L'onboarding par invitation d'organisation privilégie la clé d'accès (passkey) et utilise des tokens d'onboarding d'invitation hachés, stockés hors de la table d'invitations Better Auth
- Synchronisation des rôles d'organisation dans
src/lib/server/services/authz - Le modèle d'autorisation interne reste dans Yayaw (Permix + Drizzle):
- groupes et appartenances
- bindings scopés explicites dans
group_role_bindings - policies de rôles dans
role_policies
- Moteur d'autorisation explicable dans
src/lib/server/authz:authorizeDetailed(...)pour autorisation/refus + chaîne de décisioncan(...)comme façade booléenne utilisée par les routes et les actions
- Actions serveur personnalisées d'administration AuthZ pour liste/détail/bulk/simulate/explain/audit dans
src/lib/server/actions/authz/authorization-admin-actions.ts
Couche de données
- Configuration Drizzle dans
src/lib/db - Schémas organisés par domaine:
- schéma Better Auth
- schéma d'autorisation
- schéma système
- Les parents de la barre latérale du tableau de bord sont des tableaux de bord
de section navigables.
/dashboard/contentest le tableau de bord de santé du CMS; il résume l'inventaire de contenu de l'organisation active, l'état de publication, le stockage média, les données CMS et les jobs de génération IA avant que les utilisateurs ne descendent dans les écrans de catalogue dédiés./dashboard/admin,/dashboard/organization,/dashboard/settingset/dashboard/testsont aussi des racines de section valides; les parents de barre latérale ne pointent donc jamais vers des pages masquées ou manquantes. Le shell de tableau de bord utilise des fils d'Ariane shadcn et une barre de navigation de section partagée dérivés de la hiérarchie de barre latérale filtrée; cette barre liste uniquement les routes enfants de la section dashboard active. - Médiathèque d'organisation dans le schéma système:
media_foldersetmedia_assetssont scopés par organisation- les ressources média sont stockées dans un stockage objet public (bucket
media) avec unpublicUrlpersisté - le stockage est adossé à un fournisseur: Supabase reste supporté et le stockage compatible S3 couvre MinIO, S3 et les déploiements de type R2
- les assets visuels peuvent stocker des miniatures WebP générées pour l'affichage en médiathèque; les miniatures manquantes sont générées opportunistement lors du listage de la médiathèque et ne comptent pas dans le quota de téléversement utilisateur
- les actions serveur appliquent toujours
scope: { orgId }et rejettent les mutations inter-organisations - lecture/listage disponibles pour les membres d'organisation, téléversement/édition/suppression réservés aux rôles manager ou admin
- les quotas de téléversement viennent de la configuration à l'exécution de facturation des plans (par fichier et stockage total de l'organisation)
- la génération d'images du page-builder stocke les sorties WebP OpenAI par le même pipeline de téléversement/persistance média
- Catalogue de sections réutilisables dans le schéma système:
ui_section_registry_itemsstocke l'identité stable des sections built-in, globales et d'organisationui_section_revisionsstocke le JSONSectionDefinitionV1validé + les diagnosticsui_section_publicationsstocke l'état de cycle de vie et le pointeur vers la dernière révision publiée- les définitions de section stockent uniquement les ids de renderers, les recettes, les références de composants et les bindings
- les pages utilisent des références
PageSectionpour suivre la dernière section publiée - la création de section par IA utilise un shell réutilisable de plan workbench:
src/components/ai/plan-workbench/*- tiroir adaptateur de section:
src/blocks/dashboard/content/sections/block-ai-create-drawer.tsx - endpoint de plan streaming:
src/app/api/ai/blocks/plan/route.ts - endpoints de runs/jobs persistés (resume/poll/cancel):
src/app/api/ai/blocks/plan/jobs/* - tables de stockage persisté:
ui_block_ai_threadsui_block_ai_runsui_block_ai_run_events
- abstraction runner:
src/lib/server/services/blocks/block-ai-plan-runner.ts - le contrat de prompt IA inclut des instructions explicites de design policy (réutilisation de composants + patterns de layout cohérents avec le projet)
- action de finalisation avec approbations explicites des imports manquants:
createBlockFromAiPlanAction
- les points d'entrée de création IA sont gardés par le réglage de site
ai-components-enabled, afin que l'UI et les actions serveur se désactivent ensemble.
- Catalogue hybride de pages dans le schéma système:
ui_page_registry_itemsstocke l'identité de page, le scope/channel, le chemin et les métadonnéesui_page_revisionsstocke unPuckPageDocumentV1versionné + diagnostics- La génération IA de pages utilise un état durable Postgres:
ui_page_ai_runsui_page_ai_run_events- APIs sous
src/app/api/ai/pages/runs/* - Vercel Queues peut réveiller la route worker hébergée;
bun run worker:page-aiinterroge le même état DB pour les déploiements auto-hébergés avec worker long-lived
ui_page_publicationsstocke l'état de cycle de vie et le pointeur vers la révision publiée- l'UX du tableau de bord est divisée entre liste/table puis route d'éditeur dédiée par page
- l'éditeur est Puck + shadcn direct (aucun chemin de fallback legacy)
- le modèle de sauvegarde est autosave + publish/archive avec verrouillage
optimiste (
baseRevisionId) - la gestion de conflit est explicite (réponse
conflict) sans merge/rebase automatique - le runtime lit directement les documents Puck publiés
- les pages globales se résolvent depuis
/[locale]/[...slug] - les pages membres d'organisation se résolvent depuis
/[locale]/o/[orgSlug]/[[...slug]] - la publication est bloquée en cas d'erreurs de diagnostics et de collisions avec des routes réservées
- Politique d'approbation du registre global dans le schéma système:
ui_registry_templatesstocke les alias shadcn compatibles approuvés + les modèles d'URL- les pipelines d'import résolvent les alias externes uniquement depuis les modèles approuvés
- la page d'administration est disponible à
/dashboard/admin/registry-templates
- Actions serveur générées dans
src/lib/server/actions/database/generated
Observabilité et indicateurs de fonctionnalité
- Intégration serveur/client PostHog dans
src/lib/posthogetsrc/providers - Indicateurs dynamiques dans
src/lib/flags - Valeurs par défaut des indicateurs gérés déclarées dans
src/config/flags.config.tset seedées parsrc/lib/scripts/seed.ts - Les réglages de site admin s'appuient sur des lignes
feature_flagsgérées par le code - Les indicateurs personnalisés sont générés depuis les lignes
feature_flagsnon gérées et n'affectent le comportement à l'exécution que lorsque le code lit explicitement leur slug - Capacités auth runtime résolues dans
src/config/authentication-runtime.config.ts - Les analytics du tableau de bord sont pilotées par un view-model serveur dans
src/lib/server/services/dashboard:/dashboard/adminest la surface de santé plateforme superadmin avec revenu Stripe, audience PostHog, croissance des utilisateurs inscrits, risque de facturation et actions admin. Le parent admin de la barre latérale est un lien direct vers cette route./dashboardest un accueil de navigation conscient des permissions, construit depuis les racines de sections visibles et les liens rapides, sans dupliquer la santé organisationnelle ou les métriques fournisseur- les propriétaires/admins/managers d'organisation voient la facturation, les sièges, l'inventaire de contenu, l'usage et les actions de gestion sur les tableaux de bord de section scopés organisation
- les membres d'organisation voient uniquement l'activité opérationnelle et les raccourcis sûrs sur les sections auxquelles ils ont accès
- les agrégats base de données, PostHog et Stripe utilisent le Data Cache partagé de Next.js pendant 5 minutes, avec clés par route, période, organisation et périmètre d'accès, tandis que session et autorisation restent par requête
- les analytics de vues CMS lisent les événements
cms_page_viewedpour les pages de l'organisation active et incluent les pages globales seulement pour les acteurs ayantpage:manageglobal, y compris les classements de pages principales sur/dashboard/content - les fallbacks par fournisseur évitent qu'une source de métriques défaillante casse la page
- le statut de déploiement est adossé au fournisseur: les lectures Vercel
restent disponibles, tandis que les runtimes auto-hébergés peuvent fournir
des métadonnées statiques via les variables
DEPLOYMENT_* - les événements PostHog enregistrés depuis l'app incluent
organization_idlorsqu'une organisation active est disponible, ce qui permet les analytics scopées par organisation
Fournisseurs De Déploiement
La première cible auto-hébergée portable de Yayaw est Docker standalone Next.js
avec Postgres, stockage objet compatible S3, worker Page AI adossé à la base et
proxy inverse qui préserve Host et X-Forwarded-*. Vercel reste un fournisseur
supporté pour l'hébergement, les queues, les métriques de déploiement et la
vérification des domaines projet, mais ces capacités ne sont plus présumées par
le runtime coeur.
Seams runtime:
- stockage:
STORAGE_PROVIDER=supabase|s3 - domaines publics d'organisation:
PUBLIC_DOMAIN_PROVIDER=vercel|manual-dns - réveil Page AI:
PAGE_AI_QUEUE_DRIVER=direct|vercel-queue|db-worker - métadonnées de déploiement: variables runtime Vercel ou variables statiques
DEPLOYMENT_*
Postgres + Drizzle est la source de vérité des données applicatives. Supabase n'est pas requis pour la persistance coeur; c'est seulement un fournisseur optionnel de stockage objet et un workflow de reset local.
Plan de contrôle
- Endpoint MCP de production:
src/app/api/mcp/route.ts - Lanceur stdio local:
src/lib/scripts/mcp/yayaw-mcp-server.ts - Script de gestion des clés:
src/lib/scripts/mcp/control-plane-key.ts - Registre partagé d'opérations typées:
src/lib/server/services/control-plane - Stockage d'audit:
control_plane_audit_events - L'accès production exige le réglage de site
control-plane-mcp-enabled, une clé API Better Auth valide ou un access token OAuth, des permissions de plan de contrôle et l'autorisation Yayaw sous-jacente - Les outils d'écriture exigent
reason; les flux de publication optimistes exigentexpectedRevisionId; les archives destructrices exigentconfirm: true
Règle pour les futures fonctionnalités:
- Traiter par défaut les workflows d'exploitation, contenu, configuration, publication, audit et statut comme candidats au plan de contrôle
- Placer la logique métier réutilisable derrière des points d'entrée de service explicites et conscients de l'acteur
- Garder les actions serveur UI, outils MCP, scripts CLI et APIs HTTP facultatives comme de fins adaptateurs au-dessus de la même logique de service
- Ajouter outils/ressources MCP typés, couverture d'audit, docs, mises à jour de la source LLM et tests ciblés dans le même changement lorsqu'une fonctionnalité devient opérable par le plan de contrôle
- Documenter les exclusions intentionnelles lorsqu'une fonctionnalité reste uniquement UI
Contrat des indicateurs de fonctionnalité
Pour les fonctionnalités produit, les indicateurs doivent contrôler:
- le comportement runtime (plugins/services/actions)
- l'exposition UI (cartes, actions, entrées de navigation)
Cela évite les désactivations partielles où le backend est coupé mais où les liens UI restent visibles.
Architecture de documentation
- Docs humaines: pages Fumadocs sous
content/docs - Source de vérité des docs LLM:
content/llm/llm-source.md - Docs assistant générées:
AGENTS.mdGEMINI.md.github/copilot-instructions.md
Lorsque vous changez un comportement produit, mettez d'abord à jour la doc de
fonctionnalité anglaise pertinente, puis mettez à jour
content/llm/llm-source.md lorsque le comportement assistant ou la source de
vérité architecturale change. Régénérez les docs assistant avec:
bun run docs:llm:generate