There are five core steps to doing SEO with Next.js: render pages on the server (SSR/SSG), define a unique title and description per page with the Metadata API, generate a dynamic sitemap and robots.txt, add JSON-LD structured data, and optimize Core Web Vitals. Next.js ships built-in tools for every one of these steps, so you don’t need extra plugins or third-party SEO modules. That’s why Next.js is our first choice for SEO-critical corporate sites in our web development projects.
Why Is Next.js an SEO Advantage?
Classic React apps (SPAs) build their content in the browser, after JavaScript runs. Search engine bots don’t always execute JavaScript immediately; the render queue can take days. In Next.js, pages are produced as ready-made HTML on the server (SSR) or at build time (SSG) — when Googlebot opens the page, the title, content, and links are all in the first response. We compared Next.js and WordPress in detail in a separate post.
Pages that return ready HTML from the server get indexed far faster and more reliably than client-only rendered pages. The single most critical technical SEO decision is your rendering strategy — and Next.js gets it right by default.
Metadata API: Title, Description, and Open Graph
The App Router’s Metadata API lets you define a unique title, description, canonical, and Open Graph tags per page in a type-safe way. On dynamic pages (blog posts, product details), the `generateMetadata` function fetches the data and produces the metadata on the server:
// app/blog/[slug]/page.tsx
import type { Metadata } from 'next';
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const post = await getPost(params.slug);
return {
title: post.title, // merges with the layout template: "%s | Site Name"
description: post.excerpt,
alternates: { canonical: `/blog/${post.slug}` },
openGraph: {
title: post.title,
description: post.excerpt,
type: 'article',
images: [{ url: post.coverImage }],
},
};
}By defining `title.template` in the root layout, you get a consistent title pattern across all pages. Canonical URLs tell Google which address is the “primary” one when the same content is reachable from multiple URLs, preventing duplicate content issues.
Dynamic Sitemap and robots.txt
In Next.js, the `app/sitemap.ts` and `app/robots.ts` files automatically generate sitemap.xml and robots.txt at build or request time. When you add a new blog post, the sitemap updates itself — no manual XML editing:
// app/sitemap.ts
import type { MetadataRoute } from 'next';
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const posts = await getBlogPosts();
return [
{ url: 'https://yoursite.com', changeFrequency: 'daily', priority: 1 },
...posts.map((post) => ({
url: `https://yoursite.com/blog/${post.slug}`,
lastModified: post.updatedAt,
changeFrequency: 'weekly' as const,
priority: 0.6,
})),
];
}JSON-LD Structured Data
Structured data (Schema.org JSON-LD) tells search engines what a page is: an article, a service, a list of frequently asked questions? Organization, Article, Service, FAQPage, and BreadcrumbList are the most commonly used types. Correct structured data earns rich results (stars, FAQ accordions, breadcrumbs) and increases your chances of being cited by AI search engines like ChatGPT and Perplexity. In Next.js you solve this with a small `<script type="application/ld+json">` component embedded in the page; set it up once per page type and it runs automatically afterwards.
Performance: Core Web Vitals
Google uses page experience as a ranking signal. To score well on Core Web Vitals metrics (LCP, INP, CLS), use Next.js’s built-in optimizations:
- next/image: lowers LCP with automatic WebP/AVIF conversion, lazy loading, and sizing
- next/font: self-hosts fonts and prevents layout shift (CLS)
- Dynamic import: code-splits heavy components to shrink the initial load
- ISR (Incremental Static Regeneration): serves pages at static speed while refreshing content in the background
- Server Components: dramatically reduce the JavaScript shipped to the client
Common Next.js SEO Mistakes
- Making every page "use client" — throws away the server rendering advantage
- Defining metadata only in the root layout — every page competes with the same title/description
- Skipping canonicals — parameterized URLs get indexed as duplicate content
- Leaving the sitemap as a static file — new content reaches Google late
- Omitting hreflang tags on multilingual sites — the wrong language version ranks
Conclusion
Next.js carries everything SEO requires — server rendering, the Metadata API, automatic sitemaps, structured data support, and performance optimizations — in its core. What matters is setting these tools up completely and in the right order; we collected all the requirements of an SEO-friendly website in a separate post. For a fast, technically solid Next.js site that’s visible in search engines, get in touch with us or request a free quote.