Skip to content

PDN migration — RESUME HANDOFF (written 2026-07-30)

Working handoff for the Porte de Novembre (portedenovembre.ch) migration. Read this first, then .claude/docs/domain/pdn-migration-plan.md and the memory notes it links. This file says: what is DONE, what is LEFT, HOW to do it, and a paste-ready resume prompt at the very bottom.


0. State of the branch (as of 2026-07-30)

  • Branch develop, NOT pushed (user pushes). User is sole commit author, NO Co-Authored-By trailer.
  • ~15 PDN commits landed this session (fonts, age-gate removal, interior hero, footer seed, card titles, bottles-media, wine-detail empty Détails, hero mask, probes). See the memory gilliard-migration.md tail (## 2026-07-29 — PDN RESUMED) for the exact commit list + hashes.
  • ⚠️ The working tree currently has UNCOMMITTED .cshtml edits made by the USER / a linter (ASCII-ising comments across many views: _MasterLayout, main.scss, childListing, BlogPost, Event, card, cardCollection, ctaBanner, HomePage, _listCard, ...). Do NOT revert or commit these — they are the user's. Reconcile before committing your own work (they may have committed by resume time).

⚠️ 1. CONCURRENCY — check before touching the server/DB

The user was doing backoffice work in a concurrent session. Before ANY of these, confirm it is safe:

  • GET /seed-pdnoverwrites backoffice content changes.
  • dotnet build / restarting the dev server — locks bin/Web.exe and interrupts their session.
  • Any DB write.

Read-only work (measuring LIVE, curl/Playwright GET of local pages, reading files) is fine anytime, but a concurrent re-publish can shift local pages under you.


2. THE DISCIPLINE (do not shortcut — this is why the last pass was criticised)

The home was gated on the pixel harness and that MISSED real defects, because the harness is blind to:

  1. Masked regions' internals. The Slider Revolution hero is masked (drifts per-slide). Masking exempts it from the pixel count only — you STILL must visually match its image scale, layout and transitions.
  2. Hover / focus / entrance transitions. They change no geometry and no static-screenshot pixel. They require the CDP interaction gate (tools/fidelity/interact.mjs, uses CSS.forcePseudoState) plus actually watching the animation. This gate was run for gilliard/chevaliers but NEVER for PDN.

The loop, per page AND per region/control:

  • Screenshot LIVE vs LOCAL at 375 / 768 / 1024 / 1440 / 1920 + read DOM/computed-CSS (geometry, typography, colour, image scale).
  • Run the CDP interaction check (hover/focus/active + entrance transitions) on every interactive/animated element.
  • Source of truth = live DOM + computed CSS, never the eye, never a code comment (comments have been wrong — e.g. the 153f348 hero "re-measure" was a regression). Verify every candidate vs live BEFORE and AFTER.
  • Fix the CAUSE; systemic-first (a token/shared rule fixes many pages); commit per root cause.
  • Document deviations in assets-substitues.md and masks in tools/fidelity/config.js with written reasons.

3. TOOLS & COMMANDS (all measured against live)

  • Local host: http://portedenovembre.localtest.me:12953 (paths == live paths, NO /fr/). Live: https://portedenovembre.ch. /de/ is out of scope.
  • Sweep (all PDN pages): MSYS_NO_PATHCONV=1 node tools/fidelity/sweep.mjs pdn --widths 1440 (add 375,768,1024,1440,1920 for the full pass). Reports -> tools/fidelity/reports/pdn/<name>/ (live/local/diff PNGs + report.json). Sweep pages are defined in tools/fidelity/sweep.mjs (PDN inventory added 2026-07-29).
  • Single page diff: MSYS_NO_PATHCONV=1 node tools/fidelity/diff.mjs --site pdn --path /X/ --local-path /X/ --widths 1440 --report-only
  • Interaction gate (CDP hover/focus): tools/fidelity/interact.mjs — the ONLY reliable way to measure hover; a bare Playwright .hover() silently misses off-screen elements. Use CSS.forcePseudoState.
  • Probes (in tools/fidelity/probes/, domcontentloaded + settle — live never reaches networkidle):pdn_theme.mjs <url> <w> <shot> (theme tokens + shot), pdn_fonts.mjs <url> <w> (painted text-node fonts), pdn_page.mjs <url> <w> <shot> (full-page shot + band structure). Write throwaway probes as _tmp_*.mjs INSIDE probes/ (Node resolves playwright from tools/fidelity/node_modules, so a scratchpad script can't import it) and delete after.
  • Build/run/seed loop (ONLY after the go-signal):taskkill //IM Web.exe //F -> dotnet build Gilliard.sln -> dotnet run --no-build --project src/Web/Web.csproj (bg) -> poll curl http://portedenovembre.localtest.me:12953/ for 200 -> curl .../seed-pdn. SCSS-only changes need just npm run --prefix src/Web build (no server restart; CSS is static). .cshtml/C# changes need the full rebuild+restart (runtime Razor does NOT hot-reload here).
  • Seeder is GENERATED: tools/seed-gen/pdn-gen.mjs (reads tools/seed-gen/data/pdn.json, scraped by pdn-bands.mjs) -> src/Web/Controllers/DevSeedPdnController.cs. NEVER hand-edit the controller — edit the generator and re-run node tools/seed-gen/pdn-gen.mjs.
  • Fonts: GothamPro is REAL (self-hosted, identity in config.js, NOT substituted), Yeseva One (display), Krona One (buttons). An unexpected family fails the harness.
  • Masks (config.js pdn): Complianz cookie banner, Instagram feed, the Slider Revolution home hero.

4. WHAT'S LEFT (the backlog — agreed order: FULL AUDIT across all pages, then fix worst-first)

4a. The agreed next move: FULL visual + CDP-interaction audit across ALL PDN pages

Region-by-region, 5 widths, screenshot + DOM/CSS + hover/focus/active + entrance transitions. Produce ONE complete measured defect list (systemic vs per-page), THEN fix systemically worst-first. Pages: home, vins, 7 wine details (/vins/{johannisberg-pdn,mousseux,ice-pdn,ice-rose-pdn,ice-0-0,rose-pdn,rouge-pdn}/), cocktails, news, evenements, news-events, club, goodies, idees-cadeaux, contact, politique-de-confidentialite. Note: the system-prompt for this project forbids spawning subagents unless the user asks — do it serially, or the user can opt into agents.

4b. Specific home defects the user flagged + MEASURED (2026-07-29) — do these in the audit

  • SHARE-slide bottle image TOO SMALL. Live 686w@1440 / 860w@1920 (~44-48vw); local stuck 593w at both. Cause 1: this session's 153f348 replaced the width-based sizing (width:min(47.6vw,860px), which matched live) with height:62%/max-width:46% — a regression. Cause 2: local hero image accueil-hero-1.png aspect 1.26 (593x471) ≠ live gamme_portedenovembre_gilliard aspect 1.86 (686x369) = DIFFERENT asset/crop. Fix: verify the local hero foreground IS live's SHARE asset, then size per-slide by WIDTH to hit 686/860 (SHARE = 7 bottles wide; Enjoy/Cheers = ~3 bottles narrower — 153f348 went height-based to stop those two blowing up, so reconcile per-slide, don't blind-revert). Rule lives in styles/themes/pdn/_overrides.scss .theme-pdn .hero-slider__product-figure.
  • "Découvrez nos vins" grid HOVER transition. Local .card-collection--bottles .g-card transitions only box-shadow; live card transitions all. ⚠️ My hover probe hit the WRONG live element (.sc_blogger_item = a blog teaser). RE-IDENTIFY the live wine-grid element and CDP-measure its rest->hover delta (transform/scale/opacity/filter) before replicating.
  • Slider image FADE-IN entrance. Live SR foreground image fades/moves in on slide change; our hero-slider has no matching entrance. Measure the live entrance, replicate on the hero-slider images.

4c. Per-page structural items already measured (P5)

  • Wine-detail TWO-COLUMN hero (7 pages, biggest). Live band-1 = ONE pink section: LEFT title Yeseva WHITE 60px @x85,y267 + body(white) + ACHETER (white bg/black text, x85,y597, 134x55); RIGHT bottle johannis.png @x649,y177 290x567 OVERLAPPING landscape photo johannisberg.jpg @x806,y150 500x619. Our build renders pageHero title at the 150px LISTING scale (centred) + a SEPARATE stacked mediaText--product-detail below => title DUPLICATED + wrong scale + wrong layout. Fix: fold band-1 into the pageHero (heroTitle 60 white left + heroText body + heroCta ACHETER; bottle+photo right image column) and DON'T emit the mediaText for band 1. ⚠️ pageHero is a SHARED composition (4 brands) — scope the two-column/60px/white to wine detail via a modifier and regression-check gilliard/chevaliers.
  • Listing-card LAYOUT (evenements/cocktails/news/news-events/idees-cadeaux). Live card = image + "EVENT" kicker(pink) + title(Yeseva black) + excerpt + arrow, transparent on amber. Ours = cards-blog: badge-on-image + white bar (title + chevron), no kicker/excerpt. Layout is fixable NOW; the excerpt TEXT is the WP excerpt field = NOT in the scrape (P6/WXR).
  • Footer STRUCTURE (content is correct now). Live = [logo + "Vins de la Maison Gilliard" + MAISON GILLIARD sublogo] [contact] [Liens] [Newsletter] + dark bar with socials IN the bar. Ours = [Liens][Newsletter][contact][socials] + dark bar, NO logo column, socials as a column. Needs a shared _footer.cshtml enhancement (logo column + socials-in-bar) or a documented deviation — cross-brand risk.
  • Article-detail body carries RAW ELEMENTOR markup (pdnArticle body on theme-post pages, generator ~line 556 emits richIntro from p.post.html). Standing rule: port the rendered result, never the plugin. Re-check the theme-post branch.

4d. FAVICONS (all brands) — user request 2026-07-30

_MasterLayout.cshtml (lines ~88-92) hardcodes ONE shared favicon set at /images/favicons/... (Umbraco template default) for ALL 4 brands, so PDN/gilliard/chevaliers all show the generic favicon. Fix: fetch each brand's LIVE favicon (PDN = portedenovembre.ch/wp-content/uploads/2024/11/cropped-favicon_porte_de_novembre-1-{32x32,192x192,180x180}.jpg; gilliard + chevaliers from their live <link rel=icon>), store per-theme (wwwroot/images/<theme>/favicons/ — those dirs already exist), and make the <link>s theme-scoped via the existing theme var (/images/@theme/favicons/...) with the shared set as fallback. Needs build+restart (part of the post-go-signal batch).

4e. BLOCKED — P6 exact content re-seed

The PDN WXR export still isn't available. When it arrives, parse it (tools/seed-gen/wxr-extract.mjs -> data/sources/pdn/), re-seed ALL PDN content verbatim (text, articles, product copy, images, dates, listing excerpts), then re-run fidelity. Until then, representative/approximated content stays.


5. PASTE-READY RESUME PROMPT

Resume the Porte de Novembre (PDN / portedenovembre.ch) migration.

FIRST, before touching the server/DB, ask me whether my concurrent backoffice session is closed and it's
safe to /seed-pdn, dotnet build, and restart the dev server. Do only read-only work until I confirm.

Read .claude/docs/domain/pdn-resume.md (the handoff — state, method, backlog, tools), then
.claude/docs/domain/pdn-migration-plan.md and the pdn-migration-plan + gilliard-migration memories. Follow
the SAME discipline as gilliard/chevaliers, no shortcuts, and specifically FIX THE THOROUGHNESS GAP that
the pixel harness caused: it is BLIND to (a) masked-region internals (the hero: image scale + transitions)
and (b) hover/focus/entrance transitions. So the agreed next move is a FULL per-region + CDP-interaction
audit across EVERY PDN page at 375/768/1024/1440/1920 (screenshot live vs local + DOM/CSS + hover/focus/
active + entrance animations via tools/fidelity/interact.mjs and the probes in tools/fidelity/probes/),
producing ONE complete measured defect list, then fix systemically worst-first — measure live BEFORE and
AFTER every candidate, commit per root cause, me as sole author with NO Co-Authored-By trailer.

Known measured defects to fold into the audit (details + numbers in pdn-resume.md §4): the SHARE-slide
bottle image is too small (my commit 153f348 regressed it + the local hero image is the wrong crop); the
"Découvrez nos vins" grid hover transition is missing; the slider image has no fade-in entrance; the 7
wine-detail pages need the two-column hero (title 60px white + body + ACHETER left, bottle overlapping a
landscape photo right, no duplicated 150px title); the listing cards need live's kicker+title+excerpt+arrow
layout (not badge+white-bar); the footer structure needs live's logo column + socials-in-copyright-bar; the
article-detail body still carries raw Elementor markup; and ADD PER-BRAND FAVICONS (all 4 brands currently
share the generic template favicon — fetch each site's live favicon and make _MasterLayout's favicon links
theme-scoped).

Restart the dev server on :12953 if it's down (steps in pdn-resume.md §3) — but only after I confirm it's
safe. Keep going autonomously; stop only for a content/seed decision. Do NOT do P6 (exact WXR content
re-seed) — the PDN WXR export still isn't available, so representative content stays. Do NOT spawn subagents
unless I ask.

Contributors

No contributors

Changelog

No recent changes