How to Fix Meta Tags in Next.js (Metadata API)
Next.js App Router introduces the Metadata API: declarative export from page.tsx or layout.tsx that generates
tags. Cleaner than Pages Router patterns but has gotchas around dynamic data and inheritance. This guide covers Next.js meta tags. Pair with meta guide.Step-by-step: How to fix meta tags in Next.js
- Export static metadata. page.tsx: export const metadata: Metadata = { title: 'Page Title', description: '...' }. Next.js renders the appropriate <head> tags. Cleanest for static pages.
- Use generateMetadata for dynamic. Blog post or product page where metadata depends on data: export async function generateMetadata({ params }): Promise<Metadata> { const data = await fetch(...); return { title: data.title, description: data.description, openGraph: { ... } }; }
- Configure metadataBase. layout.tsx: export const metadata: Metadata = { metadataBase: new URL('https://example.com'), ... }. Required for relative URLs in OG/Twitter to resolve to absolute.
- Set OG, Twitter explicitly. openGraph: { title, description, url, type: 'article', images: [{url: ...}] }. twitter: { card: 'summary_large_image', title, description, images: [...] }. Don't rely on inheritance — set per page.
- Set canonical. alternates: { canonical: '/path' }. Always set; without canonical, duplicate-content risks. Self-referencing canonical is fine and recommended.
- Set robots. robots: { index: true, follow: true, googleBot: { index: true, follow: true, maxSnippet: -1, maxImagePreview: 'large' } }. Set in root layout for site-wide; override per page for noindex pages (legal, internal-search, thank-you).
- Validate. View source on representative pages. Use a meta tag analyser or our tool. Verify completeness, lengths (title ≤60, description ≤160), no duplicates.
Frequently Asked Questions
Pages Router vs App Router metadata?
Pages Router: <Head> component from next/head, imperative inside component. App Router: Metadata API, declarative export. App Router pattern is cleaner, type-safe, and recommended for new projects. Migration from Pages Router metadata to App Router metadata is mechanical but tedious.
How do I add metadata to dynamic Next.js pages?
Use generateMetadata async function that receives params (route params) and searchParams. Fetch data, return Metadata object. Same pattern works for blog post by slug, product by ID, anything URL-parameterised.
Why do my Next.js OG images not appear when sharing?
Check absolute URL (relative URLs don't work in OG without metadataBase). Verify dimensions (1200x630 ideal). Image accessible to social platforms (no auth required, no CORS issues). Run Facebook Sharing Debugger to see what Facebook sees. Run Twitter Card Validator to debug Twitter.
Can I override layout metadata in a child page?
Yes — child page metadata merges with parent layout metadata. Child can override or extend. For example, root layout sets default OG image; specific page sets custom OG image — page's wins. Inheritance is intuitive.
Best Next.js SEO library?
Built-in Metadata API is sufficient for most projects. next-seo library predates the Metadata API and remains popular for Pages Router. App Router projects: use built-in Metadata API for cleaner result. next-sitemap for sitemap generation (different concern).