A static metadata export on a dynamic route ([slug], [id], [username]) applies identical OG tags to every instance of that route. Every blog post shares the same title, every product page shows the same description, and every user profile presents the same image in social previews. Per ogp.me, og tags are the mechanism social platforms use to generate link preview cards; when all instances of a dynamic route return the same tags, the platform cannot differentiate between content pieces. This is the most common and highest-impact social sharing gap in AI-built projects: content that was individually created gets collectively presented as one undifferentiated link, eliminating per-content shareability entirely.
Critical because static metadata on dynamic routes makes every instance of that route present identically in social feeds, eliminating the individual shareability of each piece of content.
Replace static metadata exports on dynamic routes with generateMetadata functions that fetch the specific item and build OG tags from its data:
// app/blog/[slug]/page.tsx
// WRONG:
export const metadata: Metadata = { openGraph: { title: 'My Blog' } }
// RIGHT:
export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> {
const post = await getPostBySlug(params.slug)
if (!post) return { title: 'Not Found' }
return {
openGraph: {
title: post.title,
description: post.excerpt,
images: [{ url: post.ogImageUrl ?? '/og-default.png', width: 1200, height: 630 }],
url: `https://yoursite.com/blog/${params.slug}`,
},
}
}
Apply this pattern to every [param] route directory in app/ that renders public-facing content.
ID: marketing-social-sharing.share-infrastructure.dynamic-og-for-dynamic-content
Severity: critical
What to look for: Identify all dynamic routes in the project — pages with parameterized paths like [slug], [id], [username]. For each dynamic route, check whether OG metadata is generated dynamically via generateMetadata (Next.js App Router), getHead (Nuxt), or equivalent framework mechanism. Static metadata exports on dynamic route pages are a failure pattern: they apply the same metadata to every instance of that route regardless of the actual content. Count all instances found and enumerate each.
Pass criteria: Every dynamic route that renders public-facing content uses generateMetadata (or framework equivalent) to construct OG tags from the route's data. The function fetches or derives the title, description, and image from the specific item being rendered. At least 1 implementation must be confirmed.
Fail criteria: Any dynamic route uses a static metadata export (not generateMetadata) for its OG tags, OR any dynamic route has no OG metadata at all. Do NOT pass if all dynamic routes share the same static og:title and og:description — each piece of content needs unique social previews.
Skip (N/A) when: The project has no dynamic routes — all routes are static paths. Signal: no [param] folders in app/ or pages/, no dynamic route patterns.
Cross-reference: The social-meta-per-content-type check verifies that different content types generate distinct social meta, complementing this dynamic OG check.
Detail on fail: "app/blog/[slug]/page.tsx uses static metadata export — all blog posts will show the same OG title and description regardless of content" or "app/products/[id]/page.tsx has no OG metadata — each product page shows no social preview"
Remediation: Dynamic routes need dynamic metadata. Replace static metadata exports with generateMetadata functions that fetch the specific item's data:
// app/blog/[slug]/page.tsx
// WRONG:
export const metadata: Metadata = { openGraph: { title: 'My Blog' } }
// RIGHT:
export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> {
const post = await getPostBySlug(params.slug)
if (!post) return { title: 'Not Found' }
return {
openGraph: {
title: post.title,
description: post.excerpt,
images: [{ url: post.ogImageUrl ?? '/og-default.png', width: 1200, height: 630 }],
url: `https://yoursite.com/blog/${params.slug}`,
},
}
}
This is the most common and highest-impact social sharing gap in AI-built projects.