astro-site-filesv0.5.0

sitemap.xml

Every built page, with priority and changefreq rules, extra sources, hreflang alternates and index mode.

Enabled by default. sitemap: false turns it off.

Where the URLs come from

  1. The pages Astro reports in astro:build:done, including i18n fallback routes.
  2. Entries returned by sources.

For each discovered page the integration opens its HTML once and reads:

  • lastmod from the file’s modification date,
  • <meta http-equiv="refresh"> at the top: the page is a redirect and is dropped,
  • <meta name="robots" content="noindex"> (or googlebot) in the <head>: dropped unless excludeNoindex: false,
  • data-sitemap-changefreq and data-sitemap-priority on any JSON-LD <script> tag.

Always excluded: /404, /500, paths starting with /_, and the generated files themselves (sitemap.xml, sitemap-index.xml, robots.txt, llms.txt, rss.xml, feed.xml). The build log lists every path dropped by these rules. Segments like /api/ or /drafts/ are not excluded automatically; use exclude or filter.

Options

interface SitemapOptions {
  siteUrl?: string
  sources?: SitemapSource[]
  exclude?: (string | RegExp)[]
  filter?: (url: string) => boolean
  excludeNoindex?: boolean
  priority?: PriorityRule[]
  changefreq?: ChangefreqRule[]
  localeAgnosticRules?: boolean
  output?: {
    mode?: 'single' | 'index'
    maxUrls?: number
    filename?: string
  }
  audit?: {
    warnOnEmpty?: boolean
    errorOnDuplicates?: boolean
  }
  serialize?: (entry: ResolvedSitemapEntry) =>
    ResolvedSitemapEntry | undefined | Promise<ResolvedSitemapEntry | undefined>
  i18n?: I18nOptions
}

type SitemapSource = () => Promise<SitemapEntry[]>

interface SitemapEntry {
  loc: string
  lastmod?: string
  priority?: number
  changefreq?: Changefreq
}

interface PriorityRule { pattern: string | RegExp; priority: number; allLocales?: boolean }
interface ChangefreqRule { pattern: string | RegExp; changefreq: Changefreq; allLocales?: boolean }
interface I18nOptions { defaultLocale: string; locales: Record<string, string> }
Option Default Effect
siteUrl Astro site Host for <loc>; base is appended either way
sources [] Extra entries; relative loc values are prefixed with site and base
exclude [] Path prefix or RegExp; discovered pages only
filter – Receives the full URL, false drops it; discovered pages only
excludeNoindex true Drop noindex pages
priority, changefreq [] Rules by path; first match wins
localeAgnosticRules false Match rules against the path without locale prefix
output.mode 'single' 'index' writes sitemap-index.xml plus sitemap-1.xml …
output.maxUrls 50000 More entries switch to index mode automatically
output.filename sitemap.xml Single-file mode only
serialize – Transform or drop (undefined) each resolved entry, sources included
i18n Astro i18n Locale path → hreflang code, for alternates

exclude and filter do not touch entries from sources; filter those in the source itself or in serialize.

Built-in priority and changefreq

Without a matching rule:

  • priority by path depth: / 1.0, one segment 0.9, two 0.8, deeper 0.7;
  • changefreq weekly for / and paths containing /blog/, /artikel/, /insights/, /news/, /post/, /posts/, /update/ or /updates/, otherwise monthly.

Depth is counted below the base path and ignores a known locale prefix, so /de/ scores like /. Explicit values from sources or data-sitemap-* attributes win over rules.

// Entries at /, /blog/, /blog/hello-world/ and /about/, all without rules
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated by @casoon/astro-site-files -->
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://example.com/</loc>
    <lastmod>2026-09-01</lastmod>
    <changefreq>weekly</changefreq>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>https://example.com/blog/</loc>
    <lastmod>2026-09-01</lastmod>
    <changefreq>weekly</changefreq>
    <priority>0.9</priority>
  </url>
  <url>
    <loc>https://example.com/blog/hello-world/</loc>
    <lastmod>2026-09-01</lastmod>
    <changefreq>weekly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://example.com/about/</loc>
    <lastmod>2026-09-01</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.9</priority>
  </url>
</urlset>

Multilingual sites

With Astro’s i18n config set, entries that differ only in their locale prefix are grouped. Each of them gets one <xhtml:link rel="alternate" hreflang="…" href="…"/> per variant plus an x-default link to the defaultLocale variant. Set sitemap.i18n only when the mapping differs from Astro’s.

Your own priority and changefreq rules match the real, prefixed path. To write a rule once for all languages, set localeAgnosticRules: true, or allLocales: true on a single rule:

siteFiles({
  sitemap: {
    localeAgnosticRules: true,
    changefreq: [
      { pattern: '/blog/', changefreq: 'daily' },
      { pattern: '/de/aktion/', changefreq: 'hourly', allLocales: false },
    ],
  },
})

Extra entries

siteFiles({
  sitemap: {
    exclude: ['/drafts/'],
    priority: [{ pattern: '/blog/', priority: 0.9 }],
    sources: [
      async () => [{ loc: '/landing/spring/', lastmod: '2026-09-01' }],
    ],
  },
})

Audit hints

sitemap/no-site-url, sitemap/empty-sitemap, sitemap/duplicate-urls and sitemap/invalid-priority. See build-time audit.

Edit this page on GitHub · Docs for v0.5.0