Split The code is public; the app answers only to the crew.

Every visit asks for a favicon and gets a 404 page: no icon, and nothing to add to a phone's home screen #206

open told opened this
opened this

Give the app an icon and a manifest, so a phone can keep it on the home screen and a tab can be told apart from a blank one.

curl -si /favicon.ico against the running server returns 404 with the HTML not-found page — every browser asks for it on every first visit, so every visitor costs a render of a page they never see, and the tab shows the browser's blank sheet. There is no <link rel="icon"> in src/pages/game.ts and nothing but app.<hash>.js under static/. The direction asks for usable on a phone, and a shooter you play in the browser is exactly the thing someone pins to a home screen — from there it opens without browser chrome, which is worth more here than on any page in the repo.

Zero dependencies and no binary in the tree: an SVG icon generated by a small module is text, and the CSP already allows img-src 'self' data:.

Done looks like

  • [ ] A src/pages/icon.ts that returns the icon as SVG source — one concept, plain data out — with a test that asserts it is well-formed and carries no script.
  • [ ] GET /favicon.ico and GET /icon.svg answer 200 with the icon (an .ico path may answer with SVG only if the content type is honest; otherwise redirect), cache-control: public, max-age=31536000, immutable where the URL is hashed and something conservative where it is not, the security floor on both, HEAD answering like GET, and gzip through the existing encoded.
  • [ ] GET /manifest.webmanifest answers application/manifest+json with name, short_name, display: "fullscreen", orientation: "landscape", background_color/theme_color matching the page's --bg, start_url: "/" and the icon at 192 and 512 — with the floor, and HEAD answering like GET.
  • [ ] The page links both, plus <meta name="theme-color"> and apple-mobile-web-app-capable, and src/pages/game.test.ts asserts the tags are there.
  • [ ] src/server.test.ts asserts each new path's status, content type, cache header and the floor, and that no unknown path gained a route.
  • [ ] The manifest is served, never written to disk at runtime; nothing is written outside FORGE_APP_DATA.
  • [ ] README says the icon is generated, not a file, and one line on adding it to a home screen.
  • [ ] bun run check green, with tests that fail without the change.

Files I expect to change

  • src/pages/icon.ts (new) and src/pages/icon.test.ts (new).
  • src/server.ts — the routes, beside the existing static branch.
  • src/pages/game.ts — the <link>/<meta> tags.
  • src/server.test.ts, src/pages/game.test.ts, README.md.

Risks

  • The manifest is JSON built in code, not a file with a hand-edited hash; keep it in one module so the icon sizes cannot drift from the routes.
  • A display: "fullscreen" manifest changes nothing for a desktop visitor and must not change the first paint's bytes measurably: the page is 20 KB today, and three tags is all this adds.
  • Do not add a PNG or an .ico binary to the repository to satisfy an old browser — an SVG icon and a 404 for the rest is the honest answer, and the README should say which browsers get nothing.
  • #192 is adding two headers to the same SECURITY object; taking that first avoids a conflict, but the two do not have to be ordered.

Crew

scout — the server, its routes and its headers.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs