Porte de Novembre — carte « bande du live → bloc »
Généré depuis le DOM, pas deviné. Source :
tools/seed-gen/pdn-bands.mjs→tools/seed-gen/data/pdn.json(28 pages FR, mesurées à 1440 le 2026-07-23, 0 échec). Toute correction doit repasser par le scraper, jamais à la main.
1. Ce qu'est réellement le site (mesuré)
| Fait | Valeur mesurée |
|---|---|
| Stack | WordPress + Elementor + thème muzicon / muzicon-child (ThemeREX) + trx_addons |
| Plugins visibles | Slider Revolution (héro), The Events Calendar, Smash Balloon Instagram, Contact Form 7, Complianz (CMP), Advanced Popups |
| Age gate | Aucun (contrairement à gilliard.ch et chevaliers.ch) |
| Boutique | Aucune. Tous les boutons « ACHETER » pointent vers gilliard.ch/fr/vins/… |
| Langues | FR + DE. FR uniquement ici (décision 2026-07-16, DE additif plus tard) |
⚠️ Le site est rendu par DEUX moteurs différents — ne pas généraliser depuis une page
Chaque page contient trois documents Elementor distincts, identifiés par data-elementor-type : cpt_layouts (header) · wp-page / wp-post (contenu) · cpt_layouts (footer). C'est le discriminant fiable contenu/chrome — aucune heuristique closest("header") n'est nécessaire.
Mais 14 des 28 pages ne sont pas du Elementor du tout :
| Rendu | Pages | Règle de bande |
|---|---|---|
elementor | accueil, vins, 7 fiches vin, club, contact, idées-cadeaux, goodies, politique | accueil = layout LEGACY (.elementor-top-section) · toutes les autres = conteneurs flexbox (.e-con.e-parent) |
theme-archive | cocktails, news, news-events, evenements | boucle WP du thème : .posts_container > article.post_item |
theme-post | les 10 articles | corps d'article du thème (.post_content) |
Le champ renderer de pdn.json porte cette information pour que le générateur choisisse l'émetteur au lieu de deviner.
🔥 Piège déjà payé ici. Une extraction « sections Elementor » seule renvoie 1 bande pour
/cocktails/— une page de 4383 px. Le « la page est vide » venait du sélecteur, pas du site. Même famille d'erreur que les quatre orthographes de.rowchez chevaliers : la règle doit être structurelle et vérifiée, jamais supposée.
🔥 Course JS sur le menu. Le
<ul>de navigation n'acquiertsc_layouts_menu_nav … inited sfqu'après l'init du thème. Extraire surnetworkidlerenvoie une nav vide, sans erreur — exactement ce qui a livré chevaliers avec un.site-menuvide. Le scraper attend désormais explicitementul.sc_layouts_menu_nav.
2. Portée — les pages « commerce-adjacentes » SONT dans le périmètre
« Hors périmètre : e-commerce » = la transaction seule. PDN n'a pas de boutique : ses pages présentent et renvoient vers gilliard.ch. Elles sont donc des pages de contenu ordinaires et sont toutes à construire, à l'URL réelle du live :
/vins/+ les 7 fiches vin (bouton ACHETER →gilliard.ch/fr/vins/les-classiques/…)/idees-cadeaux/— 7 coffrets, chacun avec un ACHETER →gilliard.ch/fr/vins/coffrets-cadeaux/…/goodies/— 9 articles, chacun avec un ACHETER →gilliard.ch/fr/vins/goodies/…
Ces liens sortants se sèment en URL absolue du live. Les liens internes passent par le nœud (UrlMode.Relative). Rien ne reste en #.
3. La carte des bandes → blocs
Zéro nouveau bloc, zéro nouveau JS, zéro cycle ModelsBuilder. Tout est couvert par la bibliothèque partagée existante ; pdnContentPage s'autorise déjà lui-même comme enfant, donc /vins/<slug> s'imbrique sans changement de schéma.
Accueil (7 bandes, h=6484)
| # | Bande live | h | Bloc |
|---|---|---|---|
| 0 | Slider Revolution | 760 | heroSlider + heroSlide |
| 1 | 2 col · 2 images + h2 + texte + bouton « Nos vins » | 562 | mediaText |
| 2 | h2 « Découvrez nos vins » + 7 × (image + texte + DÉCOUVRIR) | 1683 | cardCollection (7 cartes → les 7 fiches vin) |
| 3 | 2 col · h2 club + texte + « S'inscrire » + image | 746 | mediaText |
| 4 | h2 « Idées de cocktails » + trx_sc_blogger + « Tous les cocktails » | 818 | childListing (source → Cocktails) |
| 5 | h2 « News & Events » + trx_sc_blogger + bouton | 696 | childListing (source → News & Events) |
| 6 | h2 « Suivez-nous sur Instagram ! » + feed Smash Balloon | 684 | mediaGallery — masqué dans config.js (flux API live) |
/vins/ (14 bandes) — 6 lignes alternées + espaceurs
h1 150 px. Six lignes mediaText 2-colonnes (Ice, Ice rosé, Johannisberg, Rosé, Rouge, Mousseux), h2 57,1 px, chacune avec « Découvrir » → sa fiche, séparées par des espaceurs de 220 px.
⚠️ Écart mesuré à confirmer : l'accueil présente 7 vins,
/vins/n'en liste que 6 (ice-0-0absent). Ce n'est pas une omission de notre part — c'est l'état du live. À reproduire tel quel.
Fiche vin ×7 (6 bandes, h≈1935-2056) — un seul gabarit
| # | Bande live | Bloc |
|---|---|---|
| 1 | 2 col · h1 70 px + texte + ACHETER + 3 images | mediaText display="product-detail" (déjà construit pour gilliard) |
| 3 | h2 « Détails » 35 px | titre de section |
| 4 | 7 × icon-box | cardCollection display="facts" (= le « En bref … » de gilliard) |
⚠️ Sur
ice-0-0, 3 des 7icon-boxsont vides (titre et description vides). Ce sont des cales de mise en page, pas du contenu : ne pas semer de faits vides, ne pas inventer de contenu pour les remplir.
/idees-cadeaux/ et /goodies/
Hero (h1 150 px + texte) puis une seule bande grille : 7 (coffrets) / 9 (goodies) × (image + texte + ACHETER) → cardCollection. Rien d'autre.
/club/
Hero · mediaText (h2 35 px + « S'inscrire ») · h2 + html (formulaire d'inscription) · h2 « Profitez d'avantages » + 3 icon-box + bouton → cardCollection display="facts".
/contact/
Hero h1 150 px · 2 col : titres + texte + icon-list + Contact Form 7 → formBlock (front-end only, comme gilliard/chevaliers) · « Suivez-nous sur les réseaux ! » + icon-list ×2 · trx_sc_googlemap → bloc map (déjà consent-gated).
/politique-de-confidentialite/
11 bandes h3 38,4 px + texte, dont un trx_sc_table (tableau de cookies) → textPage. Le texte est publié sur le live : le reprendre verbatim, jamais de placeholder.
Listings + articles (14 pages, moteur « thème »)
/cocktails/ (4), /news/ (5), /news-events/ (6), /evenements/ (1) → bandeau de titre Elementor + boucle .post_item (carte 848 px : image, date, catégorie, extrait) → childListing. Les 10 articles → pageHero + corps verbatim (articleFields).
4. Structure backoffice (arbre de contenu)
⚠️ Les articles sont à la RACINE, pas sous leur listing
Mesuré : le live sert /pink-watermelon/, /gilliarday-festival-…/ — au premier niveau, pas /cocktails/pink-watermelon/. Umbraco dérivant l'URL de la position dans l'arbre, les 10 articles sont donc enfants directs de la racine PDN, et les quatre listings sont des vues (childListing avec source + filterCategory), pas des parents.
Porte de Novembre pdnHome (1383) siteSettings + bandes de l'accueil
├─ Nos vins pdnContentPage /vins/
│ ├─ Johannisberg … pdnContentPage /vins/johannisberg-pdn/ (×7 fiches)
├─ Cocktails pdnContentPage childListing source=racine filterCategory=Cocktail
├─ News pdnContentPage childListing … filterCategory=News
├─ Events pdnContentPage childListing … filterCategory=Event
├─ News & Events pdnContentPage childListing … filterCategory=News,Event ← voir ci-dessous
├─ Le Club / Idées cadeaux / Goodies / Contact pdnContentPage
├─ Politique de confidentialité textPage
└─ 10 articles pdnArticle /pink-watermelon/ … (à la racine = URL du live)Le filtre par catégorie exclut naturellement les pages : elles n'ont pas de propriété category, donc un filterCategory renseigné ne retient que les articles.
Catégories réelles (mesurées)
Cocktail ×4 · News ×5 · Event ×1. /news-events/ liste News + Event (6), tri date-desc.
pdnArticle — TRANCHÉ : la coquille est nécessaire
Question laissée ouverte au passage précédent, désormais résolue par la mesure : les listings affichent une date et une catégorie, et childListing les lit en untyped (c.Value<string>("category"), publishDate). pdnContentPage ne porte aucune des deux. Il faut donc une coquille pdnArticle = pageHero + pageSettings + articleFields (category / body / author / publishDate) + pdnCanvas, zéro propriété propre — sur le modèle de chevaliersEvent. Coût : un fichier uSync + UN cycle ModelsBuilder, confiné au worktree.
C'est le seul changement de schéma de tout le chantier PDN.
DataType : rien à faire
PDN - Content Blocks autorise déjà les 10 blocs dont la carte a besoin — heroSlider, cardCollection, mediaText, richIntro, ctaBanner, formBlock, map, newsletterSignup, mediaGallery, childListing. Aucune modification de DataType.
Un ajustement additif à childListing
/news-events/ agrège deux catégories ; filterCategory n'en épingle qu'une. Correctif : accepter une liste séparée par des virgules dans childListing.cshtml (le champ est un simple TextBox). Rétro-compatible, sans changement de DataType ni de modèle — une valeur unique continue de fonctionner à l'identique.
5. Thème — ce que la palette doit renverser
Sombre : rose #FC8DA3, ambre #FFCC66. Police Gotham Pro (commerciale) → Montserrat, déjà contractualisé dans tools/fidelity/config.js (SHARED_FONTS) — rien à ajouter.
⚠️
var()ne se résout pas dans une SVG en data-URI : les 3 icônes de_card-collection.scssont l'or de gilliard (fill='%238e784c') en dur. Le thème sombre doit redéclarer la déclarationbackgroundentière dansthemes/pdn/_overrides.scss.
Règle : 2 thèmes le veulent ⇒ token dans base/. 1 seul ⇒ themes/pdn/_overrides.scss.
6. Masques déjà écrits (tools/fidelity/config.js)
#cmplz-cookiebanner-container— bandeau Complianz, live uniquement#sb_instagram— flux Smash Balloon live par API ; nous semons unmediaGallery

