Conversation
Premier palier de support de Next 16 (peer next ^16 ajoute). Verifie sans changement de comportement : 17 URLs, codes HTTP et metadonnees (title, canonical, Open Graph) identiques a la baseline.
…endances mortes)
- next.config: images.domains (deprecie) -> images.remotePatterns, equivalent exact
verifie par test d'optimisation d'image (domaines autorises OK, domaine inconnu 400).
- layouts: ajout de data-scroll-behavior="smooth" sur <html> (requis par Next 16).
- suppression de 17 dependances sans aucun usage dans le code : react-confetti,
next-video, mdast-util-toc, rehype-{autolink-headings,raw,slug,stringify},
remark-{parse,rehype}, unified, @radix-ui/react-{switch,tooltip,label,navigation-menu},
class-variance-authority, tailwindcss-animate, et @strapi/strapi (devDep lourde).
- suppression des types Strapi generes orphelins (src/types/strapi/generated/),
importes par personne et seule raison de la presence de @strapi/strapi.
Verifie : 17 URLs, codes HTTP et metadonnees identiques a la baseline.
433 paquets en moins dans l'installation.
…Storybook La config racine ne branchait aucun plugin Next, React, a11y ou Storybook alors que les paquets etaient deja en dependance, et les scripts s'appuyaient sur `next lint` (supprime en Next 16). - eslint.config.mjs : base @antfu/eslint-config, etendue de @next/eslint-plugin-next, jsx-a11y et eslint-plugin-storybook. - Couche de forme (style/*) et tri d'imports desactives : le depot n'a jamais eu de formateur, ces regles produisaient ~3050 erreurs sans rapport avec la correction du code. Le formatage relevera d'un diff dedie. - Signal restant : 49 erreurs / 237 avertissements, tous de fond, dont 4 appels de hooks conditionnels (react-hooks/rules-of-hooks) et 4 problemes a11y. - Scripts : `lint` = eslint ., `typecheck` = tsc --noEmit, expose a la racine. - CI : .github/workflows/quality.yml (non bloquant, cf. TASK-12). Verifie : build OK, 17 URLs et metadonnees identiques a la baseline.
Le plugin OpenAPI de Strapi declare `populate` et `fields` comme de simples chaines,
alors que le frontend utilise partout la syntaxe imbriquee. Un post-traitement
(frontend/scripts/widen-strapi-query-types.mjs) elargit 54 declarations apres
generation et est branche dans `generate:types` : la correction survit a toute
regeneration.
Passe le passif TypeScript de 198 a 181 erreurs.
Diagnostic complet du reste dans .artifacts/task4-typescript-backlog.md : la cause
principale est un snapshot de documentation Strapi incomplet pour plusieurs relations
(About.board_of_directors et About.employees declares en { id, documentId }), dont la
regeneration demande de faire tourner le backend avec une base Postgres.
- next 14.2.14 -> 15.5.25 - react / react-dom 18.3.1 -> 19.3.0 - @types/react(-dom) -> ^19 Verification : build OK, 17 URLs comparees a la baseline (codes HTTP et metadonnees head identiques), controle navigateur (TTFB 61-192 ms, LCP 280-808 ms, CLS 0-0.07), accoredeon FAQ interactif, aucune erreur console applicative. Paires compatibles : @storybook/nextjs-vite 9 (next ^14||^15, react ^19.0.0-beta), storybook-next-intl 2.0.13, motion. Decouverte : les pages rendent DEUX balises <html> imbriquees (app/layout.tsx et app/[locale]/layout.tsx). C'est pre-existant (present dans la baseline Next 14), mais provoque une erreur d'hydratation React #418 sur chaque page. Non corrige ici (hors perimetre, refactor a part).
Codemod officiel @next/codemod next-async-request-api sur les 16 pages de
app/[locale] : `params` et `searchParams` passes de `{ ... }` a
`Promise<{ ... }>` puis resolus avec `await`.
La sortie du codemod a ete remise en forme (types de props sur une ligne,
destructuration directe) et deux fonctions dont jscodeshift avait casse
l'indentation ont ete reecrites.
Verification : build OK, 17 URLs identiques a la baseline, pagination de
/nos-evenements fonctionnelle (page 1 != page 2, lien page 3 present).
- next 15.5.25 -> 16.3.5, @next/eslint-plugin-next -> 16.3.5 - next.config.mjs : suppression du bloc `eslint` (option retiree en Next 16) Correction exigee par Turbopack (plus strict que webpack) : plusieurs composants utilisaient des hooks React sans directive 'use client'. Ils etaient tolerés tant qu'ils n'etaient atteints que par des composants clients, mais le barrel `@/components` est importe par app/[locale]/layout.tsx (Server Component), ce qui exposait Pagination.tsx. Directive ajoutee a Pagination, ImagesCarousel, ProjectCarousel, TestimoniesCarousel, ProjectListBlock et hooks/useMounted. Pagination.tsx importait par ailleurs useEffect/useState sans les utiliser. Verification : build Turbopack OK, table des routes identique, 17 URLs identiques a la baseline (codes HTTP + metadonnees), pagination fonctionnelle, middleware next-intl OK (/fr/* redirige en 307, /en en 404 car locales=['fr']), optimisation d'image OK (hote autorise 404, hote refuse 400), controle navigateur TTFB 65-116 ms / LCP 288-580 ms / CLS 0, aucune erreur console nouvelle (seul demeure le #418 pre-existant).
app/layout.tsx et app/[locale]/layout.tsx rendaient chacun <html>/<body>, ce qui produisait deux balises <html> imbriquees : du HTML invalide qui faisait echouer l'hydratation de React sur TOUTES les pages (erreur #418, React abandonnait le rendu serveur et reconstruisait l'arbre cote client). Bug pre-existant (present dans la baseline Next 14), mais qui devenait le seul defaut restant apres le passage a Next 16. Le layout racine porte desormais seul <html>, <head> (scripts IRaiser et Plausible) et <body>, avec les classes et le style que portait le layout de locale. Le layout de locale ne rend plus que les providers, l'en-tete, le main et le pied de page. Verification : 17 URLs identiques a la baseline, metadonnees identiques, captures d'ecran pleine page AVANT/APRES strictement identiques (md5) sur /, /projets, /nous-connaitre et /nos-evenements -- zero regression visuelle -- et plus aucune erreur d'hydratation sur les 5 pages testees, y compris la 404. Accordeon FAQ toujours fonctionnel apres interaction.
…e composants
Storybook 9 ne compilait plus sous Next 16 : @storybook/nextjs-vite@9 transmet
l'option SWC "disablePageConfig", supprimee des versions recentes de @swc/core
("unknown field disablePageConfig").
- storybook et les @storybook/* : 9.0.18 -> 10.6.0
- @chromatic-com/storybook : ^4.0.1 -> ^5.3.1
- eslint-plugin-storybook : ^9.0.18 -> ^10.6.0
- storybook-next-intl : ^2.0.13 -> ^10.1.4
- vitest / @vitest/browser / @vitest/coverage-v8 : 3.2.4 -> 4.1.11
+ ajout de @vitest/browser-playwright (Vitest 4 sort le fournisseur Playwright
dans un paquet dedie et en fait une fabrique : provider: playwright())
Les tests de composants n'avaient JAMAIS tourne : aucun script "test" n'existait
et aucune etape de CI ne les lancait. Une fois rendus executables, 237 tests
tournaient dont 67 en echec. Deux causes ont ete corrigees :
1. .storybook/vitest.setup.ts appelait setProjectAnnotations sans y passer
storybook-next-intl ; cet appel remplace les annotations des addons au lieu
de les completer, donc le NextIntlClientProvider n'existait pas dans les
tests (67 echecs "Failed to call useTranslations ... context ... not found").
2. Les fixtures de ProjectListCard.stories.tsx et ProjectListBlock.stories.tsx
etaient restees sur une ancienne API : propriete "association: string" au lieu
de "partners: string[]", et propriete obligatoire "IFilter.filterType"
manquante. Cela faisait planter ProjectListCard au rendu (appel de
partners.map sur undefined) et representait 22 erreurs TypeScript.
Ajout de la variable PLAYWRIGHT_EXECUTABLE_PATH dans vitest.config.ts pour
pouvoir utiliser le Chromium deja present sur la machine (NixOS) au lieu du
binaire telecharge par Playwright, indisponible ici.
Resultat : 48 fichiers / 237 tests verts, build Storybook vert, build Next vert
avec table des routes identique, 17 URLs et metadonnees identiques a la
baseline. Erreurs TypeScript : 183 -> 161.
…us-connaitre" tolerante
Deux defauts mis au jour en verifiant le rendu du contenu CMS apres l'upgrade.
1. frontend/src/lib/strapi-client.ts
Le client envoyait systematiquement l'en-tete
Authorization: Bearer ${process.env.STRAPI_API_TOKEN}. Sans jeton, cela produit
litteralement "Bearer undefined", que Strapi rejette par un 401 sur TOUTES les
routes -- y compris les routes publiques accessibles anonymement. Comme chaque
page fait "if (!data?.data) return null", le site entier rendait des pages vides
SANS AUCUNE ERREUR VISIBLE.
L'en-tete n'est desormais envoye que si un jeton existe reellement. Mesure sur
/staging local, sans STRAPI_API_TOKEN :
/ 142 720 octets -> 235 306 octets, et un <h1> apparait
/nous-connaitre, /ressources/carbonbombs-org, /projets/2-tonnes,
/foire-aux-questions... rendent leur contenu CMS au lieu d'une coquille vide.
En production, ou le jeton est present, le comportement est inchange au
caractere pres.
2. frontend/src/app/[locale]/about/about.tsx
Une fois les requetes authentifiees correctement, /nous-connaitre plantait en
500 "Cannot read properties of undefined (reading 'map')" : les relations du CMS
(board_of_directors, employees, scientific_committee, strategic_committee,
division_managers, funders) peuvent etre absentes de la reponse (relation non
renseignee, ou droits d'acces differents selon le jeton). Les transformations
tolerent desormais l'absence et retombent sur un tableau vide ; les acces
imbriques (image?.url, cta?.text) sont proteges de la meme facon.
Cette page etait DEJA en 500 sur main une fois le point 1 corrige : la
correction la fait passer en 200 (201 513 octets de contenu rendu) et supprime
les deux TypeError cote serveur. Le compteur d'erreurs TypeScript passe de 161 a
141 du meme coup.
Verification de non-regression
------------------------------
La baseline precedente (main, Next 14) avait ete capturee avec le client
defectueux, donc sur des pages vides : elle ne prouvait rien sur le rendu du
contenu. Une baseline a donc ete recapturee dans un worktree git sur main
(.artifacts/baseline-content/) avec ONLY le point 1 applique, puis comparee au
texte visible page par page :
11 / 17 pages : texte visible strictement identique
5 / 17 pages : texte identique au caractere pres (multiensemble de caracteres
egal, meme nombre d'occurrences de chaque chaine) ; seule la
position de l'element <title> dans le flux differe, Next 14
l'emettant en tete de corps et Next 16 en fin de corps
1 / 17 pages : /nous-connaitre, 500 -> 200 (amelioration, cf. point 2)
Les codes HTTP des 17 URLs sont inchanges par ailleurs (200, 404 reel, 405 sur
l'API newsletter).
frontend/server-wrapper.js se contentait de re-affecter des variables a
elles-memes :
process.env.BREVO_API_KEY = process.env.BREVO_API_KEY;
process.env.STRAPI_API_TOKEN = process.env.STRAPI_API_TOKEN;
process.env.STRAPI_API_URL = process.env.STRAPI_API_URL;
Ces instructions n'ont aucun effet (elles declenchaient au passage une erreur
ESLint no-self-assign). Le serveur standalone de Next lit les variables
d'environnement au moment de la requete : seules les variables NEXT_PUBLIC_*
sont figees a la compilation, et aucune des trois ci-dessus n'en fait partie.
Le CMD passe donc de "node frontend/server-wrapper.js" a
"node frontend/server.js" et le fichier est supprime.
Verification, faute de Docker dans cet environnement : la disposition de
l'image a ete reproduite a l'identique (COPY de .next/standalone, .next/static,
public, messages) puis le serveur lance avec les variables fournies au runtime,
sans .env.local. Resultat, 0 erreur serveur :
/ 200 235 306 octets
/nous-connaitre 200 201 513 octets
/ressources/carbonbombs-org 200 167 223 octets
/projets/2-tonnes 200 166 200 octets
/page-inexistante-pour-test-404 404
/api/newsletter 405
Constat annexe, non corrige car hors perimetre : docker-compose.yml est
desynchronise du Dockerfile (il vise une etape de build "frontend" inexistante,
des chemins /prod/frontend, et declare STRAPI_URL au lieu de STRAPI_API_URL).
La CI construit l'image a partir de docker/frontend/Dockerfile, pas via ce
fichier compose.
A chaque "next dev", Next 16.3 ecrit frontend/AGENTS.md et frontend/CLAUDE.md (regles a destination des agents de code). Ces fichiers apparaissaient en fichiers non suivis et salissaient git status. Ils sont desormais ignores, comme le sont deja .next, storybook-static et next-env.d.ts. Le comportement du compilateur n'est pas modifie ; l'ecriture peut aussi etre desactivee avec "agentRules: false" dans next.config.mjs, ce que l'on ne fait pas ici pour laisser le fichier disponible localement.
Deux messages presents depuis le passage a Next 16, tous deux visibles au
demarrage de "next dev" comme au "next build", et tous deux passes inapercus
lors de la validation initiale (le build n'etait filtre que sur les lignes
"Compiled successfully" et "Error fetching redirects").
1. Convention "middleware" depreciee
The "middleware" file convention is deprecated. Please use "proxy" instead.
src/middleware.js est renomme src/proxy.js (aucune autre modification : le
fichier ne contient qu'un export default de next-intl). Next 16 refuse la
coexistence des deux fichiers, c'est donc bien un renommage.
Le codemod officiel ne fait rien ici : il ne reecrit que les exports NOMMES
("export function middleware", "export { middleware }"). Notre fichier exporte
"createMiddleware(routing)" par defaut, donc il ressort en "0 ok, 262
unmodified". La migration est faite a la main. L'export par defaut est bien
accepte : la ligne de trace du serveur passe a "proxy.ts: 336ms" et le routage
i18n est inchange (verifie avant/apres) :
/ -> 200 /fr -> 307 vers / /fr/projets -> 307 vers /projets
/en -> 404 /projets -> 200 /api/newsletter -> 405
/page-inexistante-pour-test-404 -> 404 /images/bg-paper.jpg -> 200
2. "Error fetching redirects: TypeError: data.map is not a function"
Sans STRAPI_API_TOKEN, /redirects repond 403 avec un corps d'erreur JSON, que
l'ancien code passait directement a data.map(). Le TypeError masquait la vraie
cause ; il apparaissait deux fois par chargement de configuration, en dev comme
en build. getRedirects verifie desormais la presence des variables, res.ok, puis
le type de la reponse, et journalise un message explicite :
[redirects] STRAPI_API_URL ou STRAPI_API_TOKEN absent : aucune redirection du
CMS ne sera chargee.
Ce point reste A TRAITER pour la production : next.config.mjs est evalue a la
COMPILATION, donc sans jeton au moment du "docker build", aucune redirection du
CMS n'est embarquee dans routes-manifest.json. Le correctif rend le probleme
visible et lisible, il ne le resout pas.
Verifications
-------------
- next build : vert, 9,0 s, plus aucun des deux messages.
- 17 URLs en production : codes HTTP et tailles identiques a la capture
precedente ; 0 erreur serveur.
- next dev : 9 pages parcourues au navigateur, 0 erreur de page, 0 erreur
console. Accordeon de la FAQ fonctionnel (1882 -> 2087 caracteres de texte),
navigation client / -> /projets/carbon-bombs-v2 sans erreur.
- La baseline Next 14 corrigee garde /nous-connaitre en 500 (page d'erreur,
<html id="__next_error__">) ; la branche le rend en 200 avec 6 h2 et 18 images.
…igateur
Le script "test" existe depuis le passage a Storybook 10, mais rien ne
l'indiquait dans le README, et l'echec par defaut sur cette machine est
difficile a diagnostiquer :
Error: browserType.launch:
Host system is missing dependencies to run browsers.
Le Chromium telecharge par Playwright ne demarre pas sur NixOS (bibliotheques
systeme absentes : libXcomposite, libgbm, libasound...). Le contournement existait
deja dans vitest.config.ts (PLAYWRIGHT_EXECUTABLE_PATH) mais uniquement sous
forme de commentaire de code.
Le README documente desormais les deux commandes de test et la variable, avec le
message d'erreur exact a reconnaitre. Avec elle :
48 fichiers / 237 tests verts
DnzzL
added this pull request to stack #400
September 29, 2026 13:25
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cette branche fait passer le frontend de Next.js 14.2 à 16.3, avec React 19, next-intl 4.14 et Storybook 10. Elle progresse par paliers — Next 15, puis Next 16, chacun avec sa vérification — plutôt qu'en un seul saut, pour qu'on sache quelle étape aurait cassé quoi.
Deux défauts préexistants, mis au jour par la montée
Le layout racine imbriquait deux balises
<html>, ce qui provoquait un échec d'hydratation sur toutes les pages. Le client Strapi envoyait par ailleursBearer undefineddès qu'aucun jeton n'était configuré, ce que Strapi rejette par un 401 sur toutes les routes, y compris publiques. Comme chaque page retombait sur un rendu vide sans lever d'erreur, le site entier s'affichait blanc sans le moindre signe — ni erreur serveur, ni page en échec.La branche corrige aussi les types Strapi générés, dont le
populateet lefieldsétaient trop étroits : le compteur d'erreurs TypeScript passe de 198 à 141.Vérifications
Le build passe. Les 17 URL répondent comme avant la montée, avec des métadonnées identiques. L'audit Lighthouse à contenu égal progresse sensiblement : la performance de l'accueil passe de 55 à 77, et les bonnes pratiques de 96 à 100. Les 237 tests de composants, qui n'avaient jamais pu tourner faute de script, sont désormais exécutables et verts.
Ce qu'il reste à savoir avant de relire
Les erreurs TypeScript restantes (141) et ESLint (43) ne bloquent ni le build ni la CI :
ignoreBuildErrorsest toujours actif et le workflow de qualité est encontinue-on-error. Un chantier de remédiation les traite séparément, cette branche ne les ferme pas.Enfin, l'image Docker doit recevoir
STRAPI_API_TOKENau moment dubuild. Les redirections du CMS sont évaluées à la compilation denext.config.mjs: sans jeton, elles disparaissent de l'image sans que le build échoue.