Next.js SEO Guide

Post Date:17 Feb 2026 - 09:32 PM

Complete Next.js SEO Guide: Metadata, Sitemap, Robots, and Dynamic SEO


Search Engine Optimization (SEO) is essential for any modern web application. A properly optimized website improves search engine visibility, increases organic traffic, and enhances user engagement. Next.js provides powerful built-in SEO features through its App Router and Metadata API. These features allow developers to easily manage meta tags, Open Graph data, sitemap, robots.txt, and structured data without external libraries. In this article, I will explain how I implement a complete SEO system in my Next.js applications using real production-level examples.


Next.js is one of the best frameworks for SEO because it supports:

Server-Side Rendering (SSR)
Static Site Generation (SSG)
Incremental Static Regeneration (ISR)
Built-in Metadata API
Automatic sitemap and robots support
Dynamic metadata for dynamic routes
Structured data support (JSON-LD)

These features allow search engines like Google to properly crawl and index your website.



1. Creating a Sitemap in Next.js


A sitemap helps search engines discover all important pages on your website.
Create this file:
app/sitemap.ts
Example:
import type { MetadataRoute } from "next";

export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: "https://aminul.tech",
lastModified: new Date(),
changeFrequency: "yearly",
priority: 1,
},
{
url: "https://aminul.tech/about",
lastModified: new Date(),
changeFrequency: "monthly",
priority: 0.8,
},
{
url: "https://aminul.tech/blog",
lastModified: new Date(),
changeFrequency: "weekly",
priority: 0.7,
},
];
}
This automatically generates:
https://aminul.tech/sitemap.xml
Benefits:
Helps search engines crawl pages faster
Improves indexing
Improves SEO ranking



2. Creating robots.txt in Next.js


The robots.txt file tells search engines which pages they can crawl and which pages they should avoid.
Create this file:
app/robots.ts

Example:

import type { MetadataRoute } from "next";

export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: "*",
allow: "/",
disallow: "/private/",
},
sitemap: "https://aminul.tech/sitemap.xml",
};
}

This generates:

https://aminul.tech/robots.txt



3. Creating a Reusable SEO Function


Instead of repeating metadata in every page, I use a reusable SEO generator function.
Create file:
Seo/generateSEO.ts
Example:
import type { Metadata } from "next";

type SEOProps = {
title: string;
description: string;
keywords?: string;
url?: string;
images?: string[];
author?: string;
};

export default function generateSEO({
title,
description,
keywords = "Next.js, React, Portfolio, Web Developer",
url = "https://aminul.tech",
images = ["https://aminul.tech/banner.png"],
author = "Md Aminul Islam",
}: SEOProps): Metadata {
return {
title,
description,
keywords,

alternates: {
canonical: url,
},

authors: [{ name: author, url }],

openGraph: {
title,
description,
url,
siteName: "Aminul Portfolio",
images: images.map((image) => ({
url: image,
width: 1200,
height: 630,
alt: title,
})),
type: "website",
},

twitter: {
card: "summary_large_image",
title,
description,
images,
},

robots: {
index: true,
follow: true,
},
};
}
Benefits:
  • Reusable
  • Clean code
  • Consistent SEO across all pages



4. Static Page SEO Example


Example static page:
app/about/page.tsx
import generateSEO from "@/Seo/generateSEO";

export const metadata = generateSEO({
title: "About Me | Aminul Portfolio",
description: "Learn more about Aminul Islam, a full-stack web developer.",
url: "https://aminul.tech/about",
});

export default function AboutPage() {
return <div>About Page</div>;
}
Next.js automatically injects meta tags into the HTML.



5. Dynamic SEO for Dynamic Routes


Dynamic metadata is essential for blogs, products, and dynamic pages.
Example:
app/blog/[slug]/page.tsx
import type { Metadata } from "next";
import generateSEO from "@/Seo/generateSEO";

type Props = {
params: {
slug: string;
};
};

export async function generateMetadata({ params }: Props): Promise<Metadata> {
const post = await fetch(
`https://api.example.com/posts/${params.slug}`
).then((res) => res.json());

return generateSEO({
title: post.title,
description: post.excerpt,
url: `https://aminul.tech/blog/${params.slug}`,
images: [post.image],
});
}

export default function BlogPost({ params }: Props) {
return <div>Blog Post: {params.slug}</div>;
}
This ensures each blog post has unique SEO metadata.



6. Root Layout SEO Setup


Root layout defines global HTML structure.
app/layout.tsx
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<head>
<link rel="icon" href="/logo.svg" />
<link rel="canonical" href="https://aminul.tech" />
</head>
<body>{children}</body>
</html>
);
}



7. Structured Data (JSON-LD) for Better SEO


Structured data helps Google understand your content better.
Example:
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "BlogPosting",
headline: post.title,
description: post.excerpt,
image: post.image,
author: {
"@type": "Person",
name: "Md Aminul Islam",
},
datePublished: post.date,
}),
}}
/>
Benefits:
  • Rich snippets in Google
  • Better ranking
  • Better visibility



8. SEO for E-Commerce Products


Example dynamic product SEO:
export async function generateMetadata({ params }): Promise<Metadata> {
const product = await getProduct(params.slug);

return {
title: product.name,
description: product.description,

openGraph: {
title: product.name,
description: product.description,
images: [product.image],
type: "product",
},

twitter: {
card: "summary_large_image",
title: product.name,
images: [product.image],
},
};
}



SEO Checklist for Next.js


Always implement these:
  • Metadata API
  • Sitemap
  • robots.txt
  • OpenGraph tags
  • Twitter cards
  • Canonical URLs
  • Structured Data
  • Dynamic metadata