komal.nakrani
Browse Themes
ThemesCategoriesDocsBlogTips & Tricks
SEO••By Komal Nakrani

Add a Sitemap to Astro in Two Minutes

Install @astrojs/sitemap, set site in astro.config.mjs, and Astro writes sitemap-index.xml on every build. Setup, excluding pages, lastmod and on-demand routes.

#Astro#SEO#Sitemap

To add a sitemap to an Astro site, run npx astro add sitemap, set site in astro.config.mjs, and build. Astro writes sitemap-index.xml and sitemap-0.xml into dist/ on every build, listing every static page, including pages generated by getStaticPaths().

Key Takeaways

  • One command installs and registers the integration: npx astro add sitemap.
  • The integration does nothing without site, because sitemaps need absolute URLs.
  • Use filter to keep pages like /thank-you/ out.
  • On-demand routes aren’t discovered automatically; list them with customPages.

Install it

npx astro add sitemap

astro add installs @astrojs/sitemap and adds it to your config. Then set your production URL:

// astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';

export default defineConfig({
  site: 'https://www.example.com',
  integrations: [sitemap()],
});

Run npm run build and check dist/sitemap-index.xml. It points to sitemap-0.xml, which lists your URLs. Large sites get sitemap-1.xml and so on; the integration splits at 45,000 entries by default (entryLimit).

Keep private pages out

sitemap({
  filter: (page) =>
    !page.includes('/thank-you/') &&
    !page.includes('/admin/') &&
    !page.endsWith('/404/'),
})

filter receives the full URL and keeps pages where it returns true. Anything with a noindex meta tag should also be filtered here, so you don’t send search engines mixed signals.

Add lastmod

lastmod helps search engines prioritise recrawling changed pages. Set it per URL with serialize:

// astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
import fs from 'node:fs';
import path from 'node:path';
import matter from 'gray-matter';

const blogDir = './src/content/blog';
const updated = new Map(
  fs.readdirSync(blogDir).filter((f) => /\.mdx?$/.test(f)).map((f) => {
    const { data } = matter(fs.readFileSync(path.join(blogDir, f), 'utf8'));
    return [f.replace(/\.mdx?$/, ''), data.updatedDate ?? data.pubDate];
  }),
);

export default defineConfig({
  site: 'https://www.example.com',
  integrations: [
    sitemap({
      serialize(item) {
        const slug = item.url.match(/\/blog\/([^/]+)\/?$/)?.[1];
        const date = slug && updated.get(slug);
        if (date) item.lastmod = new Date(date).toISOString();
        return item;
      },
    }),
  ],
});

Only set lastmod from real content dates. A build timestamp on every URL tells search engines nothing. (gray-matter is a separate install: npm install -D gray-matter.)

changefreq and priority are also supported, but Google has said it ignores them, so they’re not worth maintaining.

On-demand pages

The integration builds the sitemap from the routes Astro prerenders. Pages rendered on request (prerender = false) aren’t included, because their URLs aren’t known at build time. Add the ones you want indexed:

sitemap({
  customPages: ['https://www.example.com/store/', 'https://www.example.com/search/'],
})

Tell crawlers where it is

Add one line to public/robots.txt:

Sitemap: https://www.example.com/sitemap-index.xml

Then submit sitemap-index.xml in Google Search Console and Bing Webmaster Tools. The robots.txt tip shows how to generate this file from site so the domain lives in one place.

You can also link it from your <head> for discovery:

<link rel="sitemap" href="/sitemap-index.xml" />

Common problems

No sitemap in dist/. site isn’t set. The build log shows a warning from the integration.

Wrong domain in URLs. site is set to a staging or preview URL. Use the production origin.

Trailing slashes don’t match your links. The sitemap follows your trailingSlash and build.format settings; see Astro trailingSlash and build.format.

If you’re working in a Komal theme, the config file is covered in Astro configuration. The sitemap is one item on the Astro SEO checklist. For the full option list, the official @astrojs/sitemap docs are the reference.

FAQ

Does the Astro sitemap include dynamic routes?

Yes, for static builds. Any page generated by getStaticPaths() is included, because the integration reads the final list of built pages. On-demand routes need customPages.

Where is the Astro sitemap URL?

At /sitemap-index.xml on your domain. It links to one or more sitemap-N.xml files.