diff --git a/apps/docs/package.json b/apps/docs/package.json index 010088af..866ade8d 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -19,6 +19,7 @@ "@streamdown/code": "^1.0.1", "@streamdown/math": "^1.0.1", "@streamdown/mermaid": "^1.0.1", + "@vercel/agent-readability": "^0.2.1", "@vercel/analytics": "^1.6.1", "@vercel/speed-insights": "^1.3.1", "ai": "^6.0.105", @@ -63,4 +64,4 @@ "tw-animate-css": "^1.4.0", "typescript": "^5.9.3" } -} +} \ No newline at end of file diff --git a/apps/docs/proxy.ts b/apps/docs/proxy.ts index 9b4a6358..1b826c9e 100644 --- a/apps/docs/proxy.ts +++ b/apps/docs/proxy.ts @@ -7,6 +7,7 @@ import { } from "next/server"; import { i18n } from "@/lib/geistdocs/i18n"; import { trackMdRequest } from "@/lib/geistdocs/md-tracking"; +import { generateNotFoundMarkdown, isAIAgent } from "@vercel/agent-readability"; const { rewrite: rewriteLLM } = rewritePath( "/*path", @@ -57,6 +58,36 @@ const proxy = (request: NextRequest, context: NextFetchEvent) => { } } + // AI agent detection — rewrite docs pages to markdown for agents + if ( + (pathname === "/docs" || pathname.startsWith("/docs/")) && + !pathname.includes("/llms.mdx/") + ) { + const agentResult = isAIAgent(request); + if (agentResult.detected && !isMarkdownPreferred(request)) { + const result = rewriteLLM(pathname); + + if (result) { + context.waitUntil( + trackMdRequest({ + path: pathname, + userAgent: request.headers.get("user-agent"), + referer: request.headers.get("referer"), + acceptHeader: request.headers.get("accept"), + requestType: "agent-rewrite", + detectionMethod: agentResult.method, + }) + ); + return NextResponse.rewrite(new URL(result, request.nextUrl)); + } + // Agent requested a non-existent docs URL + return new NextResponse(generateNotFoundMarkdown(pathname), { + headers: { "Content-Type": "text/markdown; charset=utf-8" }, + }); + } + } + + // Handle Accept header content negotiation and track the request if (isMarkdownPreferred(request)) { const result = rewriteLLM(pathname);