Cocon SEO

Le module Cocon SEO est le moteur de génération massive de pages SEO du Labo du Yeti. Il permet de produire automatiquement des centaines de pages cohérentes à partir d'un seul template HTML et de quelques listes de variables. Chaque page générée est rangée dans un content group (groupe de contenu) qui définit les variables, les patrons de slug, de titre et de SEO, ainsi que la fréquence à laquelle l'IA peut produire de nouvelles pages.

Ce module est l'un des trois grands piliers éditoriaux du CMS, aux côtés des pages classiques et du blog IA. Il est conçu pour bâtir des cocons sémantiques à deux niveaux : une page parent (la pilier d'un service) et un ensemble de pages enfants (les variantes locales ou catégorielles). Le code de production se trouve principalement dans backend/src/services/cocon-service.js, backend/src/services/quota-service.js et backend/src/services/notification-service.js.

Capability requise. Toutes les routes de ce module exigent requireCapability('cocon'). Les rôles owner, admin, webmaster et editor ont la capacité activée par défaut ; un owner peut la désactiver pour un rôle via la matrice des droits.

Content groups

Un content group est l'unité de configuration d'un cocon. Il est persisté dans la table cocon_groups (legacy KV cocon.content_groups en cours de migration) et regroupe :

Variables et patrons d'interpolation

Les variables sont déclarées sous forme de listes nommées. Exemple pour un cocon d'agence locale :

{
  "id": "grp_plombier_villes",
  "title": "Plombier — villes Île-de-France",
  "variables": {
    "service": ["debouchage", "fuite", "chauffe-eau"],
    "ville":   ["Paris", "Versailles", "Boulogne", "Saint-Denis"]
  },
  "slug_pattern":  "{{service}}/{{ville}}",
  "title_pattern": "Plombier {{service}} à {{ville}} | Intervention 24/7",
  "seo": {
    "meta_description_pattern": "Plombier spécialisé {{service}} à {{ville}}. Devis gratuit, intervention rapide.",
    "h1_pattern":               "Plombier {{service}} {{ville}}"
  }
}

L'interpolation {{var}} est résolue au moment de la génération par cocon-service.js. Chaque clé entre doubles accolades est remplacée par la valeur courante de la combinaison en cours. Les patrons peuvent contenir n'importe quel nombre de variables, mais toute clé non déclarée dans variables provoque un rejet à la validation du groupe.

Combinaisons cartésiennes

Les combinaisons sont calculées au runtime par produit cartésien des listes de variables. Pour le groupe ci-dessus, on obtient 3 × 4 = 12 combinaisons. L'endpoint GET /api/cocon/groups/:id/combinations retourne cette matrice prévisualisée afin de valider visuellement les slugs et titres avant de lancer la génération.

servicevilleslugtitle
debouchageParisdebouchage/parisPlombier debouchage à Paris | Intervention 24/7
debouchageVersaillesdebouchage/versaillesPlombier debouchage à Versailles | Intervention 24/7
fuiteParisfuite/parisPlombier fuite à Paris | Intervention 24/7
chauffe-eauSaint-Denischauffe-eau/saint-denisPlombier chauffe-eau à Saint-Denis | Intervention 24/7
Slugs normalisés. Les valeurs de variables sont passées dans un normalisateur (minuscules, retrait des accents, espaces → tirets) avant d'être injectées dans slug_pattern. Les patrons de titre, en revanche, conservent les majuscules et accents pour rester naturels en SERP.

Hiérarchie parent / enfant

Le cocon SEO du Labo du Yeti repose sur une architecture à deux niveaux : un groupe parent et un ou plusieurs groupes enfants. Cette structure est matérialisée par le champ parent_id sur les groupes enfants et par le même champ sur les pages générées.

RôleNombre de variablesExemplePages produites
Groupe parent1 variableserviceN pages parents (1 par service)
Groupe enfant2 variables ou plusservice + villeN × M pages enfants

Slugs composites

Les enfants héritent automatiquement du segment de slug de leur parent. Si la page parent debouchage a pour slug /debouchage, ses enfants auront pour slugs /debouchage/paris, /debouchage/versailles, etc. Cette composition est faite au moment du build pour garantir que l'URL physique reflète la hiérarchie sémantique.

Section « Voir aussi »

Chaque page parent peut afficher en bas de contenu une section « Voir aussi » (ou « Voir plus ») qui liste automatiquement les pages enfants associées, filtrées par la variable commune. La configuration de cette section est portée par le composant frontend RelatedSectionPanel et permet de régler :

Cette configuration est stockée dans le groupe parent et appliquée au moment du rendu HTML par le pipeline de moteur HTML.

Quotas de génération

Pour éviter le spam IA et lisser le coût des appels Anthropic, chaque groupe possède un quota propre : un nombre maximum de pages générables sur une fenêtre glissante en jours. La valeur par défaut est 5 pages / 7 jours, modifiable via PUT /api/cocon/groups/:id/quota.

Le contrôle est centralisé dans backend/src/services/quota-service.js qui expose la méthode canGenerate(groupId). Elle est appelée avant chaque batch par la route POST /api/cocon/groups/:id/generate et retourne :

{
  "allowed":      true,
  "remaining":    3,
  "window_days":  7,
  "max":          5,
  "used":         2,
  "next_slot_at": "2026-06-04T14:32:00.000Z"
}

Si allowed vaut false, l'API répond POST 429 avec la date du prochain créneau libre. L'endpoint GET /api/cocon/groups/:id/quota-status permet à l'UI d'afficher en temps réel l'état du compteur.

Rate limit complémentaire. Au quota par groupe s'ajoute le aiGenLimiter (10 générations IA par minute, toutes ressources confondues) qui protège l'API Anthropic d'un emballement global.

Ordre parent → enfant strict

Une règle d'or structure tout le pipeline de cocon : les enfants ne peuvent pas être générés tant que les parents associés ne sont pas générés ET publiés. « Publiés » signifie ici qu'un build a effectivement été lancé via POST /api/build et que le HTML statique des parents existe dans public/.

  1. L'admin crée le groupe parent (1 variable) puis lance la génération.
  2. L'admin déclenche un build du site pour figer les pages parents.
  3. Le module cocon débloque automatiquement le groupe enfant correspondant.
  4. L'admin peut alors générer les pages enfants par lots (en respectant le quota).

Ce verrouillage évite deux pièges classiques : des liens internes « Voir aussi » qui pointent vers des parents inexistants, et des cocons enfants orphelins en cas d'abandon de campagne. Côté API, toute tentative de générer un enfant sans parent buildé répond 409 Conflict avec un message explicite.

UI Programmation

L'écran Programmation de la sidebar Contenu → Cocon SEO est le tableau de bord centralisé. Il combine deux blocs :

Cette UI consomme GET /api/cocon/groups/:id/quota-status et GET /api/cocon/groups/:id/generation-progress. La progression IA est diffusée par polling : le service backend met à jour un compteur en mémoire à chaque appel terminé.

Notifications email de créneaux

Pour ne jamais « oublier » un créneau de génération, le module notification-service.js envoie automatiquement un rappel email aux utilisateurs concernés 5 minutes après chaque créneau libéré. La constante SLOT_NOTIFICATION_ROLES = ['admin', 'webmaster'] contrôle qui reçoit ces notifications.

RôleReçoit les rappels de créneauJustification
ownerNon (par défaut)Le owner reste libre, il peut s'abonner manuellement.
adminOuiPilote opérationnel du cocon.
webmasterOuiResponsable du build et de la mise en ligne.
editorNonPas la main sur la programmation des batches.

Le mail est envoyé via la configuration SMTP gérée dans Réglages → Général et utilise les helpers de backend/src/lib/datetime.js pour afficher l'heure du prochain créneau en français.

Médiathèque cocon dédiée

Le cocon SEO possède sa propre médiathèque, distincte de la médiathèque globale du CMS. Elle est portée par les routes GET/POST/PUT/DELETE /api/cocon/media et persistée dans cocon.media.

Ses images sont réutilisables dans tous les groupes : une fois uploadée, une image peut servir d'illustration aux pages d'un groupe Plombier comme à celles d'un groupe Électricien. C'est utile pour les visuels génériques (icônes service, photos d'équipe, illustrations de réassurance) qui n'ont pas besoin d'être contextualisés par ville.

Pourquoi une médiathèque séparée ? Les images cocon sont souvent générées en lot par l'IA ou achetées sur banque d'images. Les isoler évite qu'elles polluent la grille de la médiathèque générale et facilite leur gestion (filtres, tri, purge).

Le composant frontend RelatedSectionPanel est l'éditeur visuel de la section « Voir aussi ». Il s'affiche en latéral droit lors de l'édition d'une page parent de cocon et permet de configurer :

La configuration est sérialisée dans le groupe parent et propagée à toutes ses pages au build. La règle de sécurité du builder s'applique : seuls les styles « sûrs » (couleur, alignement, gras/italique) sont éditables, le HTML structurel reste figé pour préserver le SEO.

Récapitulatif API

MéthodeRouteUsage
GET/api/cocon/groupsListe les groupes
POST/api/cocon/groupsCrée un groupe + upload du template
GET/api/cocon/groups/:id/combinationsPrévisualise la matrice cartésienne
GET/api/cocon/groups/:id/quota-statusÉtat du quota (used/max/remaining)
PUT/api/cocon/groups/:id/quotaModifie le quota du groupe
POST/api/cocon/groups/:id/generateLance un batch de génération IA (rate limit 10/min)
GET/api/cocon/groups/:id/generation-progressSuit l'avancée d'un batch en cours
DELETE/api/cocon/groups/:id/pagesSupprime toutes les pages générées du groupe
GET/api/cocon/mediaMédiathèque cocon dédiée
Liens utiles. Pour les capacités et rôles voir Authentification & RBAC. Pour la compilation du HTML statique et la génération du sitemap voir Build & Publication. Pour l'intégration des appels Anthropic voir Moteur IA.