CoursesSEO optimized content with Next.jsBuild a dynamic sitemap
Track
Work-ready Next.js

SEO optimized content with Next.js

Lesson
7

Build a dynamic sitemap

A sitemap helps search engines understand and index your website more effectively. Generate a dynamic sitemap to guide search crawlers through your content, showing them what pages exist and how often they change.
Log in to mark your progress for each Lesson and Task

A well-structured sitemap gives search engines clear guidance about your content hierarchy and update frequency.

Search engines like Google use sitemaps as a primary method to discover and understand your content. While they can crawl your site naturally through links, a sitemap:

  1. Ensures all your content is discoverable, even pages that might be deep in your site structure
  2. Helps search engines understand when content was last updated
  3. Allows you to indicate content priority
  4. Speeds up the indexing process for new content

This is especially important for dynamic content managed through Sanity, where pages might be added or updated frequently.

By the end of this lesson, you will:

  • Create a dynamic sitemap from Sanity content
  • Implement graceful validation error handling

Before diving into the code, let's understand what makes a good sitemap from a technical perspective:

  • XML Format: Search engines expect a specific XML format
  • Last Modified Dates: Helps search engines know when content was updated
  • Change Frequency: Indicates how often content changes
  • Priority: Suggests the importance of pages

Let's start with a GROQ query to fetch all page and post type documents.

Update queries.ts to include SITEMAP_QUERY
src/sanity/lib/queries.ts
// ...all other queries
export const SITEMAP_QUERY = defineQuery(`
*[_type in ["page", "post"] && defined(slug.current)] {
"href": select(
_type == "page" => "/" + slug.current,
_type == "post" => "/posts/" + slug.current,
slug.current
),
_updatedAt
}
`)

This query:

  • Gets all documents of type page and post
  • Dynamically creates a complete path depending on the value of _type
  • Returns that path as href, and the last updated date of the document

You've created a new query, so you'll need to create new types.

Terminal
npm run typegen

The Next.js app router has a special, reserved route for generating an XML sitemap response from an array of objects in JavaScript.

See the Next.js documentation for more details on the sitemap route

The route below fetches content from Sanity using the query above, and generates the shape of content response that Next.js requires.

Create a new route to generate the sitemap
src/app/sitemap.ts
import { MetadataRoute } from "next";
import { client } from "@/sanity/lib/client";
import { SITEMAP_QUERY } from "@/sanity/lib/queries";
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
try {
const paths = await client.fetch(SITEMAP_QUERY);
if (!paths) return [];
const baseUrl = process.env.VERCEL
? `https://${process.env.VERCEL_URL}`
: "http://localhost:3000";
return paths.map((path) => ({
url: new URL(path.href!, baseUrl).toString(),
lastModified: new Date(path._updatedAt),
changeFrequency: "weekly",
priority: 1,
}));
} catch (error) {
console.error("Failed to generate sitemap:", error);
return [];
}
}

After deploying your changes, you can test your sitemap by visiting http://localhost:3000/sitemap.xml on your site.

You should see something like this:

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://localhost:3000/welcome-to-layer-caker</loc>
<lastmod>2025-01-10T14:13:34.000Z</lastmod>
<changefreq>weekly</changefreq>
<priority>1</priority>
</url>
<!-- // all other URLs... -->
</urlset>

Even if your sitemap looks correct, checking with a sitemap validator tool is recommended. Especially as your website grows. It's very easy to miss validation errors. A solid option is XML Sitemaps for a free and quick check.

To ensure your sitemap is doing what it's meant to, keep these points in mind:

  • Regular Updates: Your sitemap should update when content changes
  • Size Limits: Keep under 50,000 URLs per sitemap file
  • Valid URLs: Ensure all URLs are properly formatted

At this stage, your sitemap will now automatically update whenever you publish new content in Sanity, helping search engines discover and index your content.

As you continue to enhance your sitemap implementation and expand out through other document types, you may want to consider adding different priorities for different page types to help search engines understand the relative importance of your content.

Next, you'll explore structured data and JSON-LD, a clever way of reusing your documents for set-and-forget SEO benefits.

You have 2 uncompleted tasks in this lesson
0 of 2