Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit d7fb767d7f16f9df8c78e31343b64ca4c47d4a3b
parent 52d80906421fb0134a39cf252b4e37b88b4b214a
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Fri, 25 Sep 2026 11:16:28 -0400

homepage: the hero links to the hub when homepage.json names it

"Search all archives" beside Download the source / Read the setup guide,
pointing at homepage.json's siteUrl (the hub's URL, the field the hub build
reads); absent on a build with no hub. marketing.spec checks that a present
link is absolute.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Diffstat:
Mhomepage/app/page.tsx | 14++++++++++++++
Mhomepage/e2e/marketing.spec.ts | 12++++++++++++
2 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/homepage/app/page.tsx b/homepage/app/page.tsx @@ -3,6 +3,7 @@ import { RecentAdditions } from "./components/RecentAdditions"; import { KpiHeader } from "./components/KpiHeader"; import { ArchiveCards } from "./components/ArchiveCards"; import { loadSummary } from "./lib/summary"; +import { currentHomepage } from "./lib/homepage"; // The project's front page. Its ONE job: make a visitor understand what // Archilyzer is and download it. @@ -38,6 +39,11 @@ export default function Home() { const hours = summary?.totals.hoursArchived ?? null; const gone = summary?.availability?.byState.deleted ?? 0; const counted = summary?.availability?.counted ?? 0; + // The operator's hub — one search over every published archive — is a + // separate app on its own Pages project; homepage.json's siteUrl is its + // address (the same field the hub's own build reads). No URL, no link: a + // source-only build has no hub to point at. + const hubUrl = currentHomepage().siteUrl ?? null; return ( <> @@ -87,6 +93,14 @@ export default function Home() { > Read the setup guide → </Link> + {hubUrl && ( + <a + href={hubUrl} + className="inline-flex items-center gap-2 border border-[var(--border-strong)] px-6 py-3 font-mono text-xs uppercase tracking-[0.16em] text-[var(--foreground)] rounded-[var(--radius)] hover:border-[var(--brand)] hover:text-[var(--brand)] transition-colors" + > + Search all archives + </a> + )} </div> {/* The rail: real acquisitions, real states. The signature object. */} diff --git a/homepage/e2e/marketing.spec.ts b/homepage/e2e/marketing.spec.ts @@ -22,6 +22,18 @@ test("says what it is and offers the source", async ({ page }) => { ).toHaveAttribute("href", "/docs/install/"); }); +// The hub is a separate app on its own Pages project, linked from the hero +// when homepage.json names its URL. Data-dependent like the rail below, so the +// assertion is conditional the same way: absent is a legal state (a +// source-only build has no hub), but PRESENT means an absolute link off-site — +// never a relative path into this site, which has no search. +test("the hub link, when there is one, leaves for the hub", async ({ page }) => { + const hub = page.getByRole("link", { name: /search all archives/i }); + if ((await hub.count()) === 0) return; + await expect(hub).toHaveCount(1); + await expect(hub).toHaveAttribute("href", /^https?:\/\/[^/]/); +}); + test("the trust block states what it isn't", async ({ page }) => { // The cheapest, highest-value block on the page — every claim in it is // simply true, and each one pre-empts a wrong assumption.