From 20f3171947cb6c966d3bf8fa31a36e6e74ca53da Mon Sep 17 00:00:00 2001
From: Mao Nakamoto <41178744+maonakamoto@users.noreply.github.com>
Date: Mon, 31 Aug 2026 09:58:24 +0200
Subject: [PATCH] refactor(nav): the footer promised what only the nav could
keep
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
NAV_ITEMS says "only routes that actually exist belong here — a nav link to a
404 is a lie". The footer carried the same sentence about itself, and then
restated six of those routes as its own literal s. Nothing tied the two
lists together, so removing a page from the nav left the footer pointing at it
with no way to notice. Both files promised the same thing and only one of them
could keep it.
FOOTER_SECTIONS now names hrefs instead of repeating them, and the footer
renders from that. A rename in NAV_ITEMS reaches the footer for free.
Where the footer deliberately says something shorter than the nav — "Voting",
not "How voting works"; "API", not "Integration" — that is now an explicit
`label` override rather than an independently typed second copy. The
difference is recorded as a choice instead of looking like drift.
The sibling pillars and the source-code link already came from their own SSOTs
(ECOSYSTEM_PILLARS, SOLON_GITHUB_URL) and still do.
Six tests, mutation-proven: deleting /security from NAV_ITEMS alone — exactly
the regression this prevents — fails the suite and names the orphaned footer
link. Verify green (lint, typecheck, design:check, 82 tests).
Found by a fleet-wide navigation audit across 20 repos.
Co-Authored-By: Claude Opus 5 (1M context)
Claude-Session: https://claude.ai/code/session_01XeELB8b3N4JrT2asYL9WvE
---
src/components/ui/footer.tsx | 131 +++++++++-----------------
src/lib/__tests__/site-config.test.ts | 79 ++++++++++++++++
src/lib/site-config.ts | 62 ++++++++++++
3 files changed, 185 insertions(+), 87 deletions(-)
create mode 100644 src/lib/__tests__/site-config.test.ts
diff --git a/src/components/ui/footer.tsx b/src/components/ui/footer.tsx
index e8f0184..0698bda 100644
--- a/src/components/ui/footer.tsx
+++ b/src/components/ui/footer.tsx
@@ -1,7 +1,10 @@
import Link from "next/link";
import { ECOSYSTEM_PILLARS, SOLON_GITHUB_URL } from "@/lib/config/ecosystem";
+import { FOOTER_SECTIONS, footerLinkLabel } from "@/lib/site-config";
// Only routes that actually exist belong here — a footer link to a 404 is a lie.
+// That is now structural rather than a promise: every destination below comes
+// from NAV_ITEMS, so a page removed from the nav cannot survive in the footer.
export default function Footer() {
const siblings = ECOSYSTEM_PILLARS.filter((p) => p.key !== "solon");
@@ -9,93 +12,47 @@ export default function Footer() {