Auditite
Back to blog
Technical SEO Technical SEO Audit 2025-09-05 12 min read

Next.js SEO Best Practices: Best Practices

Optimize your Next.js application for search engines. Covers SSR vs SSG, metadata API, dynamic rendering, and common crawlability pitfalls.

A

Auditite Team

Next.jsJavaScript SEOSSRtechnical SEO

Why Next.js SEO Requires Specific Attention

Next.js is one of the most popular React frameworks, used by companies from startups to Fortune 500 enterprises. Its flexibility is both its strength and its SEO challenge — Next.js offers multiple rendering strategies, and choosing the wrong one for SEO-critical pages can make your content invisible to search engines.

If you are building with Next.js, understanding how rendering choices affect crawlability is essential. For broader JavaScript SEO context, see our JavaScript SEO guide.

Rendering Strategies and SEO Impact

Static Site Generation (SSG)

Pages are pre-rendered at build time and served as static HTML.

SEO impact: Excellent. Search engines receive fully rendered HTML immediately. Fastest possible TTFB since pages are served from a CDN.

Best for: Blog posts, marketing pages, documentation, product pages that change infrequently.

Server-Side Rendering (SSR)

Pages are rendered on the server for every request.

SEO impact: Excellent. Search engines receive fully rendered HTML. Slightly slower TTFB than SSG because the server must render on each request.

Best for: Pages with frequently changing data, personalized content, pages that depend on request-time data.

Incremental Static Regeneration (ISR)

Pages are statically generated but revalidated at a configured interval.

SEO impact: Excellent. Combines the speed of SSG with the freshness of SSR. First request gets a cached version; background revalidation updates it.

Best for: E-commerce product pages, news articles, content that updates periodically but does not need real-time freshness.

Client-Side Rendering (CSR)

Pages render in the browser using JavaScript after the initial HTML loads.

SEO impact: Risky. Google can render JavaScript, but it is a two-phase process that delays indexing. Content may not be indexed at all if JavaScript errors occur. Other search engines (Bing, Yandex) have weaker JavaScript rendering.

Best for: Authenticated dashboards, internal tools, content behind login walls — never for SEO-critical public pages.

The Rule

Any page you want to rank in search should use SSG, SSR, or ISR — never client-side rendering alone.

Metadata Management

Next.js App Router (v13+)

The App Router provides a built-in metadata API. Define metadata in your layout.tsx or page.tsx files:

export const metadata = {
  title: 'Product Name - Category | Store Name',
  description: 'Compelling meta description under 160 characters.',
  openGraph: {
    title: 'Product Name - Category',
    description: 'Description for social sharing.',
    images: ['/images/product-og.jpg'],
  },
  alternates: {
    canonical: 'https://example.com/products/product-name',
  },
};

For dynamic pages, use the generateMetadata function:

export async function generateMetadata({ params }) {
  const product = await getProduct(params.slug);
  return {
    title: `${product.name} | Store Name`,
    description: product.metaDescription,
  };
}

Critical Metadata Checks

  • Unique title tags on every page — no two pages should share the same title
  • Canonical URLs — set explicitly to prevent duplicate content from query parameters or trailing slash variations
  • Open Graph and Twitter Card tags — for social sharing previews
  • Robots meta — use robots: { index: true, follow: true } for public pages and noindex for utility pages

Handling Dynamic Routes

generateStaticParams

For dynamic routes (/products/[slug]), use generateStaticParams to pre-render pages at build time:

export async function generateStaticParams() {
  const products = await getAllProducts();
  return products.map((product) => ({
    slug: product.slug,
  }));
}

This ensures all product pages are available as static HTML when Googlebot crawls them.

Pagination and Load More

If you paginate content with URL parameters (/blog?page=2), ensure:

  • Each paginated page has a unique canonical URL
  • Paginated pages are server-rendered, not loaded via client-side JavaScript
  • All paginated pages are included in your XML sitemap

XML Sitemap Generation

Static Sitemap

For smaller sites, create a sitemap.ts file in the app directory:

export default async function sitemap() {
  const products = await getAllProducts();
  return [
    { url: 'https://example.com', lastModified: new Date() },
    ...products.map((product) => ({
      url: `https://example.com/products/${product.slug}`,
      lastModified: product.updatedAt,
    })),
  ];
}

Large Site Sitemaps

For sites with thousands of pages, generate sitemap index files with multiple child sitemaps. Keep each sitemap under 50,000 URLs and under 50MB uncompressed.

Robots.txt Configuration

Create a robots.ts file in the app directory:

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

Block the /_next/ directory and any API routes that should not be crawled. See our robots.txt guide for detailed rules.

Common Next.js SEO Pitfalls

Client-Side Navigation and Crawlability

Next.js uses client-side navigation for internal links. While this provides fast page transitions for users, search engine crawlers may not execute this JavaScript. Ensure all important pages are:

  • Linked via standard <a> tags (Next.js Link component renders these)
  • Accessible without JavaScript execution
  • Included in your XML sitemap as a fallback

Loading States and Skeleton Screens

Suspense boundaries and loading states show placeholder content while data loads. If your critical SEO content is behind a loading state that requires client-side data fetching, search engines may index the loading state instead of the actual content.

Fix: Fetch SEO-critical data on the server. Use Suspense only for non-essential, below-the-fold content.

Middleware Redirects

Next.js middleware runs on the edge and can redirect requests. Ensure your redirects return proper HTTP status codes (301 for permanent, 302 for temporary) and do not create redirect chains.

Trailing Slash Consistency

Configure trailingSlash in next.config.js to enforce consistency across your entire site. Inconsistent trailing slashes create duplicate content.

Image Optimization

Next.js’s Image component provides automatic optimization:

  • Automatic WebP/AVIF conversion — serves modern formats to supporting browsers
  • Responsive sizing — generates and serves appropriate sizes via srcset
  • Lazy loading — enabled by default for images below the fold
  • Priority flag — set priority on your LCP image to preload it

Always include alt attributes on every image. For detailed image SEO strategies, read our image optimization guide.

Performance Monitoring

Next.js provides built-in Core Web Vitals reporting. Monitor:

  • LCP — ensure hero images and key content render within 2.5 seconds
  • CLS — prevent layout shifts from dynamic content loading
  • INP — keep interactive elements responsive

Use Auditite to run regular technical audits on your Next.js application, catching rendering issues, metadata gaps, and crawlability problems before they impact your rankings.

Stay in the loop

Get insights, strategies, and product updates delivered to your inbox.

No spam. Unsubscribe anytime.

Ready to see Auditite in action?

Get started and see how Auditite can transform your SEO auditing workflow.

Get started
Get started

Get insights delivered weekly

Join teams who get actionable playbooks, benchmarks, and product updates every week.