Skip to content

Respect the site's trailingSlash config when building URLs#2

Open
bimsonz wants to merge 2 commits into
jdevalk:mainfrom
bimsonz:feat/config-driven-trailing-slash
Open

Respect the site's trailingSlash config when building URLs#2
bimsonz wants to merge 2 commits into
jdevalk:mainfrom
bimsonz:feat/config-driven-trailing-slash

Conversation

@bimsonz

@bimsonz bimsonz commented Jul 18, 2026

Copy link
Copy Markdown

Problem

buildPageUrl and generateCanonical hardcode a trailing slash, so every URL the plugin emits — the schema/map sitemap feed, llms.txt, canonical, hreflang, and IndexNow — ends in /. That matches Astro's default (trailingSlash: 'ignore'/'always'), but not a site configured with trailingSlash: 'never'. It especially affects headless consumers, whose front-end serves bare URLs like /blog/post — the plugin then advertises /blog/post/, which the site doesn't serve.

Change

  • Add a shared applyTrailingSlash(path, mode) helper and thread a trailingSlash policy through every URL/canonical call site: urls.ts, canonical.ts, schema/endpoints.ts, hreflang.ts, llms.ts, indexnow.ts, metadata.ts.
  • The policy comes from ctx.site.trailingSlash — Astro's trailingSlash, exposed by emdash in the companion PR below.
  • Backward-compatible: the default, 'always', and 'ignore' keep the trailing slash; only 'never' strips it. Existing Astro-served sites are unchanged.
  • Tests: applyTrailingSlash + buildPageUrl under each policy, plus schema/map (listSchemaEntries) asserting bare URLs when trailingSlash: 'never'.

Dependency

Requires emdash exposing ctx.site.trailingSlash — companion PR: emdash-cms/emdash#2122. Until it lands, ctx.site.trailingSlash is undefined at runtime and behaviour is unchanged, so either merge order is safe.

bimsonz added 2 commits July 18, 2026 16:37
buildPageUrl and generateCanonical hardcoded a trailing slash, so every URL the
plugin emits (sitemap schema/map, llms.txt, canonical, hreflang, IndexNow) ended
in a slash. That matches Astro's default, but not a site configured with
trailingSlash: 'never' — notably headless consumers whose front-end serves bare
URLs, where the sitemap/canonical then advertise URLs that don't match the site.

Add a shared applyTrailingSlash(path, mode) that honours the site's policy, taken
from ctx.site.trailingSlash (Astro's trailingSlash, newly exposed by emdash), and
thread it through every URL/canonical call site. Backward-compatible: the default,
'always' and 'ignore' keep the trailing slash; only 'never' strips it.

Depends on emdash exposing ctx.site.trailingSlash.
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.

1 participant