diff --git a/apps/docs/app/docs/[slug]/llms.txt/route.ts b/apps/docs/app/docs/[slug]/llms.txt/route.ts new file mode 100644 index 0000000..fc019e2 --- /dev/null +++ b/apps/docs/app/docs/[slug]/llms.txt/route.ts @@ -0,0 +1,31 @@ +import { hookToMarkdown } from "@/lib/hook-markdown"; +import { HOOKS, getHook } from "@/lib/hooks-registry"; + +/* /docs//llms.txt — the machine-readable twin of every hook page: that + one hook rendered through the shared Markdown renderer. Prerendered for every + hook alongside its HTML page. */ +export function generateStaticParams() { + return HOOKS.map(({ slug }) => ({ slug })); +} + +export async function GET( + _request: Request, + { params }: { params: Promise<{ slug: string }> }, +): Promise { + const { slug } = await params; + const hook = getHook(slug); + + if (!hook) { + return new Response("Not found\n", { + status: 404, + headers: { "Content-Type": "text/plain; charset=utf-8" }, + }); + } + + return new Response(`${hookToMarkdown(hook)}\n`, { + headers: { + "Content-Type": "text/plain; charset=utf-8", + "Cache-Control": "public, max-age=0, must-revalidate", + }, + }); +} diff --git a/apps/docs/app/docs/page.tsx b/apps/docs/app/docs/page.tsx index 16b5458..3d2c79c 100644 --- a/apps/docs/app/docs/page.tsx +++ b/apps/docs/app/docs/page.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import { CodeBlock } from "@/components/code-block"; import { HookCard } from "@/components/hook-card"; +import { ArrowRightIcon } from "@/components/icons"; import { InstallCommand } from "@/components/install-command"; import { CATEGORY_LABELS, @@ -46,6 +47,39 @@ export default function DocsIndexPage() { can try it before you install it.

+
+
+

Building with an LLM?

+

+ Every hook — signatures, usage and source — as plain Markdown for AI + assistants and coding agents, generated from this site so it never + drifts. +

+
+
+ + Copy all hooks for AI + + + llms.txt + +
+
+

Quick start

  1. diff --git a/apps/docs/app/globals.css b/apps/docs/app/globals.css index 906904a..ff12fd9 100644 --- a/apps/docs/app/globals.css +++ b/apps/docs/app/globals.css @@ -266,6 +266,12 @@ body { animation: donate-bob 3.5s ease-in-out infinite; } +/* Smooth in-page anchor scrolling (e.g. the hero → #ai trigger). The + reduced-motion block below forces this back to `auto` when requested. */ +html { + scroll-behavior: smooth; +} + @media (prefers-reduced-motion: reduce) { *, *::before, diff --git a/apps/docs/app/layout.tsx b/apps/docs/app/layout.tsx index 797a71d..be2216c 100644 --- a/apps/docs/app/layout.tsx +++ b/apps/docs/app/layout.tsx @@ -27,6 +27,15 @@ export const metadata: Metadata = { default: "hookli — simple React hooks", }, description: TAGLINE, + alternates: { + // Advertise the machine-readable llmstxt.org representations of the site. + types: { + "text/plain": [ + { url: "/llms.txt", title: "hookli llms.txt" }, + { url: "/llms-full.txt", title: "hookli llms-full.txt" }, + ], + }, + }, openGraph: { type: "website", siteName: "hookli", diff --git a/apps/docs/app/llms-full.txt/route.ts b/apps/docs/app/llms-full.txt/route.ts new file mode 100644 index 0000000..f90b4d2 --- /dev/null +++ b/apps/docs/app/llms-full.txt/route.ts @@ -0,0 +1,14 @@ +import { buildLlmsFull } from "@/lib/llms"; + +/* /llms-full.txt — the whole library in one Markdown document (every hook via + the shared renderer). No request input, so it is prerendered at build time. */ +export const dynamic = "force-static"; + +export function GET(): Response { + return new Response(buildLlmsFull(), { + headers: { + "Content-Type": "text/plain; charset=utf-8", + "Cache-Control": "public, max-age=0, must-revalidate", + }, + }); +} diff --git a/apps/docs/app/llms.txt/route.ts b/apps/docs/app/llms.txt/route.ts new file mode 100644 index 0000000..e8c126a --- /dev/null +++ b/apps/docs/app/llms.txt/route.ts @@ -0,0 +1,14 @@ +import { buildLlmsIndex } from "@/lib/llms"; + +/* /llms.txt — the concise, llmstxt.org-standard index. No request input, so it + is prerendered to a static file at build time. */ +export const dynamic = "force-static"; + +export function GET(): Response { + return new Response(buildLlmsIndex(), { + headers: { + "Content-Type": "text/plain; charset=utf-8", + "Cache-Control": "public, max-age=0, must-revalidate", + }, + }); +} diff --git a/apps/docs/app/page.tsx b/apps/docs/app/page.tsx index 2a4da5e..edbb0b5 100644 --- a/apps/docs/app/page.tsx +++ b/apps/docs/app/page.tsx @@ -5,6 +5,7 @@ import { ArrowRightIcon, GitHubIcon } from "@/components/icons"; import { ComparisonSection } from "@/components/comparison-section"; import { FeaturesSection } from "@/components/features-section"; import { LiveProofSection } from "@/components/live-proof-section"; +import { AiSection } from "@/components/ai-section"; import { HooksIndexSection } from "@/components/hooks-index-section"; import { SupportSection } from "@/components/support-section"; import { BottomCtaSection } from "@/components/bottom-cta-section"; @@ -25,7 +26,15 @@ export default function Home() {