Drop-in sitemap.xml for Scriptor 2.x.
Install it and /sitemap.xml starts serving a sitemaps.org <urlset> listing every public URL on the site, each with a <lastmod>. No template edits, no theme code: the plugin hooks Scriptor's routing directly.
Two URL sources are merged:
- CMS pages — every active page from the Pages category. Nested pages get their full parent-chain path; the empty-slug home page becomes
/.lastmodis the page's last-updated timestamp. - scriptor-markdown-pages URLs — if that plugin is installed (≥ 0.1.9). The dependency is soft: on a site without it, the sitemap is simply pages-only.
lastmodis the markdown file's mtime.
composer require bigins/scriptor-sitemapThe plugin is auto-discovered (composer type scriptor-plugin); there is nothing to register.
Installing from a non-Packagist checkout? Add the VCS repository first:
composer config repositories.scriptor-sitemap vcs https://github.com/bigin/scriptor-sitemap composer require bigins/scriptor-sitemap:^0.1
sitemap.xml is not a page — it returns application/xml, not HTML. So the plugin does not try to resolve it as one. It subscribes to RouteNotFound, the last-chance event Scriptor dispatches before rendering its 404. When the request path matches the configured sitemap path, the plugin emits the XML and ends the request; everything else falls through to the normal 404 untouched.
This is the batteries-included version of the Generate sitemap.xml from PageRepository cookbook recipe — same short-circuit pattern, plus markdown-pages composition and configuration.
All keys are optional, read from $config['plugins']['sitemap']:
'plugins' => [
'sitemap' => [
// Serve at a different path (default '/sitemap.xml').
'path' => '/sitemap.xml',
// Pin a canonical absolute base for <loc>. When omitted the
// base is derived from the live request (scheme + Host,
// honouring a TLS-terminating proxy's X-Forwarded-Proto).
'base_url' => 'https://example.com',
// Drop CMS pages by template / pagetype / id / slug.
'exclude_templates' => ['search', 'thanks'],
'exclude_pagetypes' => ['redirect'],
'exclude_ids' => [42],
'exclude_slugs' => ['drafts'],
// Drop URL paths (CMS *and* markdown). An entry matches the
// exact path or anything beneath it: '/private' removes
// '/private/' and all children, but not '/privacy/'.
'exclude_paths' => ['/private'],
// Turn the route off entirely.
'enabled' => true,
],
],Out of the box, with no configuration, the plugin serves /sitemap.xml listing every active CMS page plus every markdown-pages URL, using the requested host for <loc>. That is the right behaviour for most sites.
Point crawlers at the sitemap from your robots.txt:
Sitemap: https://example.com/sitemap.xml
- PHP 8.2+
- Scriptor 2.x (provides the
RouteNotFoundevent andPageRepository) - Optional:
bigins/scriptor-markdown-pages≥ 0.1.9 to include markdown URLs
MIT — see LICENSE.