commit 82fafda9c0ea62e01d81a0c8c49b007dd000c05a
parent a55bca89082ee5a2dfc009723306f83afcb4d6a3
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Sat, 26 Sep 2026 18:22:25 -0400
export: the Ko-fi mark, last in every footer's social row
The operator's 2026-09-26 ruling replaces "hub and homepage only": every
export build, each site and the hub, ends its footer's social row with
Ko-fi's official symbol (/kofi-symbol.svg, an <img>, alt ""), linking
KOFI_URL in a new tab with the accessible name "Ko-fi" and no copy. It
never goes through normalizeSocialSvg, which recolours the operator's icons
to currentColor; the mark keeps Ko-fi's own colours. The row now always
renders, because Ko-fi is always in it.
The hub's "Ko-fi" text link is removed: one Ko-fi per footer, the mark.
KOFI_URL's comment in common/lib/project.ts now says where it renders.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
2 files changed, 36 insertions(+), 19 deletions(-)
diff --git a/common/lib/project.ts b/common/lib/project.ts
@@ -32,10 +32,11 @@ export const PROJECT_WORDMARK_LEAD = "Archi";
// valid. Only then is changing this string a cosmetic follow-up.
export const PROJECT_URL = "https://archilyzer.pages.dev";
-// The project's Ko-fi page. Rendered as a bare link (visible text "Ko-fi", no
-// copy around it) on the project's OWN surfaces only: the homepage footer and
-// the hub's footer. A site build never shows it — an archive someone else
-// hosts must not carry this project's tip jar.
+// The project's Ko-fi page. No copy around it, anywhere. On every export build
+// (each site and the hub) it is Ko-fi's official symbol, the last item of the
+// footer's social row, accessible name "Ko-fi" (the operator's 2026-09-26
+// ruling, which replaced "hub and homepage only"). The homepage footer still
+// carries it as a bare text link, "Ko-fi".
export const KOFI_URL = "https://ko-fi.com/archilyzer";
export const PROJECT_TAGLINE = "Self-hosted, searchable video-transcript archives.";
diff --git a/export/app/components/Footer.tsx b/export/app/components/Footer.tsx
@@ -95,20 +95,16 @@ export default function Footer() {
</a>
</span>
</span>
- {/* Ko-fi: a bare link, no copy — and on the HUB only. The hub is the
- project's own deployment; a site build is an archive whoever runs
- it hosts, and must not carry this project's tip jar. */}
- {instanceMode() === "hub" && (
- <a
- href={KOFI_URL}
- target="_blank"
- rel="noopener noreferrer"
- className="text-xs underline underline-offset-2 hover:text-foreground transition-colors"
- >
- Ko-fi
- </a>
- )}
- {socialLinks.length > 0 && (
+ {/* The social row: the operator's links (admin data, recoloured to
+ currentColor by normalizeSocialSvg), then Ko-fi, always LAST.
+ Ko-fi is on every build — site and hub — by the operator's
+ 2026-09-26 ruling. It is the project's tip jar, not an operator
+ link, so it never goes through normalizeSocialSvg: it is Ko-fi's
+ official symbol, vendored byte-for-byte as public/kofi-symbol.svg
+ and shown in Ko-fi's own colours. It is an <img>, not inlined,
+ because the file carries a <mask id> that would collide if the
+ markup were ever inlined twice. No copy: the accessible name is
+ exactly "Ko-fi" and nothing is visible but the mark. */}
<ul className="flex items-center gap-3 list-none">
{socialLinks.map((link, i) => (
<li key={`${link.url}-${i}`}>
@@ -123,8 +119,28 @@ export default function Footer() {
/>
</li>
))}
+ <li>
+ <a
+ href={KOFI_URL}
+ title="Ko-fi"
+ aria-label="Ko-fi"
+ target="_blank"
+ rel="noopener noreferrer"
+ className="inline-block w-5 h-5 hover:opacity-80 transition-opacity"
+ >
+ {/* A static file served as-is (images are unoptimized in this
+ static export, and next/image adds nothing for an SVG). */}
+ {/* eslint-disable-next-line @next/next/no-img-element */}
+ <img
+ src="/kofi-symbol.svg"
+ alt=""
+ width={20}
+ height={20}
+ className="block w-full h-full object-contain"
+ />
+ </a>
+ </li>
</ul>
- )}
</div>
</div>
{related.length > 0 && (