Next.js Dynamic Routing: Creating SEO-Friendly URL Structure
Learn to create SEO-friendly URL structures using dynamic routing with Next.js App Router. Slug parameters, catch-all routes, and metadata optimization.
Next.js is one of the most popular React frameworks for modern web applications. The dynamic routing features that come with the App Router provide powerful tools for creating SEO-friendly URL structures. In this guide, we'll examine slug-based URL creation and SEO optimization with Next.js in detail.
Next.js App Router Basics
The App Router in Next.js 13+ uses a file-based routing system:
app/
├── page.tsx # / (Homepage)
├── blog/
│ ├── page.tsx # /blog
│ └── [slug]/
│ └── page.tsx # /blog/article-title
├── products/
│ └── [category]/
│ └── [id]/
│ └── page.tsx # /products/electronics/123Dynamic Route Parameters
Single Parameter [slug]
For singular content like blog posts:
// app/blog/[slug]/page.tsx
import { notFound } from 'next/navigation';
interface PageProps {
params: { slug: string };
}
export default async function BlogPost({ params }: PageProps) {
const post = await getPost(params.slug);
if (!post) {
notFound();
}
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}Catch-All Routes [...slug]
For multi-segment URLs:
// app/docs/[...slug]/page.tsx
// Matches: /docs/getting-started
// /docs/api/reference
// /docs/guides/advanced/routingSEO Metadata Optimization
generateMetadata Function
Creating SEO metadata for dynamic pages:
// app/blog/[slug]/page.tsx
import { Metadata } from 'next';
export async function generateMetadata(
{ params }: PageProps
): Promise<Metadata> {
const post = await getPost(params.slug);
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
type: 'article',
},
};
}Static Generation with SEO
generateStaticParams
Creating static pages at build time:
export async function generateStaticParams() {
const posts = await getAllPosts();
return posts.map((post) => ({
slug: post.slug,
}));
}Slug Generation Function
// lib/utils/slug.ts
export function generateSlug(text: string): string {
return text
.toLowerCase()
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.replace(/[^a-z0-9\s-]/g, '')
.replace(/\s+/g, '-')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '');
}Sitemap Generation
// app/sitemap.ts
import { MetadataRoute } from 'next';
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const posts = await getAllPosts();
return posts.map((post) => ({
url: `https://example.com/blog/${post.slug}`,
lastModified: new Date(post.updatedAt),
}));
}Best Practices
- Lowercase URLs: Convert all slugs to lowercase
- Use hyphens: Prefer hyphens (-) as word separators
- Keep it short: Keep URLs under 75 characters
- Include keywords: Include main keyword in slug
- Remove stopwords: Remove words like and, the, for
Conclusion
Dynamic routing with Next.js App Router provides a powerful and flexible system for creating SEO-friendly URL structures. Using generateMetadata and generateStaticParams functions, you can achieve excellent results for both search engine optimization and user experience.