From 23badb03aeee0984f598cf09b8ce4a1a625cac75 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Wed, 10 Jun 2026 19:19:06 -0400 Subject: [PATCH] Add an SVG favicon (no more /favicon.ico 404) Link a small inline SVG (site/favicon.svg, a red tile with a white "V") from both index.html and board.html via a root-absolute href, so it resolves from "/" and from "/board/" under Vercel cleanUrls. With an icon link present, browsers stop auto-requesting (and 404ing on) /favicon.ico. No binary asset and no external dependency, consistent with the self-contained client. e2e asserts both pages declare the favicon and that /favicon.svg is served as valid SVG. Closes the last code-finishable item in the roadmap's smaller list. Co-Authored-By: Claude Opus 4.8 --- docs/nostr-static-client-spec.md | 1 + docs/roadmap.md | 3 ++- e2e/flyer.spec.js | 13 +++++++++++++ site/board.html | 1 + site/favicon.svg | 4 ++++ site/index.html | 1 + 6 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 site/favicon.svg diff --git a/docs/nostr-static-client-spec.md b/docs/nostr-static-client-spec.md index b935bf1..414ffd5 100644 --- a/docs/nostr-static-client-spec.md +++ b/docs/nostr-static-client-spec.md @@ -28,6 +28,7 @@ site/ locales.js board.html (bulletin board page) board.js + favicon.svg (inline SVG site icon) CNAME vendor/ nostr-tools/ diff --git a/docs/roadmap.md b/docs/roadmap.md index 5c03f73..81b70a7 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -240,7 +240,8 @@ should follow the board's trust model. varies with font availability and zoom; the [cheat sheet](flyer-field-limits.md) is explicitly approximate. Fine as-is; noted so it is not mistaken for a contract. -- **No favicon** — browsers log a harmless `404 /favicon.ico`. Cosmetic. +- **Favicon — ✅ done.** A small inline SVG (`site/favicon.svg`) is linked from + both pages, so browsers no longer request (and 404 on) `/favicon.ico`. - **WebKit/Safari coverage in CI** needs `libavif16` on Linux runners (`sudo npx playwright install-deps`); headless WebKit is also not a perfect stand-in for real Safari/iOS print + clipboard behavior, so a real-device diff --git a/e2e/flyer.spec.js b/e2e/flyer.spec.js index f41a64f..2e1f41c 100644 --- a/e2e/flyer.spec.js +++ b/e2e/flyer.spec.js @@ -104,6 +104,19 @@ test.describe("VoxVera static client", () => { expect(errors, errors.join("\n")).toHaveLength(0); }); + test("both pages declare an SVG favicon (no /favicon.ico 404)", async ({ page }) => { + for (const path of ["/", "/board.html"]) { + await page.goto(path); + const href = await page.locator('link[rel~="icon"]').first().getAttribute("href"); + expect(href, `${path} should link a favicon`).toBe("/favicon.svg"); + } + // The asset itself is served and is valid SVG. + const res = await page.request.get("/favicon.svg"); + expect(res.status()).toBe(200); + expect(res.headers()["content-type"] || "").toContain("svg"); + expect(await res.text()).toContain(" { await page.goto("/"); await page.emulateMedia({ media: "print" }); diff --git a/site/board.html b/site/board.html index 5a64f09..1fe6604 100644 --- a/site/board.html +++ b/site/board.html @@ -7,6 +7,7 @@ + diff --git a/site/favicon.svg b/site/favicon.svg new file mode 100644 index 0000000..9370607 --- /dev/null +++ b/site/favicon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/site/index.html b/site/index.html index 23b2780..cdf6c12 100644 --- a/site/index.html +++ b/site/index.html @@ -4,6 +4,7 @@ VoxVera Nostr Client +