diff --git a/apps/developer-hub/src/app/llms.txt/route.ts b/apps/developer-hub/src/app/llms.txt/route.ts index 58de17aef8..e922c319fe 100644 --- a/apps/developer-hub/src/app/llms.txt/route.ts +++ b/apps/developer-hub/src/app/llms.txt/route.ts @@ -6,61 +6,44 @@ const CONTENT = `# Pyth Network Documentation > First-party financial oracle delivering real-time market data to 100+ blockchains. +This is the routing index for Pyth Network's documentation. AI agents should +identify the product the user needs from the descriptions below, then fetch +exactly one product file — each is self-contained with code examples, +addresses, and patterns. Do not fetch every link. + ## AI Agent Playbook -For an opinionated integration guide with code snippets and step-by-step procedures: -> https://docs.pyth.network/SKILL.md +- [Pyth Developer Playbook](https://docs.pyth.network/SKILL.md): Opinionated integration guide with step-by-step procedures and code snippets. ## Products -### Pyth Core — Decentralized Price Oracle -Pull-based oracle providing 500+ price feeds with 400ms updates across 100+ chains. Applications fetch signed prices from Hermes and verify on-chain in a single transaction. -Best for: DeFi protocols, lending, DEXs, derivatives. -Chains: EVM, Solana, Sui, Aptos, CosmWasm, NEAR, Starknet, and more. -> https://docs.pyth.network/llms-price-feeds-core.txt - -### Pyth Pro — Low-Latency Price Streaming -Enterprise WebSocket streaming with configurable update channels (1ms–1s). Requires API key. -Best for: HFT, MEV strategies, market making, risk management. -SDK: \`@pythnetwork/pyth-lazer-sdk\` (TypeScript) -> https://docs.pyth.network/llms-price-feeds-pro.txt -MCP server for AI assistants (setup, tools, troubleshooting): -> https://docs.pyth.network/price-feeds/pro/mcp.mdx -Pre-built MCP skills (price alerts, portfolio tracking, FX conversion, volatility analysis, and more): -> https://docs.pyth.network/price-feeds/pro/mcp-skills.mdx - -### Entropy — On-Chain Randomness -Secure verifiable random number generation using commit-reveal. Callback-based API. -Best for: Gaming, NFT mints, lotteries, fair selection. -> https://docs.pyth.network/llms-entropy.txt - -### Express Relay — MEV Protection -Auction-based MEV capture and order flow protection for DeFi protocols. -> https://docs.pyth.network/express-relay/index.mdx - -## Unsure Which Price Feed Product? -Comparison of Core vs Pro with decision matrix: -> https://docs.pyth.network/llms-price-feeds.txt +- [Pyth Core — Decentralized Price Oracle](https://docs.pyth.network/llms-price-feeds-core.txt): Pull-based oracle with 500+ price feeds, 400ms updates, 100+ chains (EVM, Solana, Sui, Aptos, CosmWasm, NEAR, Starknet, and more). Best for DeFi protocols, lending, DEXs, and derivatives. +- [Pyth Pro — Low-Latency Price Streaming](https://docs.pyth.network/llms-price-feeds-pro.txt): Enterprise WebSocket streaming with configurable update channels (1ms–1s). Requires an API key. Best for HFT, MEV strategies, market making, and risk management. +- [Entropy — On-Chain Randomness](https://docs.pyth.network/llms-entropy.txt): Secure verifiable random number generation using commit-reveal with a callback-based API. Best for gaming, NFT mints, lotteries, and fair selection. +- [Express Relay — MEV Protection](https://docs.pyth.network/express-relay/index.mdx): Auction-based MEV capture and order flow protection for DeFi protocols. + +## Choosing Between Core and Pro + +- [Price Feeds — Core vs Pro Overview](https://docs.pyth.network/llms-price-feeds.txt): Side-by-side comparison and decision matrix for picking between Pyth Core and Pyth Pro. + +## Pyth Pro Tooling + +- [Pyth Pro MCP Server](https://docs.pyth.network/price-feeds/pro/mcp.mdx): Setup, tools, and troubleshooting for the MCP server that exposes Pyth Pro to AI assistants. +- [Pyth Pro MCP Skills](https://docs.pyth.network/price-feeds/pro/mcp-skills.mdx): Pre-built skills for price alerts, portfolio tracking, FX conversion, volatility analysis, and more. ## Individual Page Access -Fetch any documentation page as plain markdown by appending .mdx: - https://docs.pyth.network/price-feeds/core/getting-started.mdx + +- [Markdown page access](https://docs.pyth.network/price-feeds/core/getting-started.mdx): Any documentation page is available as plain markdown by appending \`.mdx\` to its URL. ## Machine-Readable Metadata -Programmatic discovery with token counts and content hashes: -> https://docs.pyth.network/llms-manifest.json - -## Instructions for AI Agents -1. Read the product descriptions above to identify which product the user needs. -2. Fetch exactly ONE product file — each is self-contained with code examples, addresses, and patterns. -3. For deeper detail, fetch individual pages via .mdx URLs listed in each product file. -4. Do NOT fetch all files — only fetch the single best match for the user's question. + +- [llms-manifest.json](https://docs.pyth.network/llms-manifest.json): Programmatic discovery of all routing files with token counts and content hashes. `; export function GET() { return new NextResponse(CONTENT, { headers: { - "Cache-Control": "public, max-age=86400", + "Cache-Control": "public, max-age=3600", "Content-Type": "text/plain; charset=utf-8", }, status: 200, diff --git a/apps/developer-hub/src/components/Root/index.tsx b/apps/developer-hub/src/components/Root/index.tsx index b5fbce922c..f132001906 100644 --- a/apps/developer-hub/src/components/Root/index.tsx +++ b/apps/developer-hub/src/components/Root/index.tsx @@ -16,7 +16,33 @@ export const TABS = [ export const Root = ({ children, googleAnalyticsId }: Props) => ( + + + + + For AI agents: see /llms.txt for the documentation index. Any page can + be fetched as markdown by appending .mdx to its URL, or by sending an + Accept: text/markdown header. + For the complete documentation index, see [llms.txt](https://docs.pyth.network/llms.txt). + ${String(processed.value)}`; } diff --git a/apps/developer-hub/src/middleware.ts b/apps/developer-hub/src/middleware.ts new file mode 100644 index 0000000000..385504bbdf --- /dev/null +++ b/apps/developer-hub/src/middleware.ts @@ -0,0 +1,69 @@ +import { NextResponse } from "next/server"; +import type { NextRequest } from "next/server"; + +const SKIP_PREFIXES = [ + "/_next", + "/api", + "/playground", + "/mdx", +]; + +const SKIP_EXACT = new Set([ + "/", + "/favicon.ico", + "/robots.txt", + "/sitemap.xml", + "/llms.txt", + "/llms-full.txt", + "/llms-manifest.json", + "/llms-entropy.txt", + "/llms-price-feeds.txt", + "/llms-price-feeds-core.txt", + "/llms-price-feeds-pro.txt", + "/SKILL.md", +]); + +function prefersMarkdown(accept: string | null): boolean { + if (!accept) return false; + const entries = accept.split(",").map((part) => { + const [media = "", ...params] = part.trim().split(";").map((s) => s.trim()); + const qParam = params.find((p) => p.startsWith("q=")); + const q = qParam ? Number.parseFloat(qParam.slice(2)) : 1; + return { media, q: Number.isFinite(q) ? q : 1 }; + }); + const markdown = entries.find( + (e) => e.media === "text/markdown" || e.media === "text/x-markdown", + ); + if (!markdown) return false; + const html = entries.find((e) => e.media === "text/html"); + return !html || markdown.q >= html.q; +} + +export function middleware(request: NextRequest) { + if (request.method !== "GET" && request.method !== "HEAD") { + return NextResponse.next(); + } + if (!prefersMarkdown(request.headers.get("accept"))) { + return NextResponse.next(); + } + + const { pathname } = request.nextUrl; + if (SKIP_EXACT.has(pathname)) return NextResponse.next(); + if (SKIP_PREFIXES.some((p) => pathname === p || pathname.startsWith(`${p}/`))) { + return NextResponse.next(); + } + // Already a .md/.mdx URL — let the existing rewrite handle it. + if (/\.[a-z0-9]+$/i.test(pathname)) return NextResponse.next(); + + const url = request.nextUrl.clone(); + url.pathname = `/mdx${pathname}`; + const response = NextResponse.rewrite(url); + response.headers.set("Vary", "Accept"); + return response; +} + +export const config = { + matcher: [ + "/((?!_next/static|_next/image|_next/data|favicon.ico).*)", + ], +};