Metadata and SEO Implementation
Search engine optimization (SEO) is a core strength of Next.js. In the App Router, you configure search crawler tags, browser headers, and social sharing OpenGraph card details using the built-in Metadata API.
1. Defining Static Metadata
For static pages, declare a metadata constant inside any server component page.tsx or layout.tsx file:
// src/app/about/page.tsx
import { Metadata } from "next";
export const metadata: Metadata = {
title: "About Us | My Enterprise",
description: "Learn more about our corporate team and core mission values.",
openGraph: {
title: "About Us | My Enterprise",
description: "Learn more about our corporate team and core mission values.",
images: ["/og-about.jpg"]
}
};
export default function AboutPage() {
return <h1>About Us</h1>;
}2. Generating Dynamic Metadata
For dynamic routes (such as blog posts or product catalogs), you must generate metadata dynamically based on route parameter variables. Use the generateMetadata function helper:
// src/app/blog/[slug]/page.tsx
import { Metadata } from "next";
interface ProductProps {
params: Promise<{ slug: string }>;
}
// Next.js executes this function before rendering the page HTML
export async function generateMetadata({ params }: ProductProps): Promise<Metadata> {
const resolvedParams = await params;
const slug = resolvedParams.slug;
// Retrieve post details from database
const post = await getPostDetails(slug);
return {
title: `${post.title} | Corporate Blog`,
description: post.excerpt,
openGraph: {
images: [post.coverImage]
}
};
}
async function getPostDetails(slug: string) {
// Mock API call
return {
title: "Next.js SEO Masterclass",
excerpt: "Step-by-step metadata setup guide.",
coverImage: "/og-blog-seo.jpg"
};
}
export default function BlogPostPage() {
return <article>Post content goes here...</article>;
}3. Creating XML Sitemaps (sitemap.ts)
Sitemaps tell search engines which pages on your site are available for crawling. You can generate a dynamic sitemap.xml by creating a sitemap.ts file in the root of your app directory:
// src/app/sitemap.ts
import { MetadataRoute } from "next";
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrl = "https://example.com";
// In production, fetch dynamic database slugs
const posts = [{ slug: "hello-world" }, { slug: "nextjs-caching" }];
const postUrls = posts.map(p => ({
url: `${baseUrl}/blog/${p.slug}`,
lastModified: new Date()
}));
return [
{
url: baseUrl,
lastModified: new Date(),
changeFrequency: "daily",
priority: 1.0
},
{
url: `${baseUrl}/about`,
lastModified: new Date(),
changeFrequency: "monthly",
priority: 0.8
},
...postUrls
];
}4. Setting Search Rules (robots.ts)
Configure search engine crawl boundaries by adding a robots.ts file:
// src/app/robots.ts
import { MetadataRoute } from "next";
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: "*",
allow: "/",
disallow: "/admin/" // Block search crawlers from indexing the admin dashboard panel
},
sitemap: "https://example.com/sitemap.xml"
};
}Published on Last updated: