# 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` — `
` of ``, 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 ``),
`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 `
`; it would collide if inlined twice, which is why
it is NOT inlined.)
2. **Render**: the LAST `- ` of the footer's social `
`, on EVERY export build (site and hub):
`
`. The `` 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 ` 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:///kofi-symbol.svg` 200
and the footer's Ko-fi link on each site.