---
name: nextjs-seo
description: Next.js SEO optimization guide. Use when building Next.js apps, optimizing for search engines, fixing Google indexing issues, implementing metadata, sitemaps, robots.txt, JSON-LD, or auditing SEO.
---
# Next.js SEO Optimization
Comprehensive SEO guide for Next.js 16+ applications using App Router.
> **Version:** Updated for Next.js 16.1.3 (January 2026)
## Quick SEO Audit
Run this checklist for any Next.js project:
1. **Check robots.txt**: `curl https://your-site.com/robots.txt`
2. **Check sitemap**: `curl https://your-site.com/sitemap.xml`
3. **Check metadata**: View page source, search for `
` and ``
4. **Check JSON-LD**: View page source, search for `application/ld+json`
5. **Check Core Web Vitals**: Run Lighthouse in Chrome DevTools
## Essential Files
### app/layout.tsx - Root Metadata
```typescript
import type { Metadata, Viewport } from 'next';
// Viewport (separate export required in Next.js 14+)
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
maximumScale: 5,
userScalable: true,
themeColor: [
{ media: '(prefers-color-scheme: light)', color: '#ffffff' },
{ media: '(prefers-color-scheme: dark)', color: '#0a0a0a' },
],
};
export const metadata: Metadata = {
metadataBase: new URL('https://your-site.com'),
title: {
default: 'Site Title - Main Keyword',
template: '%s | Site Name',
},
description: 'Compelling description with keywords (150-160 chars)',
keywords: ['keyword1', 'keyword2', 'keyword3'],
openGraph: {
type: 'website',
locale: 'en_US',
url: 'https://your-site.com',
siteName: 'Site Name',
title: 'Site Title',
description: 'Description for social sharing',
images: [{ url: '/og-image.png', width: 1200, height: 630, alt: 'Site preview' }],
},
twitter: {
card: 'summary_large_image',
title: 'Site Title',
description: 'Description for Twitter',
images: ['/og-image.png'],
},
alternates: {
canonical: '/',
},
robots: {
index: true,
follow: true,
},
};
```
### app/sitemap.ts - Dynamic Sitemap
```typescript
import type { MetadataRoute } from 'next';
export default function sitemap(): MetadataRoute.Sitemap {
const baseUrl = 'https://your-site.com';
return [
{
url: baseUrl,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 1,
images: [`${baseUrl}/og-image.png`], // Next.js 16 Image Sitemap
},
{
url: `${baseUrl}/about`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8,
},
];
}
```
### app/robots.ts - Robots Configuration
```typescript
import type { MetadataRoute } from 'next';
export default function robots(): MetadataRoute.Robots {
const baseUrl = 'https://your-site.com';
return {
rules: [
{
userAgent: '*',
allow: '/',
disallow: ['/api/', '/_next/', '/admin/'],
},
],
sitemap: `${baseUrl}/sitemap.xml`,
host: baseUrl,
};
}
```
## Key Principles
### Rendering Strategy for SEO
| Strategy | Use When | SEO Impact |
|----------|----------|------------|
| SSG (Static) | Content rarely changes | Best - pre-rendered HTML |
| SSR | Dynamic content per request | Great - server-rendered |
| ISR | Large sites, periodic updates | Great - cached + fresh |
| CSR | Dashboards, authenticated areas | Poor - avoid for SEO pages |
### Core Web Vitals Targets
| Metric | Target | Impact |
|--------|--------|--------|
| LCP (Largest Contentful Paint) | < 2.5s | Loading speed |
| INP (Interaction to Next Paint) | < 200ms | Interactivity |
| CLS (Cumulative Layout Shift) | < 0.1 | Visual stability |
## References
- **Metadata API**: See [references/metadata-api.md](references/metadata-api.md)
- **Sitemap & Robots**: See [references/sitemap-robots.md](references/sitemap-robots.md)
- **JSON-LD Structured Data**: See [references/json-ld.md](references/json-ld.md)
- **SEO Audit Checklist**: See [references/checklist.md](references/checklist.md)
- **Troubleshooting**: See [references/troubleshooting.md](references/troubleshooting.md)
## Common Mistakes to Avoid
1. **Mixing next-seo with Metadata API** - Use only Metadata API in App Router
2. **Missing canonical URLs** - Always set `alternates.canonical`
3. **Using CSR for SEO pages** - Use SSG/SSR for indexable content
4. **Blocking assets in robots.txt** - Don't block CSS/JS needed for rendering
5. **Missing metadataBase** - Required for relative URLs in metadata
6. **Viewport in metadata** - Must be separate export in Next.js 14+
7. **Mixing metadata object and generateMetadata** - Use one or the other, not both
## Quick Fixes
### Add noindex to a page
```typescript
export const metadata: Metadata = {
robots: {
index: false,
follow: false,
},
};
```
### Dynamic metadata per page
```typescript
export async function generateMetadata({ params }): Promise {
const product = await getProduct(params.id);
return {
title: product.name,
description: product.description,
};
}
```
### Canonical for dynamic routes
```typescript
export async function generateMetadata({ params }): Promise {
return {
alternates: {
canonical: `/products/${params.slug}`,
},
};
}
```