Next.js Metadata API: Titles, Canonicals & Open Graph Done Right

Next.js App Router replaced scattered Head tags with a first-class Metadata API — but titles, canonicals, and Open Graph still break in production when metadataBase is missing or generateMetadata returns relative URLs. This guide walks through patterns that keep search and social previews correct, and pairs them with ToolMars utilities for slug, snippet, crawl, and schema checks.
Whether you ship a marketing site or a docs product, consistent metadata is the cheapest SEO win: one source of truth for title templates, absolute canonicals, and OG images that actually resolve.
Preview titles and metas before you ship
Free SERP preview — pixel-width checks for desktop and mobile snippets.
Static metadata vs generateMetadata
Fixed routes (pricing, about, tool landing pages) should export a metadata object. Dynamic routes — blog posts, product pages, localized URLs — need generateMetadata so titles and canonicals reflect the actual resource. Mixing them incorrectly is a common source of duplicate titles and self-referencing wrong URLs.
- Static export — fast, cacheable, ideal for marketing pages.
- generateMetadata — await CMS/data; return per-slug SEO fields.
- Root layout templates — use
title.templatefor brand suffixes without repeating them on every page.
Canonicals and generateMetadata example
Set metadataBase in the root layout, then use alternates.canonical on each page. Build clean paths with a slug generator when content editors invent titles — hyphens, lowercase, no stop-word spam.
// app/layout.tsx
export const metadata = {
metadataBase: new URL("https://www.toolmars.com"),
title: { default: "ToolMars", template: "%s | ToolMars" },
};
// app/blogs/[slug]/page.tsx
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}): Promise<Metadata> {
const { slug } = await params;
const post = await getPost(slug);
return {
title: post.title,
description: post.excerpt,
alternates: {
canonical: `https://www.toolmars.com/blogs/${slug}/`,
},
openGraph: {
title: post.title,
description: post.excerpt,
url: `https://www.toolmars.com/blogs/${slug}/`,
type: "article",
images: [{ url: post.image, width: 1200, height: 630 }],
},
twitter: {
card: "summary_large_image",
title: post.title,
description: post.excerpt,
images: [post.image],
},
};
}Open Graph and social cards
Social platforms need absolute image URLs (typically 1200×630). Relative paths silently fail when metadataBase is unset. Keep openGraph.url aligned with the canonical. After drafting copy, check truncation in the SERP preview tool — Google and social cards both punish runaway lengths.
Metadata checklist
- Define metadataBase once in the root layout.
- Use title templates for brand consistency.
- Return alternates.canonical for every indexable page.
- Provide OG/Twitter images as absolute URLs.
- Preview snippet length with the meta generator.
- Add JSON-LD via the schema generator for Article or FAQ pages.
- Align crawl policy with a robots.txt that allows indexable routes.
Add structured data next to metadata
Generate Article, FAQ, and SoftwareApplication JSON-LD in the browser.
Robots, noindex, and crawl hygiene
Use metadata.robots for page-level noindex (thank-you pages, internal search). Keep site-wide Disallow rules in robots.txt — conflicting signals confuse crawlers. When you retire URLs, pair Metadata changes with redirects and a clean crawl map.
Related Tools on ToolMars
- Meta Generator — SERP preview and pixel-width warnings
- Slug Generator — clean URL paths for App Router segments
- Robots Generator — allow/disallow rules and sitemap lines
- Schema Generator — JSON-LD to complement Metadata API tags
Conclusion
The Metadata API is powerful when you treat it as a contract: absolute URLs, explicit canonicals, and previews before merge. Wire generateMetadata to real content, validate snippets and schema with ToolMars, and your Next.js pages will speak clearly to both Google and social platforms.
Preview titles and metas before you ship
Free SERP preview — pixel-width checks for desktop and mobile snippets.
Frequently Asked Questions
Should I use metadata export or generateMetadata?
Use a static metadata export for fixed pages. Use async generateMetadata when title, description, or canonical depend on params, searchParams, or fetched CMS data.
How do I set a canonical URL in the Next.js Metadata API?
Set alternates.canonical to the absolute preferred URL (or a path Next.js can resolve against metadataBase). Avoid pointing canonicals at query-string variants you do not want indexed.
What is metadataBase and why does it matter?
metadataBase is the origin Next.js uses to resolve relative Open Graph images, canonicals, and other URLs into absolute https links required by crawlers and social platforms.
Do Open Graph tags replace title and meta description?
No. og:title and og:description power social cards; title and description still matter for search snippets. Keep them consistent unless you intentionally customize social copy.
Can Next.js Metadata API emit JSON-LD?
Structured data is usually injected via a script tag in the page (dangerouslySetInnerHTML) or a dedicated component — not through the metadata title/description fields alone.
How long should Next.js page titles be?
Aim for roughly 50–60 characters so Google does not truncate. Preview pixel width with a SERP tool before merging — wide characters consume space faster.
Where should robots rules live relative to Metadata API?
Page-level robots (index/noindex) can go in metadata.robots. Site-wide crawl rules belong in robots.txt — generate both and keep them consistent.