Modèles de données CMS
Modèles de données typés, localisés et publiables, et variables inline pour le contenu CMS.
Vue d'ensemble
Yayaw sépare les données de contenu CMS des design tokens.
/dashboard/content/design-tokensreste l'éditeur de design tokens./dashboard/content/data-modelsgère la structure scopée des modèles de données CMS./dashboard/content/dataremplit et publie les entrées de ces modèles.
Les modèles de données CMS peuvent être scopés :
global: données partagées au niveau du site, contrôlées parglobal-data:manage.organization: données de l'organisation active, contrôlées parpage:manageousections:managesur cette organisation.
Les valeurs proches de médias doivent être stockées comme URL ou chaînes. La médiathèque d'organisation reste scopée séparément. Utilisez Médiathèque pour les ressources binaires possédées par l'organisation et ne stockez que les URL résultantes dans les entrées de données globales ou d'organisation.
Rôle CMS
Les données CMS sont la couche source structurée pour le contenu qui a besoin d'un contrat stable : variables de site, menus, faits produit, faits d'organisation, collections réutilisables et champs liés par référence depuis les pages ou sections. Les entrées de données doivent contenir des valeurs, pas de la présentation. Les sections et les pages décident comment ces valeurs sont rendues.
Utilisez les modèles de données quand les auteurs ont besoin de champs typés, de localisation, de validation et d'un cycle de publication. Utilisez les ressources média pour les fichiers, les sections pour la composition visuelle réutilisable et les design tokens pour les valeurs de thème visuel.
Contrats de document
Les données globales utilisent deux documents JSON versionnés :
GlobalDataModelDocumentV1GlobalDataEntryDocumentV1
Les documents de modèle définissent :
cardinality:singletonoucollectionfields: champs typés inspirés des champs personnalisés Builderlocalization: locale par défaut et locales prises en chargepresentation:headless,builtin_rendereroucomponent_recipe
La cardinalité contrôle combien d'entrées un modèle peut posséder :
singleton: une entrée globale, par exempleheader-menu,footer-menuou les paramètres SEO par défaut.collection: plusieurs entrées, par exemple produits, auteurs, redirections ou annonces réutilisables.
La présentation contrôle comment les données sont consommées :
headless: données structurées uniquement, consommées par les pages, bindings, helpers ou code personnalisé.builtin_renderer: données rendues par les composants runtime Yayaw, actuellement utilisées par les modèles internes comme l'en-tête et le pied de page.component_recipe: données destinées à être associées à une recette UI réutilisable dans un workflow ultérieur.
Chaque champ prend en charge les réglages de style Builder attendus par les éditeurs :
- type
- localisation
- valeur par défaut
- texte d'aide
- obligatoire/facultatif
- valeurs enum pour les champs select
- champs masqués qui restent hors de l'édition d'entrée tout en préservant les valeurs/défauts
Les champs masqués obligatoires doivent définir une valeur par défaut afin que les éditeurs d'entrées générés ne puissent pas créer de brouillons impossibles.
Les types de champs V1 pris en charge sont :
text,long_text,url,filenumber,boolean,select,colorrich_text,html,date,timestamplist,reference,map,javascript,code,tags,json
file stocke une URL/chaîne en V1 parce que la médiathèque est scopée par
organisation alors que les données globales sont à l'échelle du site.
Les documents d'entrée stockent les valeurs comme :
shared: une valeur pour toutes les localeslocalized: valeurs par locale avec fallback de la locale demandée vers la locale par défaut, puis vers la première locale disponible
Stockage
Les données CMS utilisent des révisions immuables et une ligne de publication par élément de registre.
Tables :
global_data_model_registry_itemsglobal_data_model_revisionsglobal_data_model_publicationsglobal_data_entry_registry_itemsglobal_data_entry_revisionsglobal_data_entry_publications
Les révisions sont dédupliquées par hash et validées avant publication. Les
publications peuvent être draft, published ou archived.
global_data_model_registry_items stocke scope et organization_id. Les
lignes existantes sont migrées vers scope = "global". Les slugs sont uniques
par scope global ou par scope d'organisation.
Édition dans le dashboard
Le dashboard fournit :
- liste de modèles avec Yayaw Table
- éditeur de champs de modèle pleine largeur
- liste dédiée d'entrées sur
/dashboard/content/data - éditeur d'entrée généré de style inspecteur, basé sur les champs du modèle sélectionné
- actions d'enregistrement, publication et archivage
- rendu lecture seule pour les utilisateurs sans permission de gestion
L'édition exige :
global-data:managepour les modèles globaux.page:manageousections:managesur l'organisation active pour les modèles d'organisation.
L'accès lecture seule est disponible via :
global-data:readouglobal-data:listpour les modèles globaux.page:read,page:list,sections:readousections:listpour les modèles d'organisation.
API runtime
Les helpers serveur vivent dans :
src/lib/server/services/global-data
Helpers clés :
getPublishedGlobalDataEntrygetPublishedGlobalDataValuelistPublishedGlobalDataEntrieslistPublishedGlobalDataFieldReferences
La plupart des helpers acceptent scope et organizationId quand des données
scopées par organisation sont nécessaires. Les bindings Page Builder existants
global_data_field et global_data_query continuent de résoudre les données
globales.
Le composant de slot runtime partagé vit dans :
src/blocks/shared/global-data-slot.tsx
Il résout une entrée singleton publiée et retombe sur l'UI statique existante quand aucune donnée publiée n'est disponible.
En-tête et pied de page
L'en-tête et le pied de page ne sont plus des entrées de catalogue de sections initialisées ni des props de page éditables sur chaque page.
Le script de seed crée deux modèles singleton à moteur de rendu intégré :
header-menufooter-menu
Les deux reçoivent une entrée main par défaut.
Les en-têtes et pieds de page générés lient ces entrées singleton avec des props
global_data_field. Les pages partagent donc une source de vérité localisée
pour les libellés de marque, URL de marque propres aux locales, éléments de
menu, tagline de pied de page et texte de copyright.
Le champ items_json est édité avec un éditeur visuel de menu dans le
formulaire d'entrée de données globales sur /dashboard/content/data. Il prend
en charge les liens de premier niveau, les groupes avec un niveau de liens
imbriqués, les bascules de thème, les bascules de langue, les actions de compte,
les contrôles de réordonnancement et un panneau de récupération JSON brut.
Les éléments d'en-tête peuvent cibler les zones gauche, centre ou droite ;
l'entrée par défaut utilise le lien de marque à gauche, la navigation au centre
et les actions thème/langue/compte à droite.
Les entrées par défaut header-menu/main et footer-menu/main organisent la
navigation publique en deux groupes de premier niveau :
Yayaw:/[locale]/codebase,/[locale]/pricinget/[locale]/docsYayaw Table:/[locale]/table,/[locale]/table/example,/[locale]/docs/tableet/[locale]/docs/table/installation
Gardez les liens de documentation développeur Yayaw Table sous le sous-projet
Fumadocs /[locale]/docs/table/*. Les pages CMS /[locale]/table/* restent
les surfaces publiques de produit et de démo.
Les anciennes lignes de seed site-header, site-footer, builtin-header et
builtin-footer sont supprimées par migration. Les documents de page hérités qui
référencent encore les anciennes sections intégrées sont normalisés en noeuds
d'en-tête/pied de page générés.
Bindings Page Builder
Les bindings de props de page prennent en charge les données globales en plus des littéraux et des ressources média.
Types de bindings :
global_data_field: lie un champ d'une entrée publiéeglobal_data_query: résout une collection publiée et extrait optionnellement un champ
L'inspecteur Puck expose un contrôle "Bind data" quand des références de données globales publiées sont disponibles. La V1 lie des champs complets.
Les variables CMS inline peuvent aussi être insérées dans les valeurs texte
depuis le catalogue d'en-tête du dashboard sur les routes
/dashboard/content/*. Les tokens sont namespacés pour éviter les collisions :
{site.name}{organization.logo}{data.global.header-menu.main.brand_label}{data.organization.<modelSlug>.<entrySlug>.<fieldKey>}{billing.product.pro_monthly.name}{billing.price.pro_monthly.id}
Les tokens inconnus restent inchangés au runtime. Les tokens non namespacés
comme {name} sont ignorés en V1.
Les variables de site sont éditées via l'entrée CMS Data du modèle singleton
intégré site-variables/main. Ses champs par défaut sont verrouillés afin que
la surface d'édition puisse changer les valeurs sans supprimer le contrat
canonique site.*. Chaque champ conserve néanmoins son propre réglage de
localisation : les valeurs techniques comme base_url, domain et les URL de
logo restent partagées, tandis que les valeurs éditoriales comme description
et title peuvent être localisées et se résoudre selon la locale demandée. Les
valeurs system_settings existantes sous cms.site-variables.v1 restent des
données de migration et de fallback.
Les variables de produits et prix de facturation sont lues depuis le catalogue
runtime des produits de facturation. Les métadonnées produit viennent de
billing_products quand elles sont configurées, tandis que les identifiants de
prix Stripe sont stockés en interne après la synchronisation du catalogue admin
ou MCP. Les variables d'organisation sont lues depuis la ligne Better Auth
organization ; l'édition continue de vivre dans les flux de paramètres
d'organisation.
La collection globale intégrée billing-product-content complète le catalogue
de facturation avec une entrée CMS par clé produit. Son champ verrouillé
catalog_product_key lie l'entrée CMS à Products & Services; les champs
éditoriaux comme badge, résumé, bullets de fonctionnalités, label CTA et état
de mise en avant peuvent être localisés. Ne stockez pas les noms de produits,
prix, intervalles, IDs Stripe ou disponibilité checkout dans ce modèle. Résolvez
ces faits depuis les namespaces de variables billing.product.* et
billing.price.*.
Le seed porte aussi le snapshot de données globales exporté depuis Supabase pour
les variables de site production, les menus header/footer et le singleton
sales-offer/main. Ces entrées sont publiées à chaque run de seed afin que les
bases production ou preview fraîches résolvent les mêmes variables CMS que
celles authorées dans Supabase. Les entrées billing-product-content ne sont
créées que lorsqu'elles manquent, afin de ne pas écraser ensuite le contenu
éditorial produit par une baseline vide.
Invalidation du cache
Les données globales publiées sont mises en cache avec des tags :
global-dataglobal-data:{modelSlug}
Les actions de publication et d'archivage revalident les tags de données globales, les routes de données du dashboard, le chemin racine public et le cache runtime des pages publiées.
Validation
Vérifications utiles après des changements de modèles de données CMS :
bun test src/lib/shared/global-data/global-data.test.ts
bun run check
bunx tsc --noEmit