Lesson 7

Building a dynamic sitemap

A sitemap helps search engines understand and index your website more effectively. Think of it as a map that guides search crawlers through your content, showing them what pages exist and how often they change.

Just like how we built SEO overrides to give content editors control over metadata, a well-structured sitemap gives search engines clear guidance about your content hierarchy and update frequency.

Why this approach?

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.

Learning objectives

By the end of this lesson, you'll be able to:

  • Create a dynamic sitemap that updates automatically
  • Connect your sitemap to Sanity content
  • Implement graceful error handling

Understanding sitemaps

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

Building the sitemap

Let's start with a simple GROQ query to fetch our pages:

query/sitemap-query.ts
const sitemapQuery = `*[_type == "page" && defined(slug.current)] {
  "slug": slug.current,
  _updatedAt
}`;

This query:

  • Gets all documents of type page
  • Makes sure they have a slug
  • Fetches both the slug and last updated date

Now let's create your sitemap function:

app/sitemap.ts
import { MetadataRoute } from "next";
import { client } from "@/lib/sanity/client";
import sitemapQuery from "~/lib/queries/sitemap";
 
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  try {
    // Fetch pages from Sanity
    const pages = await client.fetch(sitemapQuery);
 
    if (!pages) return [];
 
    const baseUrl = process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000";
 
    // Transform pages into sitemap format
    return pages.map((page: { slug: string; _updatedAt: string }) => ({
      url: `${baseUrl}/${page.slug}`,
      lastModified: new Date(page._updatedAt),
      changeFrequency: "weekly" as const,
      priority: 1,
    }));
  } catch (error) {
    console.error("Failed to generate sitemap:", error);
    return [];
  }
}

Let's break down what this code does:

  • URL Construction: Builds full URLs using your site's baseUrl
  • Metadata: Uses the _updatedAt field to set the last modified date
  • Error Handling: Returns an empty array and console.error if something goes wrong

Testing your sitemap

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

You should see something like this:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://yoursite.com/about</loc>
    <lastmod>2024-01-01T12:00:00.000Z</lastmod>
    <changefreq>weekly</changefreq>
    <priority>1.0</priority>
  </url>
  <!-- More 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 (opens in a new tab) for a free and quick check.

Best practices

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.