diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 37006219..5a503932 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -8,6 +8,7 @@ on: - "README.md" - "apps/docs/**" - "packages/hyperliquid/README.md" + - "packages/hyperliquid/package.json" - ".github/CODEOWNERS" - ".github/workflows/docs.yml" - ".lycheeignore" @@ -20,6 +21,7 @@ on: - "README.md" - "apps/docs/**" - "packages/hyperliquid/README.md" + - "packages/hyperliquid/package.json" - ".github/CODEOWNERS" - ".github/workflows/docs.yml" - ".lycheeignore" @@ -62,6 +64,10 @@ jobs: working-directory: apps/docs run: bun run check + - name: Test documentation website helpers + working-directory: apps/docs + run: bun run test + - name: Build static documentation website working-directory: apps/docs run: bun run build diff --git a/apps/docs/README.md b/apps/docs/README.md index 5f0f6f9f..6bd8a842 100644 --- a/apps/docs/README.md +++ b/apps/docs/README.md @@ -63,9 +63,12 @@ The build verifies every documentation page, internal link, asset, and anchor, p The build also exports files that let AI agents use the site without rendering JavaScript: -- `public/llms.txt` is the curated entry point: what the SDK does, when to use it, and links to every page. +- `app/llms.txt/route.ts` generates the entry point from the docs source: what the SDK does, when to use it, + call examples, and links to every page. +- `app/llms-full.txt/route.ts` generates the complete docs with frontmatter removed and relative Markdown links + converted to absolute website URLs. - `scripts/export-markdown.ts` runs after `next build` and writes a Markdown mirror for each documentation page - (`/docs/clients/` → `/docs/clients.md`, served as `text/markdown`) plus a concatenated `llms-full.txt`. + (`/docs/clients/` → `/docs/clients.md`, served as `text/markdown`). - `app/sitemap.ts` emits `sitemap.xml`, and `public/robots.txt` explicitly allows AI crawlers. - `/about/`, `/contact/`, and `/privacy/` are trust pages, and the homepage carries JSON-LD (Organization with a contact point, WebSite, SoftwareApplication). @@ -74,6 +77,7 @@ The build also exports files that let AI agents use the site without rendering J `scripts/verify-export.ts` checks all of these after every build. GitHub Pages cannot do server-driven content negotiation, so `Accept: text/markdown` requests still receive HTML; the `.md` mirrors are the Markdown path. +Run `bun run --cwd apps/docs test` to test the agent-document generators and JSON-LD helpers. Build without `NEXT_PUBLIC_BASE_PATH` to serve at a domain root instead. ## Social cards 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 00000000..39befba8 --- /dev/null +++ b/apps/docs/app/llms-full.txt/route.ts @@ -0,0 +1,10 @@ +import { llmsFullText } from "@/lib/agent"; +import { agentPagesWithMarkdown } from "@/lib/agent-pages"; + +export const dynamic = "force-static"; + +export async function GET() { + return new Response(llmsFullText(await agentPagesWithMarkdown()), { + headers: { "Content-Type": "text/plain; charset=utf-8" }, + }); +} diff --git a/apps/docs/app/llms.txt/route.ts b/apps/docs/app/llms.txt/route.ts new file mode 100644 index 00000000..d5264087 --- /dev/null +++ b/apps/docs/app/llms.txt/route.ts @@ -0,0 +1,8 @@ +import { llmsText } from "@/lib/agent"; +import { agentPages } from "@/lib/agent-pages"; + +export const dynamic = "force-static"; + +export function GET() { + return new Response(llmsText(agentPages()), { headers: { "Content-Type": "text/plain; charset=utf-8" } }); +} diff --git a/apps/docs/app/not-found.tsx b/apps/docs/app/not-found.tsx index 1a77b540..451369f4 100644 --- a/apps/docs/app/not-found.tsx +++ b/apps/docs/app/not-found.tsx @@ -1,10 +1,13 @@ import { HomeLayout } from "fumadocs-ui/layouts/home"; +import type { Metadata } from "next"; import Link from "next/link"; import { SiteFooter } from "@/components/site-footer"; import { baseOptions } from "@/lib/layout.shared"; const basePath = process.env.NEXT_PUBLIC_BASE_PATH ?? ""; +export const metadata: Metadata = { title: "Page not found", robots: { index: false } }; + export default function NotFound() { return ( diff --git a/apps/docs/app/page.tsx b/apps/docs/app/page.tsx index f3547744..5f54669c 100644 --- a/apps/docs/app/page.tsx +++ b/apps/docs/app/page.tsx @@ -5,55 +5,10 @@ import { CopyButton } from "@/components/copy-button"; import { InstallCommand } from "@/components/install-command"; import { MarketPlayground } from "@/components/market-playground"; import { SiteFooter } from "@/components/site-footer"; +import { homeStructuredData, jsonLdScript } from "@/lib/agent"; import { baseOptions } from "@/lib/layout.shared"; -import { siteUrl } from "@/lib/social"; -const jsonLd = { - "@context": "https://schema.org", - "@graph": [ - { - "@type": "Organization", - "@id": "https://bloxwap.com/#organization", - name: "Bloxwap, Inc.", - url: "https://bloxwap.com", - sameAs: [ - "https://github.com/bloxwap", - "https://x.com/bloxwap", - "https://t.me/bloxwap", - "https://discord.com/invite/cEfkcg6JHT", - "https://www.reddit.com/r/Bloxwap/", - ], - contactPoint: { - "@type": "ContactPoint", - email: "support@bloxwap.com", - contactType: "customer support", - url: "https://bloxwap.github.io/hyperliquid/contact/", - }, - }, - { - "@type": "WebSite", - "@id": `${siteUrl.href}#website`, - url: siteUrl.href, - name: "Hyperliquid SDK · Bloxwap", - publisher: { "@id": "https://bloxwap.com/#organization" }, - }, - { - "@type": "SoftwareApplication", - name: "@bloxwap/hyperliquid", - description: - "A fast, fully typed TypeScript and JavaScript SDK for the Hyperliquid exchange API: market data, trading, signing, and real-time subscriptions over HTTP and WebSocket.", - applicationCategory: "DeveloperApplication", - operatingSystem: "Bun, Node.js, Browsers, React Native", - url: siteUrl.href, - downloadUrl: "https://www.npmjs.com/package/@bloxwap/hyperliquid", - codeRepository: "https://github.com/bloxwap/hyperliquid", - license: "https://opensource.org/licenses/MIT", - isAccessibleForFree: true, - offers: { "@type": "Offer", price: "0", priceCurrency: "USD" }, - author: { "@id": "https://bloxwap.com/#organization" }, - }, - ], -}; +const jsonLd = homeStructuredData(); const features = [ { @@ -93,8 +48,8 @@ export default function Home() { // min-h-dvh lets .landing grow into the slack, keeping the footer at the bottom of a tall window.
- {/* biome-ignore lint/security/noDangerouslySetInnerHtml: JSON.stringify of a static constant is the Next.js-documented way to emit ld+json verbatim. */} -