Archilyzer · Source

archilyzer

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

commit 15fa8be09a1fddd89e519e661d03dd360b40b32d
parent 1f285f61c0182a962eeaf92f4ea6f72dc327d306
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Wed, 30 Sep 2026 18:57:59 -0400

common: AI_DOC_URL — corpus.json's useWithAi and llms.txt's Use with AI name the homepage's AI and MCP doc; the sitemap drops /use-with-ai

A site (and the hub) has no /use-with-ai page any more. corpus.json keeps the useWithAi key with
the doc's URL; llms.txt's Ask AI section lists the site's /ask/ chat and the doc as two lines.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Diffstat:
Mcommon/bin/compose-site.ts | 2+-
Mcommon/lib/corpus.test.ts | 4++--
Mcommon/lib/corpus.ts | 22++++++++++++++--------
Mcommon/lib/project.ts | 6++++++
Dexport/app/use-with-ai/page.tsx | 139-------------------------------------------------------------------------------
5 files changed, 23 insertions(+), 150 deletions(-)

diff --git a/common/bin/compose-site.ts b/common/bin/compose-site.ts @@ -179,7 +179,7 @@ async function emitAiFiles(paths: ReturnType<typeof getPaths>): Promise<void> { // siteUrl; otherwise clear any stale copy from a previous build. const sitemapPath = path.join(paths.exportPublicDir, "sitemap.xml"); if (descriptor.siteUrl) { - const routes = ["/", "/use-with-ai", "/changelog"]; + const routes = ["/", "/changelog"]; if (hasArchives) routes.push("/downloads"); if (await exists(path.join(paths.exportPublicDir, DUPLICATES_FILENAME))) { routes.push("/duplicates"); diff --git a/common/lib/corpus.test.ts b/common/lib/corpus.test.ts @@ -207,8 +207,8 @@ test("renderRobotsTxt: sitemap line only with an absolute siteUrl", () => { test("renderSitemapXml: one loc per route", () => { const xml = renderSitemapXml({ siteUrl: "https://demo.example", - routes: ["/", "/use-with-ai"], + routes: ["/", "/changelog"], }); assert.match(xml, /<loc>https:\/\/demo\.example\/<\/loc>/); - assert.match(xml, /<loc>https:\/\/demo\.example\/use-with-ai<\/loc>/); + assert.match(xml, /<loc>https:\/\/demo\.example\/changelog<\/loc>/); }); diff --git a/common/lib/corpus.ts b/common/lib/corpus.ts @@ -1,5 +1,5 @@ import type { PublicSiteDescriptor } from "./siteDescriptor"; -import { PROJECT_GENERATOR } from "./project"; +import { AI_DOC_URL, PROJECT_GENERATOR } from "./project"; import { TAGS_FILENAME } from "./curatedTags"; import { CONTRACT, @@ -190,7 +190,9 @@ export type SiteCorpus = { tags?: { url: string; videoField: "curatedTags"; description: string }; // Present when this build ships bulk-download archives (whole-channel zips). bulkArchives?: { manifest: string; note: string }; - // Pointer to the human page and BYO-key chat. + // Pointer to the human page on using the archive with AI: the homepage's AI + // and MCP doc (AI_DOC_URL; the site's own /use-with-ai page until release + // 16). The BYO-key chat is the site's /ask/. useWithAi: string; }; @@ -270,7 +272,7 @@ export function buildSiteCorpus( totals: { channels: channels.length, videos }, channels, shardScheme: SHARD_SCHEME, - useWithAi: join(base, "/use-with-ai"), + useWithAi: AI_DOC_URL, }; // Only advertise the post scheme when this site actually ships posts, so a // pure-video site's corpus.json is unchanged apart from the spec bump. @@ -337,7 +339,7 @@ export function buildHubCorpus( "the whole federation, fetch each site's corpus.json and follow its " + "shardScheme; results can be merged client-side.", }, - useWithAi: join(opts.hubUrl, "/use-with-ai"), + useWithAi: AI_DOC_URL, }; } @@ -362,8 +364,11 @@ export function renderSiteLlmsTxt(corpus: SiteCorpus): string { out.push(""); out.push("## Ask AI"); out.push( - `- [Use with AI](${join(base, "/use-with-ai")}): in-browser chat (bring ` + - `your own API key) and MCP-server setup for Claude Code, Cursor, and other tools.`, + `- [Ask AI](${join(base, "/ask/")}): in-browser chat (bring your own API key).`, + ); + out.push( + `- [Use with AI](${AI_DOC_URL}): MCP-server setup for Claude Code, Cursor, ` + + `and other tools.`, ); out.push(""); out.push("## Corpus"); @@ -426,9 +431,10 @@ export function renderHubLlmsTxt(corpus: HubCorpus): string { out.push(""); out.push("## Ask AI"); out.push( - `- [Use with AI](${join(base, "/use-with-ai")}): ask across the whole ` + - `federation (bring your own API key) or wire up the MCP server.`, + `- [Ask AI](${join(base, "/ask/")}): ask across the whole federation ` + + `(bring your own API key).`, ); + out.push(`- [Use with AI](${AI_DOC_URL}): wire up the MCP server.`); out.push(""); out.push("## Federation"); out.push( diff --git a/common/lib/project.ts b/common/lib/project.ts @@ -44,6 +44,12 @@ export const PROJECT_TAGLINE = "Self-hosted, searchable video-transcript archive // homepage/app/source); this is its no-git alternative. export const PROJECT_DOWNLOADS_URL = `${PROJECT_URL}/downloads/`; +// The homepage's AI and MCP doc (homepage/content/docs/ai-and-mcp.md): the +// published contract, the MCP server and its setup, in one place. Every +// archive's "Use with AI" link goes here, in the same tab (release 16 slice +// DX), as do corpus.json's `useWithAi` and llms.txt's line of that name. +export const AI_DOC_URL = `${PROJECT_URL}/docs/ai-and-mcp/`; + // The `generator` string stamped into corpus.json and llms.txt, so anything // that reads an archive machine-side can find the software that built it. // Shape mirrors the HTML <meta name="generator"> convention. diff --git a/export/app/use-with-ai/page.tsx b/export/app/use-with-ai/page.tsx @@ -1,139 +0,0 @@ -import type { Metadata } from "next"; -import Link from "next/link"; -import { currentSite } from "../lib/site"; -import { instanceMode } from "../lib/mode"; -import { hasArchives } from "../lib/archives"; - -export const metadata: Metadata = { title: "Use with AI" }; - -// A human-facing hub for the "bring your own AI" surface: the in-browser chat, -// the machine-readable discovery files (llms.txt / corpus.json), and the MCP -// server. Hub-aware — on a hub build it frames everything as federation-wide. -// Fully static server component; no data fetching. -export default function UseWithAiPage() { - const site = currentSite(); - const isHub = instanceMode() === "hub"; - const base = site.siteUrl?.replace(/\/+$/, "") ?? ""; - const abs = (p: string) => (base ? `${base}${p}` : p); - const scope = isHub ? "the whole federation" : "this archive"; - const envVar = isHub ? "TRANSCRIPT_HUB_URL" : "TRANSCRIPT_SITE_URL"; - const target = base || (isHub ? "https://your-hub.example" : "https://your-site.example"); - - const mcpSnippet = `{ - "mcpServers": { - "${site.siteId}": { - "command": "pnpm", - "args": [ - "-C", "/path/to/yt-dlp-transcript-browser", - "--filter", "yt-dlp-transcript-mcp", - "exec", "tsx", "src/index.ts" - ], - "env": { "${envVar}": "${target}" } - } - } -}`; - - return ( - <div className="mx-auto flex max-w-3xl flex-col gap-10"> - <header className="flex flex-col gap-3 border-b border-border pb-6"> - <p className="font-mono text-xs uppercase tracking-[0.18em] text-brand"> - Use with AI · {site.headerTitle} - </p> - <h1 className="font-display text-3xl font-semibold leading-tight text-foreground"> - Ask an AI about {scope} - </h1> - <p className="max-w-prose text-sm text-muted-foreground"> - Nothing is hosted or paid for here — you bring your own AI. Chat in your - browser with your own API key, or point a tool like Claude Code at the - machine-readable index and let it browse the transcripts itself. - </p> - </header> - - <section className="flex flex-col gap-3"> - <h2 className="font-mono text-xs uppercase tracking-[0.14em] text-muted-foreground"> - Chat in your browser - </h2> - <div className="flex flex-col gap-3 rounded-lg border border-border bg-card/40 p-5"> - <p className="text-sm text-muted-foreground"> - A retrieval-augmented chat that searches the transcripts and answers - with citations. It runs entirely in your browser and calls your own - provider (Anthropic, OpenAI, or Google Gemini) with a key you supply — - the key stays on your device and requests go straight to the provider. - </p> - <div> - <Link - href="/ask" - className="inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-brand-strong" - > - Open the chat → - </Link> - </div> - </div> - </section> - - <section className="flex flex-col gap-3"> - <h2 className="font-mono text-xs uppercase tracking-[0.14em] text-muted-foreground"> - For coding agents &amp; LLM tools - </h2> - <div className="flex flex-col gap-3 rounded-lg border border-border bg-card/40 p-5"> - <p className="text-sm text-muted-foreground"> - {scope[0].toUpperCase() + scope.slice(1)} publishes a small, fixed set - of discovery files. An agent (e.g. Claude Code via <code className="font-mono">WebFetch</code>) - can read these and navigate every transcript without any per-video - pages — the paginated shard scheme is documented inline. - </p> - <ul className="flex flex-col gap-2 text-sm"> - <li> - <a href={abs("/llms.txt")} className="font-mono text-brand hover:underline"> - /llms.txt - </a> - <span className="text-muted-foreground"> — an LLM-readable overview and link map.</span> - </li> - <li> - <a href={abs("/corpus.json")} className="font-mono text-brand hover:underline"> - /corpus.json - </a> - <span className="text-muted-foreground"> - {" "}— the channel index and exactly how to fetch any transcript - from the JSON shards{isHub ? " across every member site" : ""}. - </span> - </li> - </ul> - </div> - </section> - - <section className="flex flex-col gap-3"> - <h2 className="font-mono text-xs uppercase tracking-[0.14em] text-muted-foreground"> - MCP server - </h2> - <div className="flex flex-col gap-3 rounded-lg border border-border bg-card/40 p-5"> - <p className="text-sm text-muted-foreground"> - The repo ships an MCP server that exposes {scope} to Claude Code, - Claude Desktop, Cursor, and other MCP clients as tools - (<code className="font-mono">search_transcripts</code>, - {" "}<code className="font-mono">get_transcript</code>, …). It reads the - same static shards — over HTTP or from a local build - {isHub ? ", federating every member site" : ""}. Add it to a client: - </p> - <pre className="overflow-x-auto rounded-md border border-border bg-muted/50 p-3 font-mono text-xs text-foreground"> - <code>{mcpSnippet}</code> - </pre> - <p className="text-xs text-muted-foreground/80"> - Setup details and the <code className="font-mono">claude mcp add</code>{" "} - command are in <code className="font-mono">mcp/README.md</code>. - </p> - </div> - </section> - - {hasArchives() && ( - <p className="text-xs text-muted-foreground/70"> - Ingesting in bulk instead? The{" "} - <a href="/downloads" className="text-brand hover:underline"> - Downloads page - </a>{" "} - has whole-channel transcript zips. - </p> - )} - </div> - ); -}