commit 797c449c2d534a2a780d93cd71fb1520ed28bae1
parent 88164c4d0cac5f5c5ce92db2db07884e5ce57307
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Sat, 26 Sep 2026 18:12:36 -0400
plans: slice O — the official Ko-fi symbol as the last item of every site's social row (supersedes the hub-only bare link; no copy, official colours, vendored asset)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
1 file changed, 84 insertions(+), 0 deletions(-)
diff --git a/plans/kofi-mark-on-sites.md b/plans/kofi-mark-on-sites.md
@@ -0,0 +1,84 @@
+# The Ko-fi mark in every site's social row (release 10 slice O)
+
+Written 2026-09-26 (evening). Operator, verbatim: "I downloaded ~/Downloads/kofi_brandasset.zip for
+the kofi logo official assets, use them to show kofi in the social section on all sites." This
+SUPERSEDES the 2026-09-25 ruling that a site build carries no Ko-fi link (the "bare link, no copy,
+hub only" rule in `export/app/components/Footer.tsx:98-110` and `export/e2e/site-branding.spec.ts:48-54`).
+"No copy" still holds: the mark is an icon with the accessible name "Ko-fi", nothing else.
+
+## Verified anchors (`main` a575685d)
+
+- `export/app/components/Footer.tsx`: social row `:111-127` — `<ul>` of `<a title aria-label target=_blank
+ rel=noopener noreferrer class="inline-block w-5 h-5 text-muted-foreground hover:text-brand … [&_svg]:w-full
+ [&_svg]:h-full" dangerouslySetInnerHTML={sizeSocialSvg(link.svg)}>`, rendered only when
+ `socialLinks.length > 0`. Ko-fi text link `:101-110`, `instanceMode() === "hub"` only, `KOFI_URL` from
+ `common/lib/project.ts:39` (`https://ko-fi.com/archilyzer`). The same Footer renders the hub build
+ (`instanceMode()` from `export/app/lib/mode`).
+- Social SVGs are admin data (`settings.json`/`site.json` `socialLinks`, `normalizeSocialSvg` forces
+ `fill="currentColor"`, `common/lib/settingsSchema.ts:1290-1330`). The Ko-fi mark is NOT admin data
+ and does NOT go through that path: it is the project's own asset, rendered in its official colours.
+- Tracked static assets precedent: `export/public/{file,globe,next,vercel,window}.svg` (`git ls-files`).
+ The rest of `export/public` is gitignored build output; a new tracked file beside those five is fine.
+- The assets, unpacked at `/home/user/.claude/jobs/c0baff27/tmp/kofi/kofi_brandasset/`: `kofi_symbol.svg`
+ (3,234 bytes, `viewBox="0 0 241 194"`, fills `#FF5A16`, `#202020`, white, one `<mask id="mask0_1_219">`),
+ `kofi_logo.svg` (wordmark, 11 KB), PNG badges. Use ONLY `kofi_symbol.svg`, byte-for-byte
+ (official colours, no recolouring — a brand asset is used as shipped).
+- Specs: `export/e2e/site-branding.spec.ts:25` "footer renders the site's social links" (fixture
+ `export/e2e/fixtures/sites/testsite/site.json:9` has `socialLinks`), `:48` "a site build carries no
+ Ko-fi link" (asserts `getByRole("link", {name: "Ko-fi"})` count 0 and no `a[href=KOFI_URL]`).
+ `homepage/e2e/marketing.spec.ts:129` "the footer carries a bare Ko-fi link" — homepage, untouched.
+
+## Decisions (made)
+
+1. **One asset, one place:** `export/public/kofi-symbol.svg` = the official `kofi_symbol.svg`, tracked,
+ unmodified. (The mask id is harmless in an `<img>`; it would collide if inlined twice, which is why
+ it is NOT inlined.)
+2. **Render**: the LAST `<li>` of the footer's social `<ul>`, on EVERY export build (site and hub):
+ `<a href={KOFI_URL} title="Ko-fi" aria-label="Ko-fi" target="_blank" rel="noopener noreferrer"
+ className="inline-block w-5 h-5 …"><img src="/kofi-symbol.svg" alt="" width={20} height={20}
+ className="w-full h-full" /></a>`. The `<ul>` now renders whenever there is at least one item, i.e.
+ always (Ko-fi is always present); the `socialLinks.length > 0` gate moves to the mapped items. The
+ accessible name is exactly "Ko-fi"; no visible text.
+3. **The hub's text link `:101-110` is removed** — one Ko-fi per footer, the mark. Its comment block is
+ replaced by one saying: the mark is on every build by the operator's 2026-09-26 ruling; it is the
+ project's tip jar, rendered in Ko-fi's official colours from the vendored official asset; it never
+ goes through `normalizeSocialSvg` (that path recolours admin icons to currentColor).
+4. **Homepage untouched** (its "Elsewhere" column keeps the bare text link; a follow-up may swap it for
+ the mark — not this slice). Sites with `pwa`/offline: the image is a static file under `/`, cached
+ like the icons; check `export/app/lib/offlineCache.ts` / the service-worker precache list and add
+ the path if static assets are enumerated there.
+5. **Dark theme**: the official mark has a `#202020` outline and a white cup; on a dark footer the
+ outline is invisible but the cup and the `#FF5A16` heart read. Accept as-is (official asset), take
+ one light and one dark screenshot for the record (the e2e harness's screenshot helper, or a
+ Playwright `page.screenshot` in a throwaway script — see `scripts/` for the shot precedent; use
+ `localhost`, not `127.0.0.1`).
+
+## Implementation (one Opus slice, branch `export/kofi-mark`, its own worktree)
+
+1. `git add` the asset at `export/public/kofi-symbol.svg` (copy from the unpacked zip; verify `sha256sum`
+ equals the zip's file). 2. Footer change per decisions 2–3. 3. `site-branding.spec.ts`: replace `:48-54`
+ with "every build carries the Ko-fi mark in the social row": the link with accessible name "Ko-fi"
+ exists once, `href` = `KOFI_URL`, opens in a new tab, contains an `img[src="/kofi-symbol.svg"]`, and
+ the image resolves (200) — and it is the LAST item of the social list; run the same assertion on the
+ hub build's footer in whichever hub spec renders the footer (grep `export/e2e` for the hub fixture),
+ and assert there is exactly ONE Ko-fi link on the hub (the text link is gone). 4. Docs: SITE.md/SETTINGS.md
+ are generated — nothing. One sentence in `export/README.md` (if it describes the footer) and in
+ `AGENTS.md` only if it mentions the Ko-fi rule (grep "Ko-fi"; today it does not — then nothing).
+ 5. Record: `### Slice O, as shipped — the Ko-fi mark on every site (2026-09-26)` in
+ `plans/release-10.md` before `## Rollout`, shape of Slice M/N; one `[Unreleased]` bullet in
+ `export/CHANGELOG.md` (the export's, not the editor's — check which changelog the sites' release
+ notes read; `editor/CHANGELOG.md` if the export has none).
+
+## Gates (worktree root)
+
+tsc; `pnpm --filter export exec next build` (NOT `run build`); export e2e, detached and queued, from the
+worktree root: `node scripts/worktree.mjs run -- pnpm --filter export run e2e site-branding.spec.ts <the
+hub spec(s) touched>` and then the FULL export suite (204 at integration) because the footer is on every
+page; `export/public` links from the primary per the rules (and note `kofi-symbol.svg` is a TRACKED file,
+not a link — do not symlink over it). Numbers tool: none.
+
+## Rollout (parent)
+
+Every site + the hub rebuild and redeploy: runbook step 5 (`pnpm ops build-deploy`) + step 6 hub — this
+slice joins release 10's rollout, FINAL moves. Live check: `curl -sI https://<site>/kofi-symbol.svg` 200
+and the footer's Ko-fi link on each site.