Technical SEOJanuary 22, 202614 min read

Next.js SEO: The Complete Technical Guide for App Router

A comprehensive guide to implementing technical SEO in Next.js 14+ with App Router. Covers metadata API, JSON-LD schema, sitemap generation, robots.txt, canonical tags, and Core Web Vitals.

K

Kinetic Team

Digital Growth Engineers

Why Next.js is the Best Framework for SEO

Next.js has become the gold standard for SEO-optimized web development, and for good reason. The App Router architecture in Next.js 14+ provides first-class support for every technical SEO requirement: server-side rendering, static generation, metadata APIs, sitemap generation, and more — all built in.

This guide covers everything you need to implement a complete technical SEO system in a Next.js App Router project.

The Metadata API: Your Foundation

In Next.js App Router, the metadata export is how you control everything search engines see:

import type { Metadata } from 'next'

export const metadata: Metadata = {

title: {

template: '%s | Your Brand',

default: 'Your Brand | Primary Keyword Phrase',

},

description: 'Clear, specific description under 160 characters that includes your primary keyword.',

metadataBase: new URL('https://yourdomain.com'),

alternates: {

canonical: 'https://yourdomain.com/page-slug',

},

openGraph: {

type: 'website',

locale: 'en_US',

url: 'https://yourdomain.com/page-slug',

siteName: 'Your Brand',

title: 'Page Title | Your Brand',

description: 'Description for social sharing.',

images: [{ url: '/og-image.png', width: 1200, height: 630 }],

},

twitter: {

card: 'summary_large_image',

title: 'Page Title | Your Brand',

description: 'Description for Twitter.',

images: ['/og-image.png'],

},

robots: {

index: true,

follow: true,

googleBot: { index: true, follow: true, 'max-image-preview': 'large' },

},

}

Critical rule: You cannot export metadata from a file that uses "use client". If your page needs interactivity, create a server component wrapper that exports metadata and renders your client component.

JSON-LD Schema Markup

Structured data helps Google understand your content and can trigger rich results in search. The cleanest way to add JSON-LD in Next.js:

function JsonLd({ schema }: { schema: Record }) {

return (

type="application/ld+json"

dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}

/>

)

}

// Usage in a page:

export default function Page() {

return (

<>

"@context": "https://schema.org",

"@type": "Organization",

"name": "Your Company",

"url": "https://yourdomain.com",

}} />

...

)

}

Essential schemas for most websites:

  • Organization (on every page via layout)
  • WebSite (homepage)
  • Service (service pages)
  • FAQPage (pages with FAQs)
  • BreadcrumbList (inner pages)
  • Article (blog posts)
  • Sitemap Generation

    Next.js 13+ can generate dynamic sitemaps from a TypeScript file:

    // app/sitemap.ts
    

    import { MetadataRoute } from 'next'

    export default async function sitemap(): Promise {

    // Fetch dynamic routes (blog posts, etc.)

    const posts = await getBlogPosts()

    return [

    { url: 'https://yourdomain.com', lastModified: new Date(), priority: 1 },

    // ... static pages

    ...posts.map(post => ({

    url: https://yourdomain.com/blog/${post.slug},

    lastModified: new Date(post.dateISO),

    changeFrequency: 'monthly' as const,

    priority: 0.7,

    })),

    ]

    }

    Robots.txt

    // app/robots.ts

    import { MetadataRoute } from 'next'

    export default function robots(): MetadataRoute.Robots {

    return {

    rules: {

    userAgent: '*',

    allow: '/',

    disallow: ['/dashboard/', '/api/'],

    },

    sitemap: 'https://yourdomain.com/sitemap.xml',

    }

    }

    Core Web Vitals in Next.js

    Next.js provides built-in tooling for the three Core Web Vitals:

    LCP (Largest Contentful Paint): Use component with priority prop on above-the-fold images. This automatically preloads the image:

    Description

    CLS (Cumulative Layout Shift): Always provide width and height to components. Use font-display: swap via next/font. Avoid inserting content above existing content.

    FID/INP (Interaction to Next Paint): Break up large components with dynamic imports. Move heavy computation out of the render path.

    Font Optimization

    Load all fonts through next/font/google — never via tags:

    import { Inter, DM_Sans } from 'next/font/google'

    const dmSans = DM_Sans({

    subsets: ['latin'],

    display: 'swap',

    variable: '--font-dm-sans',

    })

    This automatically handles font-display: swap, preloading, and self-hosting the font files on your domain.

    Dynamic OG Images

    For blog posts and dynamic pages, generate unique OG images using Next.js opengraph-image.tsx:

    // app/blog/[slug]/opengraph-image.tsx

    import { ImageResponse } from 'next/og'

    export default function Image({ params }: { params: { slug: string } }) {

    const post = getPost(params.slug)

    return new ImageResponse(

    {post.title}

    )

    }

    Conclusion

    Technical SEO in Next.js is well-supported but requires deliberate implementation. The most impactful elements in order of priority:

  • 1.Proper metadata on every page (title, description, OG, canonical)
  • 2.Server rendering for critical content (no "use client" on content pages)
  • 3.JSON-LD schema on every page
  • 4.Sitemap and robots.txt
  • 5.Core Web Vitals optimization (image, font, layout stability)
  • See how Kinetic implements all of this in production →

    Next.jsSEOTechnical SEOApp RouterSchema

    FREE RESOURCE

    Get a free website growth audit

    We'll review your site and show you exactly what's costing you leads.

    Book a Discovery Call