Skip to content

fix(react-dsfr): promote anti-flash pattern in SKILL.md#17

Open
benoitvx wants to merge 1 commit into
mainfrom
fix/react-dsfr-anti-flash-promoted
Open

fix(react-dsfr): promote anti-flash pattern in SKILL.md#17
benoitvx wants to merge 1 commit into
mainfrom
fix/react-dsfr-anti-flash-promoted

Conversation

@benoitvx
Copy link
Copy Markdown
Collaborator

@benoitvx benoitvx commented May 21, 2026

Contexte

Le flash dark mode au chargement initial est la régression la plus courante quand on setup react-dsfr avec Next.js App Router. Le fix est déjà documenté dans references/setup.md (createGetHtmlAttributes + getScriptToRunAsap injecté dans <head>), mais Claude ne l'applique pas spontanément quand il génère un layout.tsx.

Symptôme confirmé

Sur un test fait, je constate que le src/app/layout.tsx généré contient :

<html {...getHtmlAttributes({ lang })}>
  <head>
    <link rel=\"stylesheet\" href=\"/dsfr/dsfr.min.css\" />
    <link rel=\"stylesheet\" href=\"/dsfr/utility/icons/icons.min.css\" />
  </head>

getHtmlAttributes est bien utilisé, mais aucun script anti-flash dans <head>. Résultat : flash visible au chargement en mode sombre.

Cause racine — deux problèmes dans la skill

1. Le SKILL.md n'attire pas l'attention sur l'anti-flash

Le SKILL.md ne mentionnait le problème que dans une sous-section Couleurs et thème, sous cette forme :

Attention au flash dark mode : en Next.js App Router, utiliser getHtmlAttributes() + <StartDsfr /> + <DsfrHead /> pour éviter le flash blanc au chargement.

Deux soucis :

  • Les noms cités (<StartDsfr />, <DsfrHead />, getHtmlAttributes()) sont les anciens noms pré-v1.30. Le package les a renommés en StartDsfrOnHydration, DsfrHeadBase, createGetHtmlAttributes — les anciens n'existent plus.
  • L'élément vraiment critique — getScriptToRunAsap() injecté dans <head>n'était pas mentionné.

Donc même si Claude lit cette ligne, il n'a pas le pattern correct sous les yeux.

2. Le references/setup.md présente d'abord un layout cassé

La section Next.js App Router de references/setup.md était organisée comme ça :

  1. Étape 1 : next.config.mjs avec transpilePackages
  2. Étape 2 : layout.tsx (sans script anti-flash dans <head>) ← le pattern présenté ici est cassé
  3. Chargement des icônes
  4. Prévention du flash dark mode (l'explication arrivait après)
  5. Setup sans transpilePackages (qui contenait enfin le pattern correct avec anti-flash)
  6. Re-initialisation DSFR

Claude lit l'étape 2 linéairement, applique le code, et n'a aucune raison de descendre lire les 4 sections en dessous. La logique est inversée : le pattern correct devrait être en premier, et les variantes en dessous.

Changements

skills/react-dsfr/SKILL.md (+64 / -3 lignes)

  • Nouvelle section ## Setup Next.js App Router en tête, juste après Import pattern, avec :
    • Le code complet minimal du layout.tsx (Pattern 1 : imports directs, sans transpilePackages)
    • Un avertissement explicite : ⚠️ sans getScriptToRunAsap() dans <head>, le mode sombre cause un flash blanc visible
    • Les 3 éléments critiques listés avec leur rôle : createGetHtmlAttributes, getScriptToRunAsap, StartDsfrOnHydration
    • Les noms v1.30+ documentés + les anciens noms explicitement marqués comme n'existant plus
    • Renvoi vers references/setup.md pour les variantes
  • Remplacement du one-liner obsolète dans Couleurs et thème par une courte cross-reference vers la nouvelle section.
  • Mise à jour du pointeur Setup par framework en bas.

skills/react-dsfr/references/setup.md (+150 / -65 lignes)

Réorganisation de la section Next.js App Router :

  • Explication du flash dark mode en tête (avant les patterns) : pourquoi c'est un problème, quels éléments l'évitent.
  • Pattern 1 — Recommandé : layout.tsx complet avec anti-flash, sans transpilePackages. Le pattern qui marche, présenté en premier.
  • Pattern 2 — Variante : DsfrHeadBase + transpilePackages + règle webpack .woff2. Présenté comme alternative pour ceux qui ont déjà transpilePackages pour d'autres raisons.
  • Tableau de comparaison entre les deux patterns.
  • Chargement des icônes DSFR : inchangé sur le fond.
  • Re-initialisation DSFR après hydratation React : précise que StartDsfrOnHydration (déjà inclus dans les deux patterns) fait le boulot par défaut ; le DsfrStartup manuel reste comme fallback pour les cas exotiques.

Aucun changement sur references/components.md, les autres frameworks (Vite, Next.js Pages Router, CRA), ou la section ESLint.

Périmètre vérifié

Ces changements ne touchent que la skill react-dsfr. Les autres skills (rgaa, securite-anssi, datagouv-apis, lasuite-ui-kit) sont intactes.

Test plan

  • Vérifier que le src/app/layout.tsx généré contient bien le <script> issu de getScriptToRunAsap dans <head>
  • Vérifier visuellement (mode sombre dans le navigateur, rechargement) : plus de flash blanc au chargement
  • Lancer la skill rgaa sur le code généré pour vérifier que les attributs SSR (data-fr-scheme, etc.) sont bien posés
  • Vérifier que la skill n'introduit pas de régression sur d'autres patterns du SKILL.md (Header, Footer, formulaires, grille)

🤖 Generated with Claude Code

The dark mode flash on initial load is the most common regression
when setting up react-dsfr with Next.js App Router. The fix has
always been in references/setup.md (createGetHtmlAttributes +
getScriptToRunAsap injected in <head>) but two issues prevented
Claude from applying it:

1. The SKILL.md only mentioned the flash issue in passing, in a
   "Couleurs et thème" subsection, with obsolete pre-v1.30 names
   (StartDsfr, DsfrHead) and without mentioning the critical
   getScriptToRunAsap script.

2. The references/setup.md Next.js App Router section showed a
   layout.tsx WITHOUT the anti-flash script as step 2, then
   documented the flash issue separately in a later section.
   Claude reads step 2 linearly and applies the broken pattern.

Symptom confirmed in Run 2 of the eig-vibe migration test plan
(test-cadrer-20260521, 2026-05-21): generated layout.tsx had
getHtmlAttributes but no script in <head>, causing the visible
dark/light glitch.

Changes:

SKILL.md:
- New top-level "## Setup Next.js App Router" section right after
  "Import pattern", with the complete minimal layout.tsx including
  the anti-flash script and a clear warning that omitting
  getScriptToRunAsap causes the flash.
- Listed the three critical elements (createGetHtmlAttributes,
  getScriptToRunAsap, StartDsfrOnHydration) with their role.
- Documented v1.30+ names and explicitly listed obsolete names to
  avoid.
- Replaced the obsolete one-liner in "Couleurs et thème" by a
  short cross-reference to the new section.
- Updated the bottom "Setup par framework" pointer.

references/setup.md (Next.js App Router section):
- Moved the "flash dark mode" explanation up, before the layout
  patterns.
- Reorganized into two clearly labeled patterns:
  - Pattern 1 (recommended): direct imports, no transpilePackages,
    anti-flash injected manually. This is the working pattern.
  - Pattern 2 (variant): DsfrHeadBase + transpilePackages +
    webpack rule for .woff2.
- Added a comparison table to help choose.
- Updated "Re-initialisation DSFR" section to acknowledge that
  StartDsfrOnHydration handles this by default; kept the manual
  DsfrStartup fallback for edge cases.

No change to skills/react-dsfr/references/components.md.
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the documentation for react-dsfr to include comprehensive setup instructions for the Next.js App Router (v1.30+). It introduces two distinct setup patterns: a recommended approach using direct imports that eliminates the need for transpilePackages, and an alternative using DsfrHeadBase. The updates specifically address common issues such as the "dark mode flash" by detailing the use of createGetHtmlAttributes() and getScriptToRunAsap(), and ensure proper DOM re-initialization via StartDsfrOnHydration. I have no feedback to provide as there were no review comments.

@benoitvx benoitvx requested a review from kaaloo May 21, 2026 14:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant