OotyOoty
SEOComing soonSocialComing soonVideoComing soonAdsComing soonAnalyticsComing soonCommerceComing soonCRMComing soonCreatorsComing soon
Join the waitlist
FeaturesToolsPricingDocs

Products

SEOComing soonSocialComing soonVideoComing soonAdsComing soonAnalyticsComing soonCommerceComing soonCRMComing soonCreatorsComing soon
FeaturesToolsPricingDocs
Log in
Join the Waitlist

Launching soon

OotyOoty

AI native tools that replace expensive dashboards. SEO, Amazon, YouTube, and social analytics inside your AI assistant.

Product

  • Features
  • Pricing
  • Get started

Resources

  • Free Tools
  • Docs
  • About
  • Blog
  • Contact

Legal

  • Privacy
  • Terms
  • Refund Policy
  • Security
OotyOoty

AI native tools that replace expensive dashboards. SEO, Amazon, YouTube, and social analytics inside your AI assistant.

Product

  • Features
  • Pricing
  • Get started

Resources

  • Free Tools
  • Docs
  • About
  • Blog
  • Contact

Legal

  • Privacy
  • Terms
  • Refund Policy
  • Security

Stay in the loop

Get updates on new tools, integrations, and guides. No spam.

© 2026 Ooty. All rights reserved.

All systems operational
  1. Home
  2. /
  3. Blog
  4. /
  5. seo
  6. /
  7. Next.js SEO: The Technical Checklist for React Developers
5 March 2026·9 min read

Next.js SEO: The Technical Checklist for React Developers

A technical Next.js SEO checklist covering metadata API, sitemaps, structured data, rendering strategies, and common React SEO mistakes.

By Maya Torres

React applications have a reputation for being invisible to search engines. That reputation is outdated, but the underlying concern is valid: if your content is rendered entirely in the browser with JavaScript, Google has to execute that JavaScript to see it. That process is slower, less reliable, and lower priority than reading server-rendered HTML.

Next.js solves this. It supports server-side rendering (SSR), static site generation (SSG), and incremental static regeneration (ISR) out of the box. But having the right rendering strategy available does not mean developers use it correctly. Most Next.js SEO problems come from misconfiguration, not platform limitations.

Here is the technical checklist.

Metadata: the generateMetadata API

In the App Router, metadata is handled through the generateMetadata function or a static metadata export in your page or layout files. This replaces the old <Head> component from the Pages Router.

export async function generateMetadata({ params }) {
  const post = await getPost(params.slug)
  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      type: 'article',


Keyword data, site audits, and rankings from Google APIs inside your AI assistant.

Try Ooty SEOView pricing
Share
Maya Torres
Maya Torres

SEO Strategist at Ooty. Covers search strategy, GEO, and agentic SEO.

Continue reading

15 Apr 2026

ChatGPT SEO Audit: How to Audit Your Site with AI (Step by Step)

A ChatGPT SEO audit is a manual site review where you feed page data, crawl output, or Google Search Console exports into ChatGPT and use targeted prompts to identify technical issues, content gaps, and ranking opportunities. It works best for analysis and pri

18 Mar 2026

Duplicate Content in SEO: What Actually Causes Problems (And What Doesn't)

The "duplicate content penalty" is one of the most persistent myths in SEO. Site owners panic when they find identical text on two URLs, convinced that Google is about to punish their entire domain. That is not how it works. Google does not have a penalty for

22 Feb 2026

Image SEO: How to Get Traffic from Google Image Search

Google Images is one of the largest search engines in the world. For industries where visuals drive decisions, like e-commerce, travel, interior design, food, and fashion, image search represents a real traffic channel that most sites completely ignore. The ba

On this page

  • Metadata: the generateMetadata API
  • Sitemaps and robots.txt
    • sitemap.ts
    • robots.ts
  • Structured data (JSON-LD)
  • Image optimization with next/image
  • Canonical URLs
  • Trailing slashes
  • The rendering decision
    • Static Site Generation (SSG)
    • Server-Side Rendering (SSR)
    • Incremental Static Regeneration (ISR)
    • Client-side only rendering
  • Common mistakes
    • Not setting metadata on dynamic routes
    • Missing OG images
    • Using hash routing
    • Forgetting to handle www vs non-www
  • The checklist
},
}
}

Every page that should appear in search results needs a unique title and description. This seems obvious, but it is the most common gap on Next.js sites. Developers build layouts with a single metadata export that applies site-wide, then never override it on individual pages. The result: every page has the same title tag.

For static pages, use the metadata export directly. For dynamic pages (blog posts, product pages, profile pages), use generateMetadata to pull the data and construct unique metadata per page. Always include openGraph properties for social sharing.

Sitemaps and robots.txt

Next.js App Router supports both programmatically.

sitemap.ts

Create a sitemap.ts file in your app/ directory:

export default async function sitemap() {
  const posts = await getAllPosts()
  return [
    { url: 'https://example.com', lastModified: new Date() },
    { url: 'https://example.com/about', lastModified: new Date() },
    ...posts.map(post => ({
      url: `https://example.com/blog/${post.slug}`,
      lastModified: post.updatedAt,
    })),
  ]
}

For larger sites with thousands of URLs, use the generateSitemaps function to create multiple sitemap files with a sitemap index. Google recommends keeping individual sitemaps under 50,000 URLs.

The next-sitemap package is an alternative that generates sitemaps at build time and offers more configuration options (priority, changefreq, exclusion patterns). Either approach works. The built-in sitemap.ts is simpler. next-sitemap is more configurable. After deploying, validate your sitemap to catch formatting errors or missing URLs.

robots.ts

export default function robots() {
  return {
    rules: { userAgent: '*', allow: '/', disallow: '/api/' },
    sitemap: 'https://example.com/sitemap.xml',
  }
}

Block your API routes, admin pages, and any internal routes that should not be crawled. You can validate your robots.txt to confirm everything is configured correctly. Include the sitemap URL so crawlers can find it without relying on Search Console submission alone.

Structured data (JSON-LD)

Next.js does not have a built-in structured data solution. You add JSON-LD as a script tag in your page components. The standard approach is to create a component that renders a <script type="application/ld+json"> element with your serialized schema object. Since server components render this into the initial HTML, search engines see the structured data without executing JavaScript.

export default function ProductPage({ product }) {
  const jsonLd = {
    '@context': 'https://schema.org',
    '@type': 'Product',
    name: product.name,
    description: product.description,
    image: product.image,
    offers: {
      '@type': 'Offer',
      price: product.price,
      priceCurrency: 'USD',
      availability: 'https://schema.org/InStock',
    },
  }
 
  return (
    <>
      <script type="application/ld+json">
        {JSON.stringify(jsonLd)}
      </script>
      {/* page content */}
    </>
  )
}

Create reusable components for each schema type you need: Article for blog posts, Product for e-commerce, Organization for your company pages, BreadcrumbList for navigation, FAQPage for FAQ sections.

You can validate your structured data implementation with the Ooty Schema Validator to catch errors before they reach production.

Image optimization with next/image

The next/image component handles responsive images, lazy loading, format conversion (WebP/AVIF), and sizing automatically. Use it for every content image on your site.

import Image from 'next/image'
 
<Image
  src="/hero.jpg"
  alt="Product dashboard showing analytics overview"
  width={1200}
  height={630}
  priority
/>

Two SEO-specific details matter here:

Always include descriptive alt text. The alt attribute is how search engines understand what an image shows. It is also essential for accessibility. Describe the image content. Do not stuff keywords.

Use the priority prop for above-the-fold images. By default, next/image lazy loads all images. For your LCP element (usually the hero image or main content image), add priority to tell the browser to load it immediately. This directly affects your Largest Contentful Paint score.

Canonical URLs

Set canonical URLs explicitly. If your site is accessible at both www and non-www, or if pages can be reached through multiple URL patterns, duplicate content issues will follow.

export const metadata = {
  alternates: {
    canonical: 'https://example.com/page',
  },
}

For dynamic pages, construct the canonical URL in generateMetadata. Use your production domain, not localhost or a preview deployment URL. A surprising number of Next.js sites have canonical tags pointing to Vercel preview URLs because the developer used process.env.VERCEL_URL instead of a hardcoded production domain.

Trailing slashes

Decide whether your URLs end with a trailing slash or not, then enforce it consistently. Next.js defaults to no trailing slash. If you want trailing slashes, set trailingSlash: true in next.config.js.

Inconsistency (some pages with, some without) creates duplicate content. Google treats /about and /about/ as different URLs unless you set canonical tags. Pick one format and stick with it across your entire site.

The rendering decision

This is where most Next.js SEO mistakes happen. Not in metadata or sitemaps, but in choosing the wrong rendering strategy for a given page.

Static Site Generation (SSG)

Best for: blog posts, documentation, marketing pages, landing pages. Any content that changes infrequently.

Pages are rendered at build time and served as static HTML from a CDN. Fastest possible load times. Search engines receive fully rendered HTML immediately. No server processing per request.

Use generateStaticParams to pre-render dynamic routes:

export async function generateStaticParams() {
  const posts = await getAllPosts()
  return posts.map(post => ({ slug: post.slug }))
}

Server-Side Rendering (SSR)

Best for: pages with user-specific content, search results, dashboards, pages where the content changes on every request.

Pages are rendered on the server for each request. Slower than SSG (the server has to do work per request), but the HTML is always current. Search engines still receive fully rendered HTML.

In the App Router, server components are SSR by default. To make a page dynamic (no caching), use export const dynamic = 'force-dynamic' or fetch data with { cache: 'no-store' }.

Incremental Static Regeneration (ISR)

Best for: product pages, frequently updated content, any page where you want SSG performance with regular content updates.

Pages are statically generated but regenerated in the background after a configurable time interval:

export const revalidate = 3600 // regenerate every hour

ISR gives you the CDN performance of SSG with near-real-time content freshness. For e-commerce sites with thousands of products, this is typically the right choice.

Client-side only rendering

Best for: nothing that needs to rank in search. Authenticated dashboards, internal tools, app features behind login.

This is the default behavior of plain React (Create React App). Content is rendered in the browser after JavaScript executes. Google can crawl JavaScript-rendered content, but it is deferred to a second wave of crawling, which may take days or weeks. For SEO content, never rely on client-side only rendering.

For a deeper explanation of how search engines process JavaScript, see our guide on JavaScript SEO.

Common mistakes

Not setting metadata on dynamic routes

Developers build a beautiful blog or product page, implement generateStaticParams, but forget generateMetadata. Every dynamic page gets the root layout's default metadata. Check your dynamic routes. Each one should have its own metadata function.

Missing OG images

Open Graph images affect click-through rates from social media and some search features. Next.js makes this easy with the opengraph-image.tsx convention (App Router) or the @vercel/og package for dynamic image generation.

At minimum, set a default OG image in your root layout. For content pages, generate images dynamically with the post title and your brand. The ImageResponse API lets you build OG images with JSX in a dedicated opengraph-image.tsx file alongside your page, and Next.js serves them automatically at the right URL.

Using hash routing

Hash-based routing (/#/about, /#/products) is invisible to search engines. The fragment identifier (everything after #) is never sent to the server and is not included in crawl requests. Next.js does not use hash routing by default, but developers sometimes introduce it through third-party routing libraries or custom navigation logic. If any of your SEO-relevant pages use hash routes, they will not be indexed.

Forgetting to handle www vs non-www

Configure your hosting to redirect one to the other. In Vercel, add both domains and set the canonical one as primary. The other will 308 redirect automatically. Without this, you might build backlinks to both versions, splitting your link equity between two duplicate versions of your entire site. After deploying, verify your redirects are returning the expected status codes.

The checklist

  1. Every page has unique title and description via metadata or generateMetadata
  2. Open Graph metadata set on all public pages
  3. sitemap.ts (or next-sitemap) generating a complete sitemap
  4. robots.ts blocking /api/ and internal routes
  5. JSON-LD structured data on relevant page types
  6. next/image with alt text on all images, priority on LCP images
  7. Canonical URLs set explicitly using production domain
  8. Trailing slash behavior consistent site-wide
  9. Content pages use SSG or ISR, not client-side rendering
  10. Dynamic routes have generateStaticParams and generateMetadata
  11. OG images generated for content pages
  12. www vs non-www redirects configured

Run your deployed pages through the Ooty SEO Analyzer to verify that server-rendered HTML includes your metadata, structured data, and content. It checks what search engines actually see, which may differ from what you see in your browser if client-side rendering is involved.

Next.js gives React developers a framework that search engines can work with natively. The technical infrastructure is there. The checklist above makes sure you are actually using it.

For a comparison of how other platforms handle these same challenges, see our Shopify SEO guide (e-commerce) and WordPress SEO guide (traditional CMS).