Next.js is inherently SEO-friendly, but there are specific configurations and optimizations that maximize your search performance. Here's our complete technical SEO checklist based on optimizing 100+ Next.js sites.
Server-Side Rendering (SSR) vs Static Generation: Use getStaticProps for content that doesn't change frequently (blog posts, landing pages). Use getServerSideProps only when content must be fresh on every request (dashboards, personalized pages). Static pages are faster and more crawlable.
Metadata management: Use Next.js 14+'s generateMetadata function for dynamic meta tags. Every page needs a unique title (50-60 characters), meta description (150-160 characters), canonical URL, and Open Graph tags for social sharing.
Structured data (JSON-LD) is essential for rich snippets. Implement Organization, BreadcrumbList, Article, Product, FAQ, and HowTo schemas where applicable. Use Next.js's Script component with strategy='afterInteractive' to avoid render blocking.
XML sitemap: Use next-sitemap or generate dynamically with a route handler. Include all indexable pages, set accurate lastmod dates, and exclude private/utility routes. Submit to Google Search Console and reference in robots.txt.
Robots.txt: Create a public/robots.txt that allows crawling of important routes and blocks admin, API, and private routes. Use the Next.js middleware for more sophisticated bot handling if needed.
Image optimization: Always use the Next.js Image component. It automatically serves WebP/AVIF, lazy loads, and generates responsive srcsets. Add descriptive alt text to every image. Use priority prop for above-the-fold images to prevent LCP delays.
Internal linking: Use Next.js Link component (not anchor tags) for client-side navigation benefits. Implement breadcrumb navigation, related content links, and a logical URL hierarchy. Flat URL structures (/blog/post-slug rather than /blog/2026/01/post-slug) perform better.
Core Web Vitals: Monitor LCP, INP, and CLS. Common Next.js-specific fixes: preload fonts with next/font, avoid layout shifts from dynamic content with Suspense boundaries, and minimize client-side JavaScript with Server Components.