Skip to content

Set an absolute baseURL per netlify context for the sitemap (#1082)#1084

Open
dduugg wants to merge 1 commit into
shift-org:mainfrom
dduugg:issue-1082-sitemap-baseurl
Open

Set an absolute baseURL per netlify context for the sitemap (#1082)#1084
dduugg wants to merge 1 commit into
shift-org:mainfrom
dduugg:issue-1082-sitemap-baseurl

Conversation

@dduugg

@dduugg dduugg commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Fixes #1082.

https://www.shift2bikes.org/sitemap.xml builds and serves (200), but every entry is a relative path:

<loc>/pages/bike-summer/</loc>

The sitemap protocol requires <loc> to be a fully qualified URL, so these entries are almost certainly being discarded by search engines. Hugo builds <loc> from each page's .Permalink, which derives from baseURL, and baseURL = "/".

Why not just change baseURL in hugo.toml

baseURL = "/" is load-bearing. The theme resolves assets and the calendar's own API calls through absURL:

site/themes/s2b_hugo_theme/layouts/partials/cal/scripts.html:140:  url: '{{ absURL "api/events.php" }}',
site/themes/s2b_hugo_theme/layouts/partials/head-content.html:29:  <link rel="icon" href="{{ absURL "favicon.ico" }}">

With a relative base these resolve same-origin, which is what lets one build work unchanged on localhost, on deploy previews, and in production. Hardcoding the production URL into hugo.toml would make previews and local dev load assets from, and fetch event data from, www.shift2bikes.org.

The change

baseURL stays / in hugo.toml. netlify.toml overrides it per build context via HUGO_BASEURL (hugo maps that env var onto baseURL):

Context HUGO_BASEURL Result
production https://www.shift2bikes.org (canonical host, matching the domain redirects at the top of netlify.toml) sitemap points at the site we actually serve
deploy-preview / branch-deploy $DEPLOY_PRIME_URL (that build's own origin) assets and the /api proxy resolve against the preview, not production
local dev / any uncased build unset, so / from hugo.toml relative, works on any host

It is set inline in each command rather than in a [context.*.environment] table, because netlify only expands env vars like $DEPLOY_PRIME_URL inside command. A [context.*.environment] value is a literal string, so HUGO_BASEURL = "$DEPLOY_PRIME_URL" there would hand hugo the literal text $DEPLOY_PRIME_URL.

Verification

Built with hugo 0.152.2, reproducing each context's environment:

production (HUGO_BASEURL literal):
  <loc>https://www.shift2bikes.org/archive/get-lit/</loc>

deploy-preview (DEPLOY_PRIME_URL expanded by the shell, as netlify does):
  <loc>https://deploy-preview-1082--shift.netlify.app/archive/get-lit/</loc>
  home page's calendar call: url: 'https://deploy-preview-1082--shift.netlify.app/api/events.php'

local dev (no env, baseURL stays "/"):
  <loc>/archive/get-lit/</loc>

So the sitemap becomes absolute in the two deployed contexts, previews stay self-contained (the /api/* proxy handles the preview-origin API calls), and local dev is unchanged. netlify.toml was confirmed to still parse as valid TOML.

Notes

…g#1082)

The sitemap advertised at /sitemap.xml lists relative <loc> paths,
because baseURL is "/". The sitemap protocol requires fully
qualified urls, so search engines reject these entries.

baseURL stays "/" in hugo.toml, since the theme resolves assets and
the calendar's /api calls through absURL, and a relative base is what
lets the same build work on localhost, deploy previews, and prod.
Instead, override it per netlify context:

  production           -> https://www.shift2bikes.org ( canonical host )
  deploy/branch deploy -> $DEPLOY_PRIME_URL ( that build's own origin )

Set inline in `command`, since netlify only expands env vars like
$DEPLOY_PRIME_URL there, not in a [context.*.environment] table. On
previews the assets and /api proxy then resolve against the preview
rather than production.
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.

sitemap.xml emits relative <loc> values, so search engines reject it

1 participant