You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docusaurus.config.js:26-28 documents SITE_URL/BASE_URL overrides as the
supported way to deploy a non-root preview:
Override with SITE_URL/BASE_URL for non-production deployments such as GitHub
Pages previews (e.g. SITE_URL=https://castrojo.github.io BASE_URL=/endusers/).
Five paths 404 when you do that. Verified by running that exact build, not
by inference:
The manifest link 404s, so the site is not installable at all; the
apple-touch-icon 404s, so iOS home-screen saves fall back to a screenshot; and
even if the manifest were fetched, its start_url and all three icons would
404 too. On castrojo.github.io those root paths may belong to an unrelated
site, which is worse than a 404.
None of this is visible in the build output: it exits [SUCCESS], and onBrokenLinks: 'throw' governs page routes rather than static assets.
Recommendation
Two independent edits. Both are production changes, so this issue is filed
without a PR — the quality lane is test-only and does not open production PRs.
See the note at the bottom.
1. static/manifest.json — switch to manifest-relative paths
Per the appmanifest spec,
member URLs are resolved against the manifest's own URL. Making the paths
relative fixes every baseUrl at once with no build machinery. Exact
replacement for the four affected lines:
With the manifest served at /endusers/manifest.json, start_url: "."
resolves to /endusers/ and each icon to /endusers/favicons/.... At the
production root it is unchanged from today.
This is already compatible with the test landing in #335: that test asserts
manifest paths are same-origin (no scheme, no // prefix) and resolves
both relative and root-absolute forms under static/, so it stays green
before and after this edit. It was written that way deliberately so it
would not block this fix.
2. docusaurus.config.js — prefix the two headTags hrefs
const siteUrl = process.env.SITE_URL || 'https://endusers.cncf.io';
const baseUrl = process.env.BASE_URL || '/';
++// Docusaurus does not apply baseUrl to headTags attribute values; they are+// emitted verbatim. Prefix them here so non-root preview deploys resolve.+const withBaseUrl = (path) =>+ `${baseUrl.replace(/\/$/, '')}/${path.replace(/^\//, '')}`;
At the default baseUrl: '/' both expressions produce exactly the strings
that are there today, so production output is byte-identical and the build
stays green.
Impact: high — every non-root preview deploy ships a wholly broken manifest and icon set, silently, via the workflow the config itself documents
Effort: low — four one-line JSON edits plus a three-line config helper; production output at the default baseUrl is byte-identical
Note on why there is no PR
Both edits are production changes (static/manifest.json and docusaurus.config.js). The quality lane opens test-only PRs, so this needs a
human or a production-capable lane to land. The exact replacement text is
given above so applying it is mechanical.
Finding
docusaurus.config.js:26-28documentsSITE_URL/BASE_URLoverrides as thesupported way to deploy a non-root preview:
Five paths 404 when you do that. Verified by running that exact build, not
by inference:
at
00b44df, node v26.8.2, 2026-09-19.What the build emits
Config-derived references are
baseUrl-prefixed correctly:The two
headTagsentries are emitted verbatim, with no prefix:Docusaurus applies
baseUrltofaviconand to fields it owns, but it doesnot rewrite
headTagsattribute values — they are passed straight through.And
build/manifest.jsonis copied out ofstatic/byte-for-byte, becauseDocusaurus performs no transformation on
static/:Net effect on a preview deploy
/manifest.json/endusers/manifest.json/favicons/apple-touch-icon.png/endusers/favicons/...start_url: "/"/endusers/icons[].src/endusers/favicons/...The manifest link 404s, so the site is not installable at all; the
apple-touch-icon 404s, so iOS home-screen saves fall back to a screenshot; and
even if the manifest were fetched, its
start_urland all three icons would404 too. On
castrojo.github.iothose root paths may belong to an unrelatedsite, which is worse than a 404.
None of this is visible in the build output: it exits
[SUCCESS], andonBrokenLinks: 'throw'governs page routes rather than static assets.Recommendation
Two independent edits. Both are production changes, so this issue is filed
without a PR — the quality lane is test-only and does not open production PRs.
See the note at the bottom.
1.
static/manifest.json— switch to manifest-relative pathsPer the appmanifest spec,
member URLs are resolved against the manifest's own URL. Making the paths
relative fixes every
baseUrlat once with no build machinery. Exactreplacement for the four affected lines:
With the manifest served at
/endusers/manifest.json,start_url: "."resolves to
/endusers/and each icon to/endusers/favicons/.... At theproduction root it is unchanged from today.
This is already compatible with the test landing in #335: that test asserts
manifest paths are same-origin (no scheme, no
//prefix) and resolvesboth relative and root-absolute forms under
static/, so it stays greenbefore and after this edit. It was written that way deliberately so it
would not block this fix.
2.
docusaurus.config.js— prefix the twoheadTagshrefsattributes: { rel: 'manifest', - href: '/manifest.json', + href: withBaseUrl('/manifest.json'), },attributes: { rel: 'apple-touch-icon', sizes: '180x180', - href: '/favicons/apple-touch-icon.png', + href: withBaseUrl('/favicons/apple-touch-icon.png'), },At the default
baseUrl: '/'both expressions produce exactly the stringsthat are there today, so production output is byte-identical and the build
stays green.
Verifying a fix
Disjointness from open PRs
tests/site-config.test.mjs) asserts thatSITE_URL/BASE_URLflow into
url,baseUrland the JSON-LD logo URL, and that the twoheadTagshrefs exist on disk. It does not assert that those hrefs arebaseUrl-prefixed, and it changes no production code. The config edit abovedoes not conflict with it:
withBaseUrl('/manifest.json')still yields/manifest.jsonat the defaultbaseUrl, which is the value test: cover the docusaurus.config.js and sidebars.js navigation contract (tests/site-config.test.mjs) #275 checks.either path form, as described above.
/imgreferences,static/fonts/, andthe orphan direction over
static/images/social/faviconsrespectively.None reads
start_url,headTagshrefs, orbaseUrlbehaviour.Priority
baseUrlis byte-identicalNote on why there is no PR
Both edits are production changes (
static/manifest.jsonanddocusaurus.config.js). The quality lane opens test-only PRs, so this needs ahuman or a production-capable lane to land. The exact replacement text is
given above so applying it is mechanical.
Filed by quality agent (hold-gated mode)
— hive: agent=quality backend=copilot model=claude-opus-5