# Plan Status: **ready_for_implement** Goal: implement `ROADMAP.md` Priority 4 — make the page addable to an Android home screen as "Home Lanundry" with a cartoon washing-machine icon. T-001..T-005 are done and unchanged in behavior. ## Scope - New static assets (manifest and icons), embedded routes, three `` tags, tests, README. - Out of scope: service worker, offline mode, TLS, install prompt UI, any change to status rule, JSON contract, SSE, page layout or the ``. - Transport stays plain HTTP, so Chrome offers "Add to Home screen" (shortcut), not "Install app". This is accepted; document it. ## T-006 — Home screen icon and web manifest ### Design decisions - Assets live in `internal/web/static/` and are embedded with `go:embed` (an `embed.FS` over a fixed file list, or individual `[]byte` vars). No new dependencies. - Routes (all `GET`, exact paths, registered on the existing mux): - `/manifest.webmanifest` — `Content-Type: application/manifest+json` - `/icons/icon.svg` — `image/svg+xml` - `/icons/icon-192.png`, `/icons/icon-512.png`, `/icons/icon-maskable-512.png` — `image/png` - `/apple-touch-icon.png` (180x180) — `image/png` - Static assets use `Cache-Control: no-cache` (revalidate); the existing `no-store` on page/API stays. - Manifest content: `name` and `short_name` "Home Lanundry", `start_url` `/`, `scope` `/`, `display` `standalone`, `theme_color` and `background_color` `#ffffff`, `icons` = 192 and 512 (`purpose: any`) plus maskable 512 (`purpose: maskable`). - Icon art: flat cartoon front-loading washing machine — light-blue rounded-square background, white/pastel body, round porthole with blue water and a few bubbles, two or three control knobs and a small display on top. For the maskable variant, extend the background full-bleed and keep all artwork inside the central 80% safe zone. ### Files to change (tests first) 1. `internal/web/handler_test.go` (write first, confirm failing): - Table test for each new route: 200, expected `Content-Type`, non-empty body; PNG routes start with the PNG signature; `POST` returns 405. - Manifest test: decode JSON; assert `name`/`short_name` == "Home Lanundry", `display` == "standalone", `start_url` == "/", and that every `icons[].src` resolves to a route that returns 200 and has the declared `sizes` (decode PNG config) and `type`; one icon has `purpose` "maskable". - Extend `TestPageAndRouting` expected substrings with `rel="manifest"`, `name="theme-color"`, `rel="apple-touch-icon"`. 2. `internal/web/static/icon.svg` (new): source art, 512x512 viewBox. 3. `internal/web/static/icon-192.png`, `icon-512.png`, `icon-maskable-512.png`, `apple-touch-icon.png` (new): rendered from the SVG (full-bleed variant for maskable). Suggested tools: headless `google-chrome --screenshot` or Pillow; keep the generation script out of the repo, or add it as `internal/web/static/README`-free `scripts/` only if small — implementer's choice, but the committed SVG must be the source of truth and PNGs must visually match it. Visually check the result (view the PNGs, including a circle-crop check of the maskable one). 4. `internal/web/static/manifest.webmanifest` (new): content as above. 5. `internal/web/handler.go`: embed the new assets, register the routes with correct content types and cache header, update the package/handler doc comment to mention the manifest and icons. 6. `internal/web/static/index.html`: add to `<head>`: `<link rel="manifest" href="/manifest.webmanifest">`, `<meta name="theme-color" content="#ffffff">`, `<link rel="apple-touch-icon" href="/apple-touch-icon.png">`, `<link rel="icon" href="/icons/icon.svg" type="image/svg+xml">`. Do not change title, layout or script. 7. `Dockerfile`: no change expected (it already copies `internal`); verify the build still embeds the new files (`.dockerignore` must not exclude `*.png`/`*.svg`/`*.webmanifest` — check and fix if it does). 8. `README.md`: new "Add to Android home screen" subsection (before "Limitations"): open the page in Chrome on Android, menu → "Add to Home screen"/"Install app" if offered, name "Home Lanundry". State the plain-HTTP limitation: without HTTPS Chrome only offers a home-screen shortcut with the icon, not a full install, and there is no offline mode. Add the new routes (`/manifest.webmanifest`, `/icons/*`, `/apple-touch-icon.png`) to the endpoint documentation. Do not touch the AI Workflow section. 9. `ROADMAP.md`: already updated by the planner; no further edit. ### Validation - `go fmt ./...`, `go vet ./...`, `go test ./...` (plus `-race` on `./internal/web`). - Smoke: run the service, `curl -sI` each new route for status and content type; open the page in Chrome DevTools (Application → Manifest) at a 360px viewport and confirm no manifest or icon errors and a correct icon preview. - Docker build if available (confirm assets are embedded). ### Commit message `feat(web): add Home Lanundry home-screen icon and web manifest`