refactor(design): board JS uses relative paths; drop __GSTACK_SERVER_URL injection

Board JS in design/src/compare.ts now calls ./api/feedback and ./api/progress
(relative to location.pathname) and feature-detects server mode via
location.protocol instead of the injected window.__GSTACK_SERVER_URL global.
The injection in design/src/serve.ts is removed (dead code now that nothing
reads it). Tests updated to match the new contract: serve.test.ts asserts
the relative-path JS is present and the global is gone; feedback-roundtrip
asserts location.protocol detects HTTP mode.

Why: prep for the multi-board daemon (design/src/daemon.ts upcoming) where
the same generated HTML is served at /boards/<id>/ instead of /. Relative
paths resolve against location.pathname in both cases, so one HTML, two
hosts. The injection was the only thing tying board JS to a specific
serving path; removing it unblocks the daemon work without forking the
generator.

file:// fallback preserved via the location.protocol feature-detect — board
opened directly as a file still falls through to the DOM-only success path.

The 6 feedback-roundtrip browser tests continue to fail with
session.clearLoadedHtml undefined; that failure pre-exists this branch
(verified against HEAD with these edits stashed) and lives in
browse/src/write-commands.ts, not in the design code path. Tracking
separately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-05-25 14:31:22 -07:00
co-authored by Claude Opus 4.7
parent 64f9aafa1e
commit f55595d594
4 changed files with 52 additions and 38 deletions
+11 -8
View File
@@ -65,11 +65,9 @@ describe('Serve HTTP endpoints', () => {
const url = new URL(req.url);
if (req.method === 'GET' && url.pathname === '/') {
const injected = htmlContent.replace(
'</head>',
`<script>window.__GSTACK_SERVER_URL = '${url.origin}';</script>\n</head>`
);
return new Response(injected, {
// Board JS uses relative URLs (./api/feedback, ./api/progress)
// and a location.protocol feature-detect; no injection needed.
return new Response(htmlContent, {
headers: { 'Content-Type': 'text/html; charset=utf-8' },
});
}
@@ -118,12 +116,17 @@ describe('Serve HTTP endpoints', () => {
server.stop();
});
test('GET / serves HTML with injected __GSTACK_SERVER_URL', async () => {
test('GET / serves HTML with relative-path board JS (no injection)', async () => {
const res = await fetch(baseUrl);
expect(res.status).toBe(200);
const html = await res.text();
expect(html).toContain('__GSTACK_SERVER_URL');
expect(html).toContain(baseUrl);
// No more per-origin URL injection; board JS uses relative paths.
expect(html).not.toContain('__GSTACK_SERVER_URL');
expect(html).not.toContain(baseUrl);
// Board JS calls relative endpoints so the same HTML works at / and at
// /boards/<id>/ (daemon mode).
expect(html).toContain("fetch('./api/feedback'");
expect(html).toContain("fetch('./api/progress')");
expect(html).toContain('Design Exploration');
});