YYayaw
Documentation

Catalogue des composants

Inventaire interne des composants UI, règles d'aperçu et contrat de registre V2.

Vue d'ensemble

Yayaw inclut un catalogue interne de composants à :

  • /dashboard/content/components

Le catalogue prend en charge un inventaire mixte :

  • composants locaux depuis src/components/ui/*
  • composants importés stockés dans des snapshots DB (non exécutables)

Docs liées :

Rôle CMS

Le catalogue des composants est l'inventaire de rendu du CMS. Il documente et prévisualise les pièces UI bas niveau que les sections peuvent utiliser, y compris les composants locaux et les snapshots de source importés. Les composants ne sont pas du contenu édité en eux-mêmes ; ce sont les primitives de rendu sûres utilisées par les sections réutilisables et les références directes de page.

Gardez les imports de composants non exécutables, compilez-les en recettes validées et ne publiez que les entrées qui réussissent les contrôles de compilation et de smoke render.

Objectifs :

  • lister les composants UI depuis src/components/ui
  • lister les composants UI importés depuis les révisions DB
  • prévisualiser les composants compatibles avec des contrôles de props vivants
  • afficher les fichiers source utilisés par chaque entrée
  • valider le rendu compatible tokens avec les design tokens runtime courants

Scope et conventions

La source de vérité locale reste explicite : src/components/ui/catalog/registry.ts.

Scope actuel :

  • fichiers de premier niveau dans src/components/ui/*.tsx
  • entrées clés pour src/components/ui/kibo-ui/*/index.tsx
  • entrée clé pour src/components/ui/yayaw-table/index.ts
  • entrées importées depuis la DB (ui_component_registry_items) fusionnées dans le même inventaire

Conventions :

  • une entrée de catalogue par composant clé
  • un composant clé par dossier pour les répertoires de composants imbriqués
  • le point d'entrée cible est index.tsx pour les dossiers imbriqués (les exceptions héritées sont explicites dans le registre)
  • les entrées importées sont des éléments de registre à scope global avec snapshots source uniquement
  • la règle de collision est déterministe : imported > local pour le même slug/id

Modèle d'aperçu

Le comportement d'aperçu est piloté par les recettes et partagé avec le rendu runtime :

  • src/lib/server/services/components/ui-component-recipe-compiler.ts
  • src/components/ui/catalog/ui-recipe-renderer-server.tsx
  • src/components/ui/catalog/ui-recipe-renderer-client.tsx

Flux :

  1. Le snapshot source est compilé en UiComponentRecipeV1.
  2. L'aperçu du catalogue rend la recette avec des contrôles générés depuis propSchema, apiSchema et harnessSchema.
  3. Le runtime de blocs résout les révisions de recettes publiées et utilise le même chemin de renderer.

creative-composition est volontairement plus strict : ses inputs runtime passent uniquement par propSchema. apiSchema et harnessSchema doivent être omis ou vides, fixtures doit être vide, et les réglages API, harness ou fixtures associés ne peuvent pas servir de canaux runtime cachés.

Politique d'aperçu runtime uniquement :

  • l'aperçu du catalogue utilise toujours le renderer de recettes interne
  • aucune iframe de docs externe n'est intégrée dans le panneau d'aperçu
  • les contrôles de parité d'aperçu passent par des onglets de variantes quand plusieurs bibliothèques exposent la même clé de composant

Garde de publication :

  • compiled + smoke render OK => published (auto-publication pour imports ou recompilation)
  • sinon => draft_blocked

Suppression douce :

  • les composants importés sont retirés du catalogue avec le statut de publication deleted
  • les snapshots source restent en DB pour audit/rejeu

Intégration AI SDK

Le fallback de compilation piloté par IA et la classification utilisent désormais Vercel AI SDK :

  • src/lib/server/services/components/ui-component-ai-client.ts
  • src/lib/server/services/components/ui-component-recipe-ai-fallback.ts
  • src/lib/server/services/components/ui-component-import-classifier.ts

Règles :

  • toutes les sorties IA sont validées avec des schémas zod stricts
  • l'utilisation des modèles suit une chaîne de fallback résiliente intégrée ; les builders de pages/blocs peuvent encore demander un modèle préféré depuis les contrôles UI
  • un fallback déterministe est toujours disponible si l'IA est indisponible
  • aucun échec IA ne bloque les pipelines d'import ou de compilation

Classification par bibliothèque et catégorie

Les composants importés sont classifiés avec une stratégie hybride :

  1. cache par sourceHash (réutilise les métadonnées de classification précédentes)
  2. heuristiques déterministes (bibliothèque + groupe)
  3. enrichissement AI SDK (affinage bibliothèque/catégorie)

Métadonnées persistées sur les lignes de registre :

  • library
  • group
  • classificationSource
  • classificationVersion
  • classificationModel (quand l'IA est utilisée)

Politique de catégorie :

  • normalisation en kebab-case minuscule
  • les nouvelles catégories sont acceptées automatiquement après normalisation

Politique de bibliothèque :

  • valeurs contrôlées : shadcn-ui, kibo-ui, yayaw, ai-sdk, custom

Composants vendoriés AI Elements

AI Elements est vendorié sous un namespace dédié :

  • src/components/ui/ai-elements/*
  • les ids du registre local de catalogue utilisent ai-elements-* pour éviter les collisions avec les ids shadcn principaux

Script d'installation/mise à jour :

  • bun run components:install-ai-elements

Comportement du script :

  • résout l'index de registre @ai-elements
  • installe chaque élément de registre dans src/components/ui/ai-elements
  • ignore les fichiers existants par défaut (--all pour réinstaller chaque élément)
  • régénère src/components/ui/ai-elements/index.ts
  • régénère les surcharges déterministes d'aperçu composite dans src/lib/server/services/components/ui-component-ai-elements-preview-overrides.generated.ts
  • continue en cas d'échec par élément et rapporte un résumé

Comportement du catalogue :

  • les fichiers AI Elements vendoriés sont listés dans src/components/ui/catalog/registry.ts
  • ils sont tagués comme bibliothèque ai-sdk
  • les familles AI Elements inconnues compilent en recettes composite par défaut afin de garder les aperçus disponibles
  • les recettes composites locales ai-elements-* sont enrichies par des surcharges déterministes générées depuis les snapshots source (components:generate-ai-elements-previews)
  • les éléments AI Elements importés utilisent automatiquement le préfixe de slug ai-elements-* quand leur slug de base entrerait en collision avec un id de catalogue local existant
  • quand plusieurs bibliothèques exposent la même clé canonique de composant, des onglets d'aperçu permettent aux utilisateurs de changer de variante et indiquent si leurs sources normalisées sont identiques ou différentes
  • le dashboard ne charge d'abord que les résumés de catalogue ; la recette et la source de la variante sélectionnée sont chargées à la demande afin que l'ouverture de la page Components ne compile ni ne transfère tous les aperçus de composants

Entrées unifiées et onglets de variantes

L'inventaire est groupé par clé logique de composant, pas par id brut de registre.

Règles :

  • une ligne d'inventaire par clé canonique de composant
  • chaque ligne peut exposer plusieurs variantes de bibliothèque (onglets dans l'aperçu)
  • sélectionner un filtre de bibliothèque garde une ligne visible quand elle a au moins une variante de cette bibliothèque
  • sélectionner un filtre de catégorie garde une ligne visible quand au moins une variante correspond à cette catégorie

Règles de regroupement par clé canonique

La résolution de clé canonique est définie dans :

  • src/components/ui/catalog/catalog-identity.ts

Normalisation actuelle :

  • les ids ai-elements-* sont groupés sous leur clé de base sans préfixe
  • tous les autres ids conservent leur valeur d'origine comme clé canonique

L'ordre des variantes de bibliothèque est déterministe :

  • shadcn-ui
  • ai-sdk
  • kibo-ui
  • yayaw
  • custom

Flux d'import et synchronisation de registre

La V2 prend en charge la gestion de composants depuis l'UI du catalogue pour les utilisateurs avec components:manage.

Flux d'ajout pris en charge :

  • entrée de commande shadcn
  • import de synchronisation d'alias de registre complet (onlyNew=true par défaut)
  • collage de snapshot source (name, sourceFile, sourceSnapshot)
  • import de snapshot source MCP via yayaw_component_import
  • import de recette déclarative MCP via yayaw_component_recipe_import

Action de synchronisation de registre :

  • syncRegistryAliasComponents(registryAlias, { onlyNew: true })

Politique non bloquante pour les nouvelles versions de bibliothèques :

  • la découverte du registre utilise les candidats de payload d'index (index.json et registry.json)
  • les éléments pas encore vendoriés localement peuvent quand même être importés via le pipeline de snapshots DB
  • la validation allowlist reste appliquée pour les domaines source

Les outils MCP de composants exposent la même frontière de catalogue adossée à la base :

  • yayaw_components_list et yayaw_component_get inspectent l'inventaire de composants ; includeSchemas=true renvoie les schémas de props/API/harness, les capacités runtime, les indications d'usage et les références directement utilisables
  • yayaw_component_import stocke et compile un snapshot source
  • yayaw_component_recipe_import valide et stocke une UiComponentRecipeV1 déclarative avec le statut draft_ready, sans exécuter de code fourni
  • yayaw_component_recompile recompile un snapshot stocké
  • yayaw_component_publish publie une révision compilée et smoke-renderable
  • yayaw_component_delete soft-delete une entrée importée

Ces outils ne mutent pas les fichiers source locaux du dépôt en production. Si un agent doit ajouter ou modifier des fichiers React first-party, c'est un changement de code qui doit passer par une branche et une pull request.

Les imports déclaratifs sont limités aux kinds de recettes first-party rendus par le runtime présent dans le dépôt. Le payload complet, les valeurs par défaut, les fixtures et les valueShape récursifs doivent être du JSON borné. La publication reste une opération explicite séparée. Pour design_system_extension, importer et publier ne suffit pas : le plan final doit référencer la révision publiée exacte depuis une nouvelle composition. Un import portant designContextId n'est accepté qu'après la sélection explicite du prototype dans ce contexte. Le compilateur inscrit cet ID sur la révision de recette immuable ; l'inventaire lit la provenance depuis cette révision publiée exacte, jamais depuis les métadonnées mutables du registre. Une recompilation ou la publication d'une autre révision n'hérite donc pas accidentellement de cette provenance. Pour creative-composition, l'autorisation générique des fixtures ne s'applique pas : fixtures doit être vide, tandis que apiSchema et harnessSchema doivent être omis ou vides. Une référence runtime exacte slug@revision n'est acceptée qu'après au moins une publication de cette révision. La provenance immuable publishedAt maintient une ancienne référence approuvée après l'avancement du pointeur du catalogue, tandis qu'un brouillon compilé ne peut pas être injecté dans une page générique.

Les recettes creative-composition peuvent exprimer une topologie artistique bornée : ratios de grille personnalisés, ordre et spans responsives, superposition dans un canvas, récits sticky avec repli mobile linéaire, recadrages focaux et masques d'image, rôles typographiques display, formes décoratives, fallback d'upload explicite par e-mail et mouvement intentionnel avec état de réduction du mouvement piloté par le runtime. Les nœuds de formulaire et d'upload natif sont fermés par défaut derrière un registre versionné de handlers CMS publics exacts. Le registre contient un handler multipart : POST /api/cms/forms/personalization-request. Ses contrôles obligatoires sont email (email), firstName (text), consent (checkbox) et photo (upload natif images) ; birthDate (date) et message (textarea) sont optionnels. Les noms, types et indicateurs obligatoires doivent respecter exactement ce contrat littéral. La photo doit être au format JPEG, PNG ou WebP et ne pas dépasser 8 Mo. Le serveur applique l'orientation, la réencode sans les métadonnées source, réinspecte les octets canoniques et ne stocke que cette image canonique dans le stockage privé, sans la promouvoir dans les médias CMS. Les états d'upload et de suppression forment un ledger durable en base ; les demandes non prêtes ou expirées ne sont jamais exposées aux lectures opérateur. Cet endpoint crée une demande de personnalisation destinée au suivi par un opérateur. Ce n'est pas un endpoint de checkout, de confirmation de commande ou de paiement.

honest_form_controls exige aussi des champs et un bouton submit dans ce formulaire actionnable enregistré ; file_upload exige son contrat POST multipart exact. Les actions same-origin arbitraires restent refusées. Pour tout autre handler ou action, seul email-fallback représente honnêtement la collecte de fichiers. Les opérateurs admin traitent les demandes privées avec yayaw_cms_personalization_requests_list, yayaw_cms_personalization_request_get, yayaw_cms_personalization_request_status_update, yayaw_cms_personalization_request_delete et yayaw_cms_personalization_requests_prune. Le prune prend en charge le dry-run et retire les demandes dont la rétention de 180 jours est expirée. Le worker Page AI long-lived exécute une maintenance bornée indépendamment des runs IA en attente : il récupère les objets interrompus pendant l'upload ou la suppression et applique la rétention. Le petit prune best-effort après une soumission réussie ne fait que compléter cette voie worker durable. Une capacité typographique display exige un style display autorisé et un rôle family explicite (brand-sans, brand-serif ou brand-mono) qui correspond à la famille de police des design tokens actifs. Les props de surface utilisent des rôles sémantiques stables comme background, foreground, card, muted, primary, accent et border ; elles sont résolues par le thème actif et ne promettent pas une couleur littérale. Les anciens noms de surface évoquant des couleurs restent des alias de compatibilité et ne prouvent pas semantic_surfaces. Les props fonctionnelles ont aussi des types bornés et des champs obligatoires : une chaîne comme "true" ne remplace pas un comportement booléen au runtime. Le serveur infère creativeCapabilities uniquement depuis un arbre déclaratif exact valide et refuse un manifeste fourni qui prétend utiliser des primitives que l'arbre n'implémente pas. Un prototype sélectionné déclare requiredCapabilities ; avant la persistance de la page, chaque région mappée doit utiliser la révision publiée exacte dont les manifestes de structure et d'implémentation dérivés côté serveur correspondent à la topologie et aux noms/schéma/arbre canoniques enregistrés pour cette région. Cette révision exacte doit être le composant publié racine de la section mappée, et les bindings résolus de son instance doivent correspondre au manifeste de rendu enregistré. new_recipe exige une révision créée dans le même contexte et ne peut pas reprendre une topologie compositionHash déjà présente sur une creative-composition publiée dans l'inventaire préparé ; un nouvel ID, slug ou numéro de révision ne rend pas un clone inédit. reuse_published exige son composant publié déclaré. Une occurrence imbriquée du composant promis ne satisfait pas le contrat.

Le runtime versionné expose aussi les primitives de fidélité bornées suivantes via yayaw_components_list(includeSchemas=true) :

  • canvas.height accepte content pour une hauteur pilotée par le contenu et band pour une scène compacte ; canvas.mobileGap contrôle l'espacement borné lorsque les enfants s'empilent sur mobile
  • image.aspect, image.mobileAspect et image.desktopAspect acceptent auto, cinema, landscape, panorama, portrait, square, strip, tall ou video ; image.height accepte auto, band, panel ou hero
  • decoration.treatment accepte solid, outline ou wash ; wash rend un accent pigmenté en couches et ne remplace jamais une image requise
  • frame.material accepte clean, paper, deckle ou taped ; frame.rotation et placement.rotation acceptent les valeurs bornées -6, -3, 0, 3 ou 6, et text.style: "note" fournit un traitement de note manuscrite
  • text.weight accepte normal, medium, semibold, bold ou black
  • visibility.show accepte all, mobile ou desktop, tandis que disclosure rend un contrôle sémantique borné details/summary avec label obligatoire et align, appearance: "bare" | "framed" et surface optionnels

Ces nœuds infèrent compact_band, responsive_media, watercolor_wash, paper_collage, typographic_weight, responsive_recomposition et responsive_navigation uniquement depuis un comportement matériel : compact_band exige height: "band", responsive_media exige des ratios mobile et desktop non-auto distincts sans hauteur fixe, et responsive_navigation exige un disclosure mobile avec une branche desktop non vide. La planification d'un prototype conserve un ledger de faisabilité par région. Les props d'ordre responsive (desktopOrder ou mobileOrder) exigent un parent direct grid ou stack ; les props de span responsive (desktopSpan ou mobileSpan) exigent un parent direct grid. Un ancêtre compatible ne suffit pas. Chaque région déclare les nœuds allowlistés exacts, leurs chemins canoniques (tree, puis tree.children.N récursivement), leurs props bornées, le recipePropSchema déclaratif exact, une liste recipePropNames possédant exactement les mêmes clés et les recipePropBindings exacts de l'instance de section prévue. Les props requises sans défaut exigent un binding, chaque clé de binding appartient au schéma et chaque image.src doit être exactement $props.<identifier>, avec cette prop liée comme media_asset ou localized_media_asset à un média durable de l'inventaire préparé. mediaAssetIds égale l'ensemble exact et dédupliqué des IDs utilisés par tous les bindings média. Le serveur reconstruit puis valide la recette avec le contrat runtime canonique. Il calcule compositionHash depuis les noms de nœuds, chemins canoniques et props structurelles uniquement, après exclusion du contenu, des médias, actions, choix de palette surface/tone et autres props non structurelles, avec normalisation des références runtime. Il calcule séparément implementationHash depuis les noms/schéma/arbre et renderManifestHash depuis cette implémentation et ses bindings, puis compare les trois manifestes produits par le serveur à l'instance publiée exacte utilisée à la racine de la section mappée. Un arbre différent aux mêmes capacités grossières, un substitut imbriqué ou des bindings modifiés échouent. Une union globale de capacités ne peut pas masquer une région irréalisable. Pour design_system_extension, chaque candidat A/B/C doit mapper visiblement au moins une région vers new_recipe. Les textes, liens, labels, placeholders, textes alternatifs et messages d'upload visibles dans un prototype doivent chacun être un sink direct $props.<identifier>. Les bindings de texte sont des littéraux localisés exacts pour toutes les locales préparées ; les liens sont des cibles littérales ou localisées sûres et bornées. Les bindings global-data critiques pour le prototype sont refusés au lieu d'être considérés comme figés. repeat, $item et $index sont aussi refusés : le contenu répété visible doit être développé en nœuds planifiés explicites afin que la topologie et les bindings enregistrés correspondent au runtime revu. L'enregistrement du prototype exige aussi les comparaisons A/B, A/C et B/C complètes, avec des preuves artefact-région exactes pour les deux candidats dans chaque région stable. Les compositionHash régionaux ordonnés forment la signature structurelle du candidat. Le manifeste normalisé du page shell est épinglé séparément et doit correspondre exactement au candidat sélectionné dans le plan et le runtime ; il ne fait pas partie de la signature de distinction entre candidats. Les implementationHash et renderManifestHash régionaux ordonnés forment les signatures d'implémentation et de rendu. Les trois signatures A/B/C de chaque type doivent être distinctes. Des changements de contenu, média, palette, défauts de schéma ou bindings ne transforment pas une topologie inchangée en direction séparée. Une empreinte normalisée de matrice d'arêtes en niveaux de gris 16 × 16, calculée côté serveur, rejette aussi les planches clonées ou insuffisamment différentes. Ce garde-fou grossier de la structure de la planche complète ne prouve jamais à lui seul une direction ou une fidélité distincte ; il complète les trois signatures, la critique par paires, l'inspection visuelle et une Visual QA substantielle.

L'enregistrement exact-runtime utilise kind: "generated_set_v2". Avant cet enregistrement, chaque image de récit ou de recette utilisée par ces bindings est finalisée avec MIME image, dimensions et provenance SHA-256, puis ajoutée par l'unique refresh média-only de présélection. Les planches et les captures runtime post-enregistrement sont interrogées directement par ID et ne doivent pas déclencher d'autre refresh d'inventaire. Chaque candidat fournit un pageShell exact (layout et designTokens de page bornés ou null) et des artifactBounds entiers pour chaque région visible. Une région mesure au moins 200 × 120 pixels et 2 % de la planche, leur union couvre au moins 40 %, et le chevauchement de deux régions ne dépasse pas 50 % de la plus petite. Hors du scope d'une page globale, les tokens de page valent obligatoirement null. Pour chaque paire de candidats, au moins une empreinte de région correspondante doit être matériellement distincte ; le chrome de la planche seul ne suffit pas.

Le client fournit les arbres, schémas, bindings et bounds prévus, jamais les hashes dérivés de composition, implémentation, rendu, page shell, fingerprint ou runtime. Le serveur calcule ces champs et résout chaque candidat via les runtimes canoniques de page et de recette. L'enregistrement renvoie les aperçus runtime signés et un runtimeHash par candidat. Le Visual QA compare chaque planche pour toutes les locales préparées en desktop/mobile et clair/sombre, uploade chaque capture pleine page distincte avec le contexte, le hash runtime et le rôle exacts renvoyés, puis appelle yayaw_cms_prototype_runtime_review_complete. La valeur visual_qa est un rôle logique de l'acteur courant, pas la preuve d'un reviewer authentifié indépendamment. Les planches et les aperçus runtime restent des artefacts visuels séparés : manifestes et hashes détectent substitution ou dérive, sans prouver une équivalence de pixels.

En production, la résolution runtime échoue de façon fermée sans fingerprint immuable fourni par NEXT_DEPLOYMENT_ID, le gitCommitSha résolu tel que DEPLOYMENT_GIT_COMMIT_SHA, ou le deploymentId résolu ; "local" est un fallback réservé aux environnements hors production. Le fingerprint de déploiement et la version du contrat renderer entrent dans runtimeHash : un changement de build renderer invalide donc la revue antérieure.

La sélection est bloquée tant que cette revue runtime n'est pas courante. Une modification du renderer, du déploiement, d'une recette, d'un média, d'une capture ou des tokens peut la rendre périmée. Un changement de design tokens après l'enregistrement impose un nouveau contexte préparé et trois nouveaux candidats. Après sélection, les révisions de recettes exactes peuvent être importées et publiées, puis un refresh avec les mêmes tokens précède le plan strict version 2. Ce plan reproduit exactement le layout du page shell et la couche de tokens de page du candidat sélectionné.

En production, l'enregistrement v2 n'est activé qu'après le rollout reader-first : CMS_PROTOTYPE_RUNTIME_V2_WRITES_ENABLED est désactivé par défaut et reste à false pendant que le build reader-compatible remplace et draine toutes les instances antérieures. Il ne passe à true qu'une fois ce build devenu le rollback floor. Le champ v2 séparé ne sécurise pas à lui seul une flotte mixte. Dès qu'un contexte v2 existe, ne jamais rollback vers un build antérieur au reader ; avancer uniquement en roll-forward jusqu'au retrait ou à la migration de ces contextes. L'enregistrement legacy reste lisible et écrivable pendant cette phase pour la compatibilité de transition, mais un nouveau workflow exact ne doit pas s'y rabattre. Le writer désactivé renvoie cms_design_prototype_runtime_rollout_pending. En local et dans les autres environnements hors production, les écritures v2 sont activées par défaut lorsque la variable est absente.

Indications d'usage pour le planificateur de blocs

Le planificateur IA de blocs consomme les indications d'usage du catalogue quand elles sont disponibles :

  • court extrait d'exemple depuis le contexte CLI/persisté
  • dépendances clés de registre
  • liens docs/exemples

Ces métadonnées sont en lecture seule et passées dans le payload de prompt pour améliorer la sélection de composants et de props dans les arbres de blocs générés. Elles n'exécutent aucun code source DB.

Enrichissement de contexte CLI-first

Les imports résolvent maintenant le contexte depuis la CLI shadcn officielle en premier, puis appliquent des fallbacks déterministes.

Points d'implémentation :

  • src/lib/server/actions/components/component-registry-actions.ts
  • src/lib/server/services/components/ui-component-shadcn-cli-context.ts
  • src/lib/server/services/components/shadcn-cli-runner.ts
  • src/lib/server/services/components/ui-component-recipe-import-enrichment.ts
  • src/lib/server/services/components/ui-component-import-preview-evidence.ts

Comportement :

  • le runner CLI est local-first (bunx shadcn) avec fallback npx -y shadcn@latest, timeout, retry et logs structurés
  • le résolveur agrège :
    • métadonnées/fichiers de payload shadcn view
    • liens shadcn docs --json pour les composants shadcn principaux
    • shadcn search + shadcn view pour les blocs d'exemples de registre
  • le contexte résolu inclut :
    • sourceTitle / sourceDescription
    • exampleSnippets
    • registryDependencies
    • liens de docs (docs, examples)
    • indice d'interaction (click-trigger, selection ou fallback inline)
  • la priorité des preuves d'aperçu est déterministe : CLI -> payload -> web -> source snapshot
  • le contexte est mis en cache dans les métadonnées d'import par sourceHash (contextVersion, liens, extraits, dépendances), ce qui évite les appels CLI répétés lors des imports répétés
  • quand le contexte CLI est indisponible, l'import reste non bloquant et le comportement de garde compilation/publication ne change pas
  • aucun code source externe n'est exécuté ; seules les métadonnées et snapshots sont parsés

Politique interaction-first :

  • les aperçus de type overlay doivent préférer des déclencheurs de clic explicites plutôt que des états toujours ouverts
  • les blueprints IA composites sont neutres par défaut (pas de microcopy spécifique IA/chat sauf si les preuves source l'exigent explicitement)

Comportement des design tokens

L'aperçu du catalogue ne dépend pas uniquement du CSS de base.

Il résout les tokens runtime effectifs pour la session courante (surcharges globales + organisation) et applique des variables CSS scopées à la surface d'aperçu. Cela permet aux utilisateurs du dashboard de valider les composants UI contre les mêmes valeurs de tokens sémantiques que celles utilisées au runtime.

Validation

La cohérence du registre est validée par des tests :

  • unicité des ids d'entrée
  • existence des fichiers source
  • références demoId résolues par la carte de démo

Gardes runtime/catalogue :

  • aucune exécution de code DB (les snapshots source ne sont jamais évalués)
  • publication bloquée quand les diagnostics de compilation ou le smoke render échouent
  • les extensions du design system importent les nouvelles recettes seulement après la sélection du prototype avec le designContextId actif ; l'inventaire actualisé lit cette provenance sur la révision publiée immuable exacte
  • created_component_not_new bloque un composant déjà présent dans la baseline initiale et created_component_context_mismatch un composant importé par un autre workflow
  • created_component_not_used bloque un composant déclaré comme créé mais absent des nouvelles compositions, y compris si une autre révision du même slug est utilisée

Commandes utiles :

bun test src/components/ui/catalog/registry.test.ts
bun test src/lib/server/services/components/ui-component-recipe-compiler.test.ts
bun test src/lib/server/services/components/ui-component-catalog-query.test.ts
bun run components:generate-ai-elements-previews

Variables d'environnement

  • OPENAI_API_KEY
  • OPENAI_COMPONENTS_AI_FALLBACK

Ces variables OpenAI sont optionnelles et n'affectent que l'enrichissement AI SDK pour les composants importés. Les surcharges locales d'aperçu AI Elements sont entièrement déterministes et ne requièrent pas OPENAI_API_KEY.

Direction du contrat

  • scope produit global
  • stockage de snapshot source pour audit/rejeu
  • aucune exécution runtime de code stocké en DB

Type de référence :

  • UiComponentRegistryItemV1 dans src/components/ui/catalog/types.ts

Tables DB :

  • ui_component_registry_items
  • ui_component_recipe_revisions
  • ui_component_publications