From bb012eb22623b2d652b70754d5dc36ac0ce752c4 Mon Sep 17 00:00:00 2001 From: lucasrodes Date: Sun, 7 Jun 2026 12:01:01 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=F0=9F=A4=96=20Redirect=20bare=20su?= =?UTF-8?q?bproject=20roots=20to=20their=20trailing-slash=20form?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /projects/etl (no slash) fell through to the umbrella assets and 404ed. Also un-breaks legacy /projects/etl/en/latest links, whose /en/latest strip lands on the bare root. Co-Authored-By: Claude Opus 4.8 (1M context) --- _worker.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/_worker.js b/_worker.js index 9e337c8..e1efd6c 100644 --- a/_worker.js +++ b/_worker.js @@ -49,6 +49,14 @@ export default { } for (const [prefix, origin] of Object.entries(SUBPROJECTS)) { + // Bare project root without trailing slash (/projects/etl) — redirect + // to the canonical slash form, otherwise it falls through to the + // umbrella's static assets and 404s. Deeper slash-less paths don't + // need this: the proxied Pages project 308s them itself. + if (url.pathname === prefix.slice(0, -1)) { + url.pathname = prefix; + return Response.redirect(url.toString(), 301); + } if (url.pathname.startsWith(prefix)) { const target = `${origin}${url.pathname}${url.search}`; return fetch(target, request);