From e45f1c04d0ba86bde71b098b6a0deec2ea9276a9 Mon Sep 17 00:00:00 2001 From: Luiz Gustavo Date: Mon, 25 May 2026 04:09:15 -0300 Subject: [PATCH] fix(seo): use body H1 as case-file and OG title MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit generateMetadata still derived the page <title>/OG title from the generic auto frontmatter topic ("Dow Uap D44 …"). Search engines, link cards, and AI crawlers show that string, so it must be the human magazine headline the narrator wrote as the body H1. Mirror the page component's H1 extraction. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --- web/app/c/[slug]/page.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/web/app/c/[slug]/page.tsx b/web/app/c/[slug]/page.tsx index c39ba57..f2edbe6 100644 --- a/web/app/c/[slug]/page.tsx +++ b/web/app/c/[slug]/page.tsx @@ -81,7 +81,14 @@ export async function generateMetadata( const c = await loadCase(slug); if (!c) return { title: "Case file not found" }; - const title = locale === "pt-br" ? (c.fm.topic_pt_br ?? c.fm.topic ?? slug) : (c.fm.topic ?? slug); + // Prefer the narrator's body H1 (the magazine headline) over the generic + // auto-derived frontmatter topic ("Dow Uap D44 …"). This is what search + // engines and link cards show, so it must be the human title. Two H1s when + // present: EN then PT-BR; fall back across them, then to frontmatter. + const h1s = [...c.body.matchAll(/^#\s+(.+)$/gm)].map((m) => m[1].trim()); + const title = locale === "pt-br" + ? (h1s[1] ?? h1s[0] ?? c.fm.topic_pt_br ?? c.fm.topic ?? slug) + : (h1s[0] ?? c.fm.topic ?? slug); const desc = pickLead(c.body, locale).slice(0, 200); const canonical = `${SITE_URL}/c/${slug}`; // OG image — use the case's editorial illustration when present. WhatsApp,