GitHub Packages · MIT · Node ≥ 18

sitemap-beacon

Audit XML sitemaps against your built static site: every URL should be a real, indexable, canonical page, and every such page should be listed.

  1. 1 Point the @mrlouiswright scope at GitHub Packages in .npmrc

    @mrlouiswright:registry=https://npm.pkg.github.com
  2. 2 Install

    npm i -D @mrlouiswright/sitemap-beacon
Installing from GitHub Packages needs a token

Published to GitHub Packages, not npmjs.com. GitHub Packages needs a GitHub token with read:packages to install, even for public packages: add //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} to .npmrc or run npm login --registry=https://npm.pkg.github.com.

~/project — zsh
$ npx sitemap-beacon dist --base-url https://example.com --fail-on mediumsitemap-beacon — https://example.com8 page(s); 2 sitemap file(s) with 10 URL(s) on https://example.com HIGH     sitemap_index.xml:4 sitemap_index.xml lists sitemap-posts.xml, which is not in the build [sitemap-child-missing]         ↳ fix: Generate the child sitemap or remove it from the index.HIGH     sitemap-pages.xml:6 <loc>/blog/copy.html</loc> is not an absolute http(s) URL [sitemap-loc-invalid]         ↳ fix: Use the full URL, e.g. https://example.com/blog/copy.html.HIGH     sitemap-pages.xml:9 https://example.com/private/secret.html is noindex (X-Robots-Tag in _headers) [sitemap-url-noindex]         ↳ fix: Remove noindex pages from the sitemap, or remove the noindex.HIGH     sitemap-pages.xml:10 https://example.com/tag.html is noindex (<meta name="robots">) [sitemap-url-noindex]         ↳ fix: Remove noindex pages from the sitemap, or remove the noindex.HIGH     sitemap-pages.xml:11 https://example.com/old.html is a meta-refresh redirect page (old.html) [sitemap-url-non-200]         ↳ fix: List the destination URL instead.... 8 high, 5 medium, 5 low, 1 info✔ Passing (fail-on: none).
Sample output from the sitemap-beacon README.

Why it exists

Sitemaps drift away from the site they describe. A page gets noindex but stays in the sitemap. A post is canonicalised to its new URL, but the old one is still listed. The build stamps every lastmod with the deploy time, so Google stops trusting the dates. A section is added and never makes it into the sitemap. sitemap-beacon reads your sitemaps (indexes, children and .xml.gz) alongside the built HTML and checks each one against the other. It reports the file, line, severity and a concrete fix, before you deploy.

CLI, library and GitHub Action. Node.js 18+, zero runtime dependencies. Works on any static build output (Astro, Next.js “output: 'export'”, Eleventy, Hugo, Jekyll, Docusaurus, VitePress, plain HTML) and runs offline: point it at the folder your build writes. By Louis Wright.

Features

Discovery

sitemap.xml, sitemap_index.xml, sitemap-*.xml, .xml.gz, and the files named in Sitemap: lines in robots.txt. Sitemap indexes are followed to their children, and missing children are reported.

Protocol

valid <urlset>/<sitemapindex> root and namespace, 50,000-URL and 50 MB limits, absolute and properly escaped <loc>, duplicates, and valid changefreq/priority (which Google ignores; reported as info).

Each URL vs the build

no page at that URL (or only a meta-refresh stub or an error page), noindex from meta robots or from X-Robots-Tag in _headers/vercel.json, canonicalised to a different URL, or another host or protocol.

lastmod

invalid W3C datetime, in the future, older than the page's own dateModified/article:modified_time, the same on every URL (a build timestamp), and an optional maximum age.

Coverage

indexable, self-canonical pages that are not in any sitemap. Use notInSitemap globs for pages you leave out on purpose.

Output

text, JSON, SARIF 2.1.0 and Markdown; --fail-on; exit codes 0/1/2; allowlist entries with expiry dates.

Usage

# Example

 npx sitemap-beacon dist

# Example

 npx sitemap-beacon dist --base-url https://example.com --fail-on medium

# Example

 npx sitemap-beacon public --sitemap sitemap-index.xml --max-age-days 730

# Example

 npx sitemap-beacon out --clean-urls --not-in-sitemap "/tags/**,/page/*"

CI / GitHub Action

permissions:
  contents: read
  security-events: write   # only needed for the SARIF upload
jobs:
  sitemap-beacon:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
        with: { persist-credentials: false }
      - run: npm ci && npm run build   # produce the static site first
      - uses: MrLouisWright/sitemap-beacon@v1
        with:
          path: dist
          fail-on: high
          sarif: sitemap-beacon.sarif
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with: { sarif_file: sitemap-beacon.sarif }

Options & flags

FlagDescription
Site
--base-url <url>Public URL of the site, e.g. https://example.com (default: inferred from canonical/og:url)
--include <globs>Only check these pages (file or URL path globs, comma-separated)
--exclude <globs>Skip these pages
--clean-urlsPages are served without .html (about.html -> /about)
Checks
--sitemap <files>Sitemap file(s) relative to the site dir (default: auto-detect)
--max-age-days <n>Report lastmod older than n days (info)
--no-coverageDo not report pages missing from the sitemap
Common
-c, --config <file>JSON config (default: .sitemap-beacon.json or "sitemapBeacon" in package.json)
-f, --format <fmt>text (default) | json | sarif | markdown
--json <file>Also write a JSON report
--sarif <file>Also write SARIF 2.1.0
--markdown <file>Also write Markdown (e.g. for a job summary)
--fail-on <sev>critical | high | medium | low | info | none (default: high)
--list-rulesPrint rules and default severities
--no-fixesHide fix suggestions in text output
--no-colorDisable colours

Full reference, config file format and API in the README.

Support this project

Support open-source security tools

I build free, open-source tools that help developers ship safer websites. Every coffee helps keep them maintained, documented and free for everyone.

Buy me a coffee (opens Stripe in a new tab)

Secure checkout by Stripe

Portrait of Louis Wright

About the author

Louis Wright

Cyber security researcher and software engineer based in the UK.

More tools by Louis Wright

58 tools

Sentinels security scanners & CI gates · 20