typescriptintermediate

Dynamic Sitemap Generation

Generate a comprehensive sitemap.xml from dynamic routes and database content.

typescript
// app/sitemap.ts
import type { MetadataRoute } from 'next';

const BASE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'https://example.com';

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  // Static pages
  const staticPages: MetadataRoute.Sitemap = [
    {
      url: BASE_URL,
      lastModified: new Date(),
      changeFrequency: 'daily',
      priority: 1,
    },
    {
      url: `${BASE_URL}/about`,
      lastModified: new Date(),
      changeFrequency: 'monthly',
      priority: 0.5,
    },
  ];

  // Dynamic pages from database/CMS
  const posts = await fetch('https://api.example.com/posts').then((r) => r.json());

  const postPages: MetadataRoute.Sitemap = posts.map(
    (post: { slug: string; updatedAt: string }) => ({
      url: `${BASE_URL}/blog/${post.slug}`,
      lastModified: new Date(post.updatedAt),
      changeFrequency: 'weekly' as const,
      priority: 0.8,
    })
  );

  // Category pages
  const categories = await getCategories();
  const categoryPages: MetadataRoute.Sitemap = categories.map(
    (cat: { slug: string }) => ({
      url: `${BASE_URL}/category/${cat.slug}`,
      lastModified: new Date(),
      changeFrequency: 'weekly' as const,
      priority: 0.7,
    })
  );

  return [...staticPages, ...postPages, ...categoryPages];
}

// For large sites, use multiple sitemaps:
// app/sitemap/[id]/route.ts
// export async function GET(req, { params }) {
//   const { id } = params;
//   // Generate paginated sitemap
// }

Use Cases

  • SEO optimization
  • search engine indexing
  • large content sites

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.