Dynamic Sitemap Generation for Next.js with Sanity Pages
You're right to feel that having two sitemaps with duplicate content is odd! The good news is that with modern Next.js (especially App Router), you don't actually need next-sitemap at all anymore. You can create a fully dynamic, server-side sitemap using Next.js's built-in MetadataRoute.Sitemap API.
The Modern Approach: Single Dynamic Sitemap
Instead of using next-sitemap, create a app/sitemap.ts (or app/sitemap.xml/route.ts) file that queries Sanity directly at request time. This gives you a single sitemap that's always up-to-date without needing redeployments:
// app/sitemap.ts
import { MetadataRoute } from 'next'
import { sanityFetch } from '@/sanity/lib/client'
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const query = `*[_type in ["page", "post"] && defined(slug.current)] {
"href": select(
_type == "page" => "/" + slug.current,
_type == "post" => "/posts/" + slug.current
),
_updatedAt
}`
const pages = await sanityFetch({ query })
return pages.map((page) => ({
url: `https://yourdomain.com${page.href}`,
lastModified: new Date(page._updatedAt),
changeFrequency: 'weekly',
priority: 0.8,
}))
}This approach is covered in detail in Sanity's dynamic sitemap guide.
Why This is Better
- No duplicate content - Single source of truth
- Always current - Reflects content changes immediately without redeployment
- Native Next.js - No extra dependencies
- Proper caching - Next.js handles revalidation automatically
- Uses Sanity's
_updatedAt- Accurate lastModified dates for search engines
When You Might Still Use next-sitemap
The only real reason to keep next-sitemap is if you need its postbuild generation for static exports or have complex sitemap index splitting requirements. But for most Sanity + Next.js apps with dynamic content, the native Next.js approach is simpler and more reliable.
The "two sitemaps" pattern from next-sitemap's docs (using getServerSideSitemap in a server-side route like app/server-sitemap.xml/route.ts) was really a workaround before Next.js had first-class sitemap support. Now that Next.js has MetadataRoute.Sitemap in the App Router, you can do everything in one place without the awkwardness of merging static and dynamic sitemaps or dealing with duplicate entries.
Show original thread4 replies
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.