From 5899a29974395691f5e1eae83c712a9bc6691974 Mon Sep 17 00:00:00 2001 From: Adam Shatzkamer Date: Fri, 9 Oct 2026 21:01:54 +0000 Subject: [PATCH] fix(docs): attach default og:image to Markdoc metadata so docs pages show preview cards Docs pages that define nextjs.metadata title/description emit their own openGraph/twitter object; Next's metadata merge replaces the parent layout's images, so shared docs links lost the social preview card entirely (only twitter:card was emitted, no og:image). Attach the site default og:image/twitter:image (with width, height and alt) whenever a page emits per-page openGraph/twitter values but does not explicitly set images. Pages without frontmatter still inherit the root layout unchanged. Verified with a next build: /docs/ now emits og:image 1200x630 + alt + twitter:image; /docs/plain (no frontmatter) still inherits the layout image. --- next.config.mjs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/next.config.mjs b/next.config.mjs index 6ff04dc..08c1787 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -52,6 +52,26 @@ const nextConfig = { return ( source + ` +// Site-wide default social card. Docs pages carry title/description +// frontmatter, and Next's metadata merge REPLACES the parent layout's +// openGraph/twitter object instead of merging images into it — so a +// docs page that emits its own openGraph would otherwise lose the +// og:image/twitter:image entirely and shared links would render as a +// plain text card. Attach the site default card (unless the page +// author explicitly sets images) so every docs page previews properly +// on LinkedIn, X, and Slack. +const __defaultOgImage = { + url: '/opengraph-image.png', + width: 1200, + height: 630, + alt: 'GoFr — An Opinionated Go Framework', +}; +const __defaultTwitterImage = { + url: '/twitter-image.png', + width: 1200, + height: 630, + alt: 'GoFr — An Opinionated Go Framework', +}; const __pageMeta = frontmatter.nextjs?.metadata || {}; const __pageTitle = typeof __pageMeta.title === 'string' ? __pageMeta.title : undefined; const __pageDesc = typeof __pageMeta.description === 'string' ? __pageMeta.description : undefined; @@ -65,6 +85,16 @@ const __tw = { ...(__pageDesc ? { description: __pageDesc } : {}), ...(__pageMeta.twitter || {}), }; +// Default card image unless the author explicitly provided their own. +// Only attach when the page actually carries per-page values — pages +// without frontmatter must stay empty so the parent layout's openGraph +// (with its own title/description/images) is preserved. +if (Object.keys(__og).length && !__og.images) { + __og.images = [__defaultOgImage]; +} +if (Object.keys(__tw).length && !__tw.images) { + __tw.images = [__defaultTwitterImage]; +} const __derivedCanonical = ${JSON.stringify(__canonical)}; const __alternates = { canonical: __derivedCanonical,