diff --git a/CLAUDE.md b/CLAUDE.md
index 89cb52f..0cdd1cd 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -373,7 +373,9 @@ plein ont tous les deux été essayés et jugés trop nets avant ça.
Les PDF portent des métadonnées (titre, auteur, langue) posées par
`scripts/generate-pdf.js` via `pdf-lib`. Titres ≤ 60 caractères,
descriptions ≤ 160 (Google coupe au-delà ; textes de la mission SEO du
- 24/09/2026 dans `PROFILE.seo` et `results.metaDescription`) ; `favicon.ico`
+ 24/09/2026 dans `PROFILE.seo` et `results.metaDescription`, suffixe des
+ pages projet et description FR de l'accueil raccourcis le 25/09 avec
+ l'accord d'Antoine), vérifiés sans exception par `check-seo.mjs` ; `favicon.ico`
multi-tailles à la racine, rendu depuis `assets/favicon.svg`.
- **Site considéré fonctionnellement complet** (sept. 2026) : bilingue,
PDF, Fit-Checker IA, hero cliquable + études de cas STAR, side project
diff --git a/README.md b/README.md
index 38fd0cf..93ce766 100644
--- a/README.md
+++ b/README.md
@@ -361,7 +361,9 @@ détail ne demande de toucher qu'à `data.js`, jamais à
le projet en ligne) comme d'habitude.
2. Ajoute une clé correspondante dans `PROJECT_DETAILS` (juste après
`SIDE_PROJECTS` dans `data.js`) : le plus simple est de **copier l'entrée
- `tour-de-growth` et de remplacer les textes**. Champs : `title`,
+ `tour-de-growth` et de remplacer les textes**. Champs : `title` (le titre
+ de l'onglet devient «
— étude de cas · Antoine Berthaud », 60
+ caractères au plus : un nom de projet de plus de 26 caractères dépasse),
`tagline`, `metaDescription` (`{fr, en}`, 160 caractères au plus : ce
que Google affiche), `liveUrl`, `problem`, `whatItIs` (+ `whatItIsPoints` et
`whatItIsClosing` optionnels), `teachingMoment` (optionnel, `{title,
diff --git a/en/projects/tour-de-growth.html b/en/projects/tour-de-growth.html
index bbc96c1..f98b947 100644
--- a/en/projects/tour-de-growth.html
+++ b/en/projects/tour-de-growth.html
@@ -9,7 +9,7 @@
entièrement générées : on ne modifie que ce gabarit (structure) et
data.js / i18n.js (textes). Titre, description et og:/twitter: sont posés
par le générateur dans la langue de la page. -->
-Tour de Growth — case study · Antoine Berthaud, Product Manager
+Tour de Growth — case study · Antoine Berthaud
@@ -24,7 +24,7 @@
-
+
@@ -32,7 +32,7 @@
-
+
@@ -48,7 +48,7 @@
"@type": "WebPage",
"@id": "https://cv.antoine.berthaud.me/en/projects/tour-de-growth.html#page",
"url": "https://cv.antoine.berthaud.me/en/projects/tour-de-growth.html",
- "name": "Tour de Growth — case study · Antoine Berthaud, Product Manager",
+ "name": "Tour de Growth — case study · Antoine Berthaud",
"description": "Tour de Growth, a side project by Antoine Berthaud: a check-up that maps your growth strategy onto the 5 AARRR pillars, no jargon. Product approach and stack.",
"inLanguage": "en",
"author": {
diff --git a/index.html b/index.html
index 3e8c736..55b1061 100644
--- a/index.html
+++ b/index.html
@@ -22,7 +22,7 @@
lisent les robots sans JavaScript ; app.js ne les touche plus que s'ils
diffèrent de data.js (page pas encore régénérée, signalée en console). -->
Antoine Berthaud · Senior Product Manager Growth à Nantes
-
+
-Tour de Growth — étude de cas · Antoine Berthaud, Product Manager
+Tour de Growth — étude de cas · Antoine Berthaud
@@ -24,7 +24,7 @@
-
+
@@ -32,7 +32,7 @@
-
+
@@ -48,7 +48,7 @@
"@type": "WebPage",
"@id": "https://cv.antoine.berthaud.me/projets/tour-de-growth.html#page",
"url": "https://cv.antoine.berthaud.me/projets/tour-de-growth.html",
- "name": "Tour de Growth — étude de cas · Antoine Berthaud, Product Manager",
+ "name": "Tour de Growth — étude de cas · Antoine Berthaud",
"description": "Tour de Growth, side project d'Antoine Berthaud : un check-up qui situe sa stratégie growth sur les 5 piliers AARRR, sans jargon. Démarche produit et stack.",
"inLanguage": "fr",
"author": {
diff --git a/scripts/check-seo.mjs b/scripts/check-seo.mjs
index 478aec8..0a5a25e 100644
--- a/scripts/check-seo.mjs
+++ b/scripts/check-seo.mjs
@@ -849,17 +849,11 @@ async function lot4(browser) {
const cp = ld && ld["@graph"].find((n) => n["@type"] === "CollectionPage");
check(4, "4.1-description", `${pg.path} : description de la mission dans la meta, og:, twitter: et le JSON-LD`, info.description === d && sameDesc(d) && cp && cp.description === d && cp.name === info.title, `${(info.description || "").length} car.`);
}
- // Longueurs. Les textes que la mission a fixés doivent tenir ; ceux
- // qu'elle ne fournit pas (titre des pages projet, description de
- // l'accueil) sont signalés sans faire échouer, en attendant une décision.
- const fixedTitle = pg.kind === "home" || pg.kind === "results";
- const fixedDesc = pg.kind === "results" || pg.kind === "project";
+ // Longueurs : tous les titres et descriptions doivent tenir.
const tl = info.title.length,
dl = (info.description || "").length;
- if (tl <= MAX_TITLE || fixedTitle) check(4, "4.1-len-title", `${pg.path} : titre ≤ ${MAX_TITLE} caractères`, tl <= MAX_TITLE, `${tl} car.`);
- else skip(4, "4.1-len-title", `${pg.path} : titre ≤ ${MAX_TITLE} caractères`, `⚠ ${tl} car. — texte hors mission, à décider (voir le rapport)`);
- if (dl <= MAX_DESCRIPTION || fixedDesc) check(4, "4.1-len-desc", `${pg.path} : description ≤ ${MAX_DESCRIPTION} caractères`, dl <= MAX_DESCRIPTION, `${dl} car.`);
- else skip(4, "4.1-len-desc", `${pg.path} : description ≤ ${MAX_DESCRIPTION} caractères`, `⚠ ${dl} car. — texte hors mission, à décider (voir le rapport)`);
+ check(4, "4.1-len-title", `${pg.path} : titre ≤ ${MAX_TITLE} caractères`, tl <= MAX_TITLE, `${tl} car.`);
+ check(4, "4.1-len-desc", `${pg.path} : description ≤ ${MAX_DESCRIPTION} caractères`, dl <= MAX_DESCRIPTION, `${dl} car.`);
}
await rawCtx.close();
diff --git a/sitemap.xml b/sitemap.xml
index bd9b3d1..a49d419 100644
--- a/sitemap.xml
+++ b/sitemap.xml
@@ -13,7 +13,7 @@
https://cv.antoine.berthaud.me/
- 2026-09-24
+ 2026-09-25
@@ -41,14 +41,14 @@
https://cv.antoine.berthaud.me/projets/tour-de-growth.html
- 2026-09-24
+ 2026-09-25
https://cv.antoine.berthaud.me/en/projects/tour-de-growth.html
- 2026-09-24
+ 2026-09-25