diff --git a/main.js b/main.js
index 19e6172a..ee95726c 100644
--- a/main.js
+++ b/main.js
@@ -2746,8 +2746,17 @@ async function serveBns(request) {
? up.contentType : guessType(reqPath === "/" ? "index.html" : reqPath);
let body = up.buffer;
if (ct.includes("text/html")) {
- // Strip the gateway's path-form so assets
- // resolve against the bns:// origin, not back through the relay.
+ // Translate the gateway's path-form to
+ // a bns:///… base so assets resolve against the bns:// origin.
+ // Previously we stripped the tag entirely, which worked when the
+ // gateway's base matched the request path, but broke on any SPA
+ // fallback: hitting bns://pithos.sia/HouseMusic/house-music served
+ // the site's root index with , and
+ // stripping that let the browser use bns://pithos.sia/HouseMusic/
+ // as the implicit base — so `assets/logo.svg` on the root page
+ // resolved one folder too deep and 404d. Keeping the gateway's
+ // base (translated to bns://) honours the gateway's SPA fix for
+ // Theseus too.
// Also strip the gateway's relay chrome (banner + chip + their boot
// script) in case an older gateway, a misconfigured deployment, or
// a cached edge missed the x-bns-policy signal and injected it
@@ -2757,7 +2766,7 @@ async function serveBns(request) {
// for exactly this kind of surgical removal.
body = Buffer.from(
body.toString("utf8")
- .replace(//i, "")
+ .replace(//i, (_, tail) => ``)
.replace(/[\s\S]*?/gi, "")
.replace(/[\s\S]*?/gi, "")
.replace(/[\s\S]*?/gi, ""),