---
title: 'sitemap'
description: 'Generate /sitemap.xml automatically, with per-language sitemaps and an index for multilingual sites. Any page can opt out from its front matter.'
slug: 'sitemap'
type: 'article'
date: 2026-04-15T00:00:00.000Z
lang: 'en'
url: 'https://www.eleventy-baseline.dev/docs/modules/sitemap/'
---

`INTERNAL_KEY`: '\_sitemap'

---

## What it does

The sitemap module emits `/sitemap.xml` from your built pages. In single-language mode, one flat sitemap. With multilang active, one sitemap per language at `/<lang>/sitemap.xml` plus a sitemap index at `/sitemap.xml` that points at each.

Any page can opt out from its front matter, and the module also adds a computed `page.sitemap` to every page as a readable summary of where it stands.

The sitemap is rendered through virtual templates: synthetic templates Baseline injects into the build, not files you write. They use Eleventy's normal collection access (`collections.all`) and the same data cascade your pages do.

---

### Active when

`options.sitemap` is truthy. Defaults to `true`. Set `sitemap: false` to skip the module entirely.

---

### Lifecycle

- **Build-time.** Registers virtual templates: a single `/sitemap.xml`, or per-language sitemaps plus an index if multilang is active.
- **Cascade-time.** Computed `page.sitemap` resolves on every page from the cascade (its `ignore`, `changefreq`, `priority` fields).

The sitemap virtual templates set `_internal: true` so they do not get a page context. They are emitted as XML, not HTML, and the head module skips them.

---

## How it works

1. **Compute `page.sitemap`.** Registered as `eleventyComputed.page.sitemap`. Resolves `ignore`, `changefreq`, `priority` from cascade data.
2. **Resolve language config.** Reads `settings.languages` through [`normalizeLanguageMap`](https://github.com/apleasantview/eleventy-plugin-baseline/blob/main/_baseline/core/utils/normalize-language-map.js), the same helper the multilang module uses.
3. **Register virtual templates.**
   - Single-language: one template at `/sitemap.xml`. Loops `collections.all`, filters excluded pages, emits `<urlset>` with `<loc>`, optional `<lastmod>`, optional `<changefreq>`, optional `<priority>`.
   - Multilingual: one template per language at `<lang>/sitemap.xml`, plus a sitemap index template at `/sitemap.xml`. Per-language sitemaps include `<xhtml:link>` alternates for every translation sibling, sourced from the translation map.

Each virtual template sets `_internal: true` so the page-context registry skips it (it is not a real page). It also sets `eleventyExcludeFromCollections: true` so the sitemap does not list itself.

---

## Defaults

- **Sitemap output.** `/sitemap.xml` in single-language mode, or `/<lang>/sitemap.xml` plus `/sitemap.xml` (the index) when multilang is active.
- **Computed `page.sitemap`.** Every page receives `{ ignore, changefreq, priority }`, with `ignore` resolved from `data.noindex`, `data.page.noindex` or `data.settings.noindex`, `changefreq` an empty string and `priority` `-1`. This is a readable summary rather than the mechanism: the template does its own filtering off the front matter, so changing `page.sitemap` from a template does not change the output.
- **Exclusion rules.** The template drops a page when any of these is true, each read straight from the page's data: `noindex: true`, `sitemap.ignore: true`, `eleventyExcludeFromCollections: true`, or no `url` (a `permalink: false` record). `settings.noindex` empties the whole file in one go.
- **`changefreq` and `priority`** are emitted only when the page's own front matter carries them under `sitemap`. The computed defaults never reach the XML.

---

### Settings

The sitemap module reads three keys on the `settings` argument. Full shape on [[site-settings | Site settings]].

{% tableBlock true %}

| Key                  | Type      | Used for                                                                                                                |
| -------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------- |
| `settings.url`       | `string`  | Building absolute `<loc>` entries.                                                                                      |
| `settings.noindex`   | `boolean` | When `true`, the sitemap file is still written but lists nothing.                                                       |
| `settings.languages` | `object`  | Drives per-language partitioning when multilang is active. Read through the same normalisation as the multilang module. |

{% endtableBlock %}

---

### Options

{% tableBlock true %}

| Option    | Type      | Default | Meaning                                      |
| --------- | --------- | ------- | -------------------------------------------- |
| `sitemap` | `boolean` | `true`  | Activate the module. Set `false` to skip it. |

{% endtableBlock %}

---

### Per-page sitemap controls

Set these in front matter:

```yaml
sitemap:
  ignore: true # exclude from sitemap (page still renders)
  changefreq: weekly
  priority: 0.8
  lastmod: 2026-01-15
```

- **`noindex: true`** in front matter excludes the page from the sitemap and (because the head module reads the same field) emits a `robots` meta tag.
- **`sitemap.ignore: true`** is sitemap-only exclusion. The page still renders and search engines can still index it.
- **`eleventyExcludeFromCollections: true`** keeps the page out of all collections, including `collections.all`, so the sitemap never sees it.

`lastmod` uses `sitemap.lastmod` if you set it; otherwise the page date.

---

## Multilingual mode

When the multilang module is active and `settings.languages` has more than one entry, the layout switches automatically:

- `/en/sitemap.xml`, `/nl/sitemap.xml`, etc.: one per language, listing only that language's pages plus hreflang alternates.
- `/sitemap.xml`: a sitemap index pointing at each per-language sitemap.

---

## Tips

- Set `settings.noindex: true` to empty the sitemap (useful for staging environments). The file is still written; it just lists no pages.
- Search engines treat `changefreq` and `priority` as hints. Set them sparingly, only where you actually have a useful answer.
- Provide `lastmod` in front matter when you care about freshness signals. Without one, the page date is used.
- URLs are absolutized via Eleventy's `HtmlBasePlugin` using `settings.url` and `pathPrefix`. Keep `settings.url` origin-only (no trailing path), and use `pathPrefix` for sub-path deployments.

---

## Peer deps

None.

---

## See also

- [[site-settings | Site settings]] for `url`, `noindex`, `languages`.
- [[multilang | multilang module]] for the language normalisation and translation map shared with this module.
- [[page-context | Page context]] for `_internal: true`, the opt-out the virtual templates use.
- [[sitemaps-and-drafts | Tutorial: sitemaps and drafts]]
