fix(studio): serve favicon.svg from embedded preview server#806
Conversation
The /favicon.svg request was falling through to the SPA catch-all, which returns index.html. The browser received HTML instead of an SVG and silently discarded it, leaving the tab with no icon. Added an explicit route for /favicon.svg alongside the existing /assets/* and /icons/* static routes. Closes #804
jrusso1020
left a comment
There was a problem hiding this comment.
APPROVE at 022c487c. Smallest possible fix for the reported issue (#804) — one explicit route alongside the existing /assets/* and /icons/* patterns. Diagnosis is precise: the SPA catch-all was returning index.html for /favicon.svg, so the browser got HTML where it expected SVG and silently dropped it.
Rule 2 — other root-level static files to consider
The same fall-through-to-SPA-catch-all pattern likely affects any other root-level static file the studio expects:
/robots.txt/manifest.json/favicon.ico(browser-default fallback when/favicon.svgisn't loaded — though this PR fixes the SVG path so the .ico fallback is moot)/apple-touch-icon.png(iOS Safari)- Any future PWA-style assets
Worth a quick ls dist/studio/ (or whatever the public-asset emit target is) to see what else lives at the root. If none of those exist today, this PR is complete; if any do, the same SPA-catch-all trap will silently swallow them.
For the favicon case specifically: most browsers will retry /favicon.ico after /favicon.svg fails (or pre-fetch both in parallel depending on <link> tag presence). If dist/studio/ contains a favicon.ico too, you might want to add /favicon.ico to the route list as well for symmetry — same one-line addition.
Non-blocking. The reported user impact (tab icon missing) is fixed by this one line.
CI
Essentially all green. Lint, Build, Test, Typecheck, Test: runtime contract, Format, File size check, regression, player-perf, Preview parity (in_progress but trending green), CodeQL (all 3 langs), Analyze ✓. The only in_progress checks at review time are the heavier windows-latest jobs and CLI smoke. No reds.
Verdict
APPROVE. Smallest possible PR for a real cosmetic user-visible bug. Ship 🚀
— Rames Jusso (pr-review)
vanceingalls
left a comment
There was a problem hiding this comment.
APPROVE at 022c487c. Additive review — @jrusso1020 (Rames) already covered the minimal-fix framing and the Rule 2 question about other root-level static files that could share the SPA-catch-all trap.
Strengths
packages/cli/src/server/studioServer.ts:423— single-line addition slotted in next to the existing/assets/*and/icons/*routes. Diagnosis in the PR body is precise: the SPA catch-all returnsindex.htmlfor/favicon.svg, browser drops the HTML-typed SVG, tab icon goes missing.- Path matches the consumer exactly:
packages/studio/index.htmldeclares<link rel="icon" type="image/svg+xml" href="/favicon.svg" />— same absolute path the new route handles. No 404 risk introduced.
Rule 2 — verified (closing Rames's open question)
Rames flagged the sibling-site concern hypothetically (other root files like robots.txt, manifest.json, favicon.ico, apple-touch-icon.png could share the SPA-catch-all trap). Checked packages/studio/public/ against the contents API at HEAD: only favicon.svg and the icons/ directory exist. No other root-level static files are present, so this PR is genuinely complete — not just complete-conditional-on-no-other-files.
If/when any of those get added later, the same one-line route pattern will be needed and this PR's shape is the template.
CI
All required green at review time (Lint, Build, Test, Typecheck, Format, Test: runtime contract, CodeQL ×3, Preview parity, regression, player-perf, File size check, Smoke: global install). mergeStateStatus: BLOCKED because Render-on-windows + Tests-on-windows + CLI smoke (required) were still in-progress — not failing. No reds.
Notes
- nit:
serveStudioStaticFileresolves understudioDir(packages/cli/src/server/studioServer.ts:417) usingc.req.path.slice(1)— fine for/favicon.svg(single segment, no traversal), and theexistsSync/isFile()guard catches anything weird. No traversal concern for this PR.
Verdict: APPROVE
Reasoning: Smallest possible fix for a real user-visible bug; path matches the consumer in index.html; verified no sibling root files share the same trap; CI clean.
— Vai
Closes #804
Problem
/favicon.svgwas not listed as a static route in the embedded preview server (studioServer.ts). Requests for it fell through to the SPA catch-all, which returnsindex.html. The browser received HTML where it expected an SVG and silently ignored it, leaving the tab with no icon.The file itself (
public/favicon.svg→dist/studio/favicon.svg) was already correct and present — it just wasn't being served.Fix
One-line addition: explicit route for
/favicon.svgalongside the existing/assets/*and/icons/*static routes.