Next.js SEO starts with one choice: how each page renders. Crawlers read server-rendered HTML fast and reliably, while client-only pages force bots to run JavaScript before they see any text. This guide shows which rendering mode fits which page, and how to set metadata, sitemaps and structured data in the App Router.
Every example works with current Next.js versions and needs no extra plugin.
Pick the right rendering mode for each page
Next.js gives you four options. Choose per route, not per site.
- Static generation (SSG): builds the page once at deploy time. Best for blogs, docs and landing pages.
- Incremental static regeneration (ISR): rebuilds static pages on a timer or on demand. Best for catalogs and news.
- Server-side rendering (SSR): builds the page on each request. Best for personalized or fast-changing pages.
- Client-side rendering (CSR): builds the page in the browser. Use it only for private dashboards and widgets.
Any text you want ranked or cited should arrive in the first HTML response. Test it with curl, as shown in our answer engine optimization checklist.
Set unique metadata with generateMetadata
Each page needs its own title, description and canonical URL. The Metadata API handles all three on the server:
// app/blog/[slug]/page.tsx import type { Metadata } from 'next'; 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.summary, alternates: { canonical: `https://example.com/blog/${slug}` }, openGraph: { title: post.title, description: post.summary, type: 'article', }, }; } Keep titles under about 60 characters and descriptions under about 160. Never reuse one description across many pages.
Generate a sitemap and robots file
Next.js builds both files from code, so they stay current as your content grows.
// app/sitemap.ts import type { MetadataRoute } from 'next'; export default async function sitemap(): Promise<MetadataRoute.Sitemap> { const posts = await getAllPosts(); return posts.map((p) => ({ url: `https://example.com/blog/${p.slug}`, lastModified: p.updatedAt, })); } // app/robots.ts import type { MetadataRoute } from 'next'; export default function robots(): MetadataRoute.Robots { return { rules: { userAgent: '*', allow: '/' }, sitemap: 'https://example.com/sitemap.xml', }; } Add structured data on the server
Render JSON-LD inside a server component, so crawlers see it without running scripts:
export default async function Page({ params }) { const { slug } = await params; const post = await getPost(slug); const jsonLd = { '@context': 'https://schema.org', '@type': 'Article', headline: post.title, datePublished: post.publishedAt, }; return ( <article> <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} /> <h1>{post.title}</h1> </article> ); } To see how answer engines use this data, read AEO vs SEO: How Answer Engines Change Your Content Strategy.
Handle images and headings
Use the next/image component with real width and height values, and add the priority prop to your hero image. That prevents layout shifts and speeds up the largest paint.
Keep one h1 per page and a clear heading order below it. Headings give crawlers and AI tools a map of your content.
Next.js SEO FAQs
Is Next.js good for SEO?
Yes. Next.js renders pages on the server or at build time, so crawlers receive full HTML. Its Metadata API also makes titles, descriptions and canonical tags easy to manage.
Is SSR or SSG better for SEO?
Both work well, because both send complete HTML. SSG gives faster load times for content that rarely changes, while SSR suits pages that change on every request.
Does Google crawl JavaScript?
Googlebot can render JavaScript, but it queues that work and many other crawlers skip it. Server-rendered content avoids both risks.
How do I add meta tags in Next.js?
Export a metadata object or a generateMetadata function from your page or layout file in the App Router.
How do I add a sitemap in Next.js?
Create an app/sitemap.ts file that returns your URLs. Next.js serves it at /sitemap.xml automatically.
Planning a web app that ranks?
Rendering choices shape rankings long before launch. If you want a team to plan them with you, explore DigiStreet Media's web application development services. Which rendering mode do you use most? Tell me in the comments.
Disclosure: I publish this account for DigiStreet Media, a digital marketing agency in Noida, India.
