Skip to content

Generate trailing-slash URLs so canonical and sitemap name the served page - #1853

Merged
mrbobbytables merged 1 commit into
cncf:mainfrom
mrbobbytables:fix/trailing-slash-canonical
Oct 23, 2026
Merged

mrbobbytables merged 1 commit into
cncf:mainfrom
mrbobbytables:fix/trailing-slash-canonical

Conversation

@mrbobbytables

Copy link
Copy Markdown
Member

Fixes #1852.

Remit: user-observable defect. Every page's rel="canonical" and 39 of 44 sitemap.xml entries name a URL that only ever 301s.

What was wrong

Netlify serves each page under its trailing-slash URL and redirects the bare form, but trailingSlash was unset, so Docusaurus generated the bare form everywhere. Verified on production today:

$ curl -sI https://endusers.cncf.io/resources/metrics | grep -iE "^HTTP|^location"
HTTP/2 301
location: /resources/metrics/
$ curl -sL https://endusers.cncf.io/resources/metrics/ | grep -o '<link[^>]*canonical[^>]*>'
<link data-rh=true rel=canonical href=https://endusers.cncf.io/resources/metrics />

Sitemap: 39 entries without a slash (all 301), 5 with (200).

Change

  • docusaurus.config.js: trailingSlash: true. Built output now has 45 sitemap entries, all slashed; /resources/metrics/ declares itself canonical.
  • Sitemap ignorePatterns: /search became /search/**. The plugin matches patterns against the route after the slash is applied (@docusaurus/utils createMatcher over route.path), so the bare pattern let /search/ leak into the sitemap on the first build. tests/sitemap-exclusions.test.mjs now models routes in the served shape and asserts the bare pattern no longer matches.
  • tests/site-config.test.mjs: pins trailingSlash === true with the reason.
  • tests/e2e/*: exact-href selectors (href$="/blog/<slug>" etc.) gain the slash; search.spec.js visits /search/?q= because docusaurus serve drops the query on its slash redirect, where Netlify preserves it (curl -sI 'https://endusers.cncf.io/search?q=foo' -> location: /search/?q=foo).

No redirects or file layout change: Docusaurus already emitted <route>/index.html for every page, so existing deep links keep resolving exactly as before; only the generated hrefs, canonical and sitemap change.

Validation

  • npm run build and npm run build:production succeed with onBrokenLinks: 'throw' intact.
  • npm run test:unit:coverage:check passes.
  • npm run test:e2e against the production build: 326 passed, 34 skipped (the fixture lane runs only under E2E_COVERAGE=1; its selectors were updated the same way).
  • duplication at ceiling, eslint, prettier, knip, cspell clean.

… page

Netlify serves every page under its trailing-slash URL and 301s the bare
form, but the site was generated without trailingSlash set, so every
page's rel=canonical and 39 of the 44 sitemap entries named a URL that
only ever answers with a redirect. Measured on production 2026-10-23:
/resources/metrics 301s to /resources/metrics/, and the page served
there declares /resources/metrics as canonical.

Set trailingSlash: true in docusaurus.config.js. The sitemap now lists
45 URLs, all in the served form, and each page's canonical is the URL
that returns 200. The sitemap ignorePattern becomes /search/** because
the plugin matches patterns against the route after the slash is
applied, and the test model for that contract now mirrors the setting.
End-to-end selectors that pinned exact hrefs gain the slash, and the
search spec visits /search/?q= directly, since docusaurus serve drops
the query on its redirect where Netlify keeps it.

Remit: user-observable defect (every published canonical URL and most
sitemap entries redirect instead of resolving).

Fixes cncf#1852

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: mrbobbytables <mrbobbytables@users.noreply.github.com>
@netlify

netlify Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for endusers ready!

Name Link
🔨 Latest commit 4e3ae1b
🔍 Latest deploy log https://app.netlify.com/projects/endusers/deploys/6adbb6a90626f3d5e30bc1fb
😎 Deploy Preview https://deploy-preview-1853--endusers.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@mrbobbytables
mrbobbytables added this pull request to the merge queue Oct 23, 2026
Merged via the queue into cncf:main with commit 0c20b49 Oct 23, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[quality] Sitemap and rel=canonical publish non-trailing-slash URLs that always 301

1 participant