--- title: "Next.js SEO: Metadata, Open Graph, and Sitemap Best Practices" description: "How to implement comprehensive SEO metadata in Next.js App Router. Dynamic metadata, Open Graph images, sitemaps, and robots.txt done right." --- Next.js App Router provides a powerful metadata API that makes comprehensive SEO implementation clean and type-safe. When implemented correctly, you get proper title tags, meta descriptions, Open Graph previews, Twitter Cards, canonical URLs, and structured sitemaps from a centralized, maintainable configuration. This is the exact setup we use on every new project.
The Metadata API
The App Router exports a `metadata` object or a `generateMetadata` function from any `layout.tsx` or `page.tsx`. For static pages, export the object. For dynamic pages, use the async function.
Root Layout Defaults
Your root layout should define sensible defaults that child pages can override:
```tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
metadataBase: new URL('https://dreamtechdynamics.com'),
title: {
default: 'DreamTech Dynamics — Software Development Agency',
template: '%s | DreamTech Dynamics',
},
description: 'We build fast, scalable web and mobile applications for startups and enterprises.',
openGraph: {
type: 'website',
locale: 'en_US',
siteName: 'DreamTech Dynamics',
},
twitter: {
card: 'summary_large_image',
site: '@dreamtechdyn',
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
'max-image-preview': 'large',
},
},
};
```
Setting `metadataBase` is essential. Without it, relative URLs in Open Graph image fields will not resolve correctly and social previews will break.
Dynamic Metadata for Blog Posts
For dynamic routes like blog posts, use `generateMetadata` to pull data and return metadata based on the specific content:
```tsx
export async function generateMetadata({ params }): Promise<Metadata> {
const post = await getPost(params.slug);
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
type: 'article',
publishedTime: post.publishedAt,
authors: [post.author.name],
images: [{ url: post.featuredImage, width: 1200, height: 630 }],
},
alternates: {
canonical: `/blog/${params.slug}`,
},
};
}
```
Always set the canonical URL. Next.js does not automatically generate canonical tags, and without them, URL variations accumulate duplicate content signals.
Open Graph Images
Social sharing previews are a significant source of click-through rates from social media, messaging apps, and link previews. A compelling OG image dramatically increases engagement.
Next.js supports automatic OG image generation via the `ImageResponse` API. Create an `opengraph-image.tsx` file in a route segment and it renders dynamically for each page.
For high-traffic pages, statically generate OG images at build time. For dynamic content, use edge-rendered image generation to keep response times fast.
XML Sitemaps
Create your sitemap using Next.js's built-in sitemap support. Add a `sitemap.ts` file to your app directory:
```tsx
import { MetadataRoute } from 'next';
import { blogPosts } from '@/lib/data/blog';
export default function sitemap(): MetadataRoute.Sitemap {
const blogUrls = blogPosts.map((post) => ({
url: `https://dreamtechdynamics.com/blog/${post.slug}`,
lastModified: new Date(post.publishedAt),
changeFrequency: 'monthly' as const,
priority: 0.7,
}));
return [
{ url: 'https://dreamtechdynamics.com', lastModified: new Date(), priority: 1.0 },
{ url: 'https://dreamtechdynamics.com/services', lastModified: new Date(), priority: 0.9 },
{ url: 'https://dreamtechdynamics.com/blog', lastModified: new Date(), priority: 0.8 },
...blogUrls,
];
}
```
Only include canonical, indexable URLs. Do not include paginated pages, filter variations, or search result pages.
robots.txt
Next.js generates robots.txt from a `robots.ts` file:
```tsx
import { MetadataRoute } from 'next';
export default function robots(): MetadataRoute.Robots {
return {
rules: [
{ userAgent: '*', allow: '/', disallow: ['/admin/', '/api/'] },
{ userAgent: 'GPTBot', disallow: '/' },
],
sitemap: 'https://dreamtechdynamics.com/sitemap.xml',
};
}
```
This approach keeps your robots.txt colocated with your application code and type-checked, which prevents common formatting errors that break crawlers.
Verifying Implementation
After deployment, verify your implementation using Google Search Console's URL Inspection tool, which shows exactly what Google sees. Use the Rich Results Test for structured data. Check social sharing previews using LinkedIn's Post Inspector and Twitter's Card Validator.
Add SEO metadata tests to your CI pipeline. Missing titles, broken canonical URLs, and malformed OG tags are regressions that should never reach production.






