1. Documentation
  2. Resources
  3. AI Agents
  • README
  • Docs
  • Github
  • Introduction
  • Quickstart
  • Text
  • Code
  • Lists
  • Tables
  • Accordion
  • Badge
  • Button
  • Callout
  • Code Block
  • Code Block Group
  • Code Snippet
  • Columns
  • Custom components
  • GitHub
  • Hover Card
  • Mermaid
  • Properties
  • Related Topics
  • Steps
  • Tabs
  • Tree
  • Images
  • Video
  • Files
  • Grain
  • Shade
  • Moss
  • Configuration
  • OpenAPI
  • AI Chat
  • Integrations
  • Site Identity
  • Content
  • Navigation
  • Appearance
  • Header and Footer
  • Icons
  • Fonts
  • SEO
  • Search
  • AI Agents
  • React Router
  • Astro
  • Next.js
  • Cloudflare
  • Vercel

AI Agents

Publish llms.txt, llms-full.txt, and page-level Markdown for AI agents.

llms.txt

Included in starter templates

This functionality is already configured in the starter templates. Follow the complete setup in the Quickstart.

/llms.txt is the small entry point for an AI assistant or any tool that needs to discover your documentation. Heyo Docs generates it from the same pages and navigation model that power the site, so links do not drift from the sidebar.

The file contains the documentation title and description, then an absolute Markdown URL for each page. It points agents to the smaller, page-level documents first; an agent can load only the context needed for a question instead of retrieving the complete site.

What to publish

Set siteUrl in heyo-docs.config.ts before deploying. That makes the links in the generated index deterministic and correct in previews, crawlers, and production:

heyo-docs.config.ts
export default heyoDocs({
  siteUrl: "https://docs.example.com",
  // ...the rest of the configuration
});

Serve the result as plain text at exactly /llms.txt with content-type: text/plain; charset=utf-8. The framework guides show the route for React Router, Next.js, and Astro.

How agents should use it

  1. Fetch /llms.txt to discover the available documentation.
  2. Choose the relevant *.md page URL from the list.
  3. Fetch that Markdown page and answer from its contents.
  4. Fetch /llms-full.txt only when the task genuinely requires the entire documentation corpus.

llms.txt is a discovery aid, not an access-control mechanism. Publish only content that is already intended to be public.

React Router

Create a project

A project created with create-heyo-docs already publishes /llms.txt. The template registers the resource route, reads the server-side content registry, and prerenders the file for static deployments. Set siteUrl in the generated configuration before deployment.

bun create @heyo-sh/heyo-docs my-docs --template react-router

Manual, minimal configuration

In an existing React Router Framework Mode app, add the resource route before the documentation catch-all and return the generated index from its loader:

app/routes.ts
route("llms.txt", "routes/llms.ts"),
route("*", "routes/docs.tsx"),
app/routes/llms.ts
import { llmsIndex } from "@heyo-sh/heyo-docs";
import type { LoaderFunctionArgs } from "react-router";

import config from "../../heyo-docs.config";
import { pages } from "virtual:heyo-docs-content/server";

export function loader({ request }: LoaderFunctionArgs) {
  const siteUrl = config.siteUrl ?? new URL(request.url).origin;
  return new Response(llmsIndex(pages, config, siteUrl), {
    headers: { "content-type": "text/plain; charset=utf-8" },
  });
}

Add /llms.txt to the prerender() result in react-router.config.ts when the site is deployed statically.

Next.js

Create a project

The Next.js template generated by create-heyo-docs includes the Route Handler and the generated Markdown registry it needs. No additional AI-agent setup is required after creation.

bun create @heyo-sh/heyo-docs my-docs --template next

Manual, minimal configuration

First run generateNextContent() before development and builds, as described in the Next.js setup guide. Re-export markdownPages and config from the server-only docs helper, then add this App Router handler:

app/llms.txt/route.ts
import { llmsIndex } from "@heyo-sh/heyo-docs/node";

import { config, markdownPages } from "../lib/docs";

export function GET(request: Request) {
  const siteUrl = config.siteUrl ?? new URL(request.url).origin;
  return new Response(llmsIndex(markdownPages, config, siteUrl), {
    headers: { "content-type": "text/plain; charset=utf-8" },
  });
}

Astro

Create a project

The Astro template generated by create-heyo-docs includes a static src/pages/llms.txt.ts API route. It is generated with the rest of the site; only siteUrl needs to be set for canonical links.

bun create @heyo-sh/heyo-docs my-docs --template astro

Manual, minimal configuration

After adding heyoDocsAstro({ config }) to astro.config.ts, create an API route that reads the server-side virtual page registry:

src/pages/llms.txt.ts
import type { APIRoute } from "astro";
import { llmsIndex } from "@heyo-sh/heyo-docs";

import config from "../../heyo-docs.config";
import { pages } from "virtual:heyo-docs-content/server";

export const GET: APIRoute = ({ request }) => {
  const siteUrl = config.siteUrl ?? new URL(request.url).origin;
  return new Response(llmsIndex(pages, config, siteUrl), {
    headers: { "content-type": "text/plain; charset=utf-8" },
  });
};

llms-full.txt

Included in starter templates

This functionality is already configured in the starter templates. Follow the complete setup in the Quickstart.

/llms-full.txt combines every generated documentation page into one plain-text response. It is useful when an assistant needs broad context—for example, to prepare an onboarding brief, compare several parts of the API, or index a small documentation site.

Heyo Docs builds the response from the Markdown page registry. The result has no frontmatter or documentation UI, so it is more useful to a language model than downloading and scraping a series of rendered HTML pages.

When to use it

Use the full document for offline indexing, evaluation fixtures, or tasks that span many pages. For interactive questions, start with llms.txt and load the individual Markdown pages instead. Targeted retrieval keeps prompts smaller, reduces repeated context, and makes the sources easier to inspect.

Response contract

Expose this file at /llms-full.txt with:

text
content-type: text/plain; charset=utf-8

The document is generated at request time by the React Router and Next.js templates. Astro emits the equivalent static response during its build. In all cases the source is the same content registry used by the docs UI.

Because the file may grow with every MDX page, do not treat it as the default context window for an agent. Keep llms.txt and per-page Markdown endpoints available alongside it.

React Router

Create a project

The React Router template generated by create-heyo-docs includes this resource route and adds /llms-full.txt to its static prerender list. Set siteUrl in the generated configuration before deployment.

bun create @heyo-sh/heyo-docs my-docs --template react-router

Manual, minimal configuration

Register llms-full.txt before the documentation catch-all, then generate the response from the server-side virtual content registry:

app/routes.ts
route("llms-full.txt", "routes/llms-full.ts"),
route("*", "routes/docs.tsx"),
app/routes/llms-full.ts
import { llmsFull } from "@heyo-sh/heyo-docs";
import type { LoaderFunctionArgs } from "react-router";

import config from "../../heyo-docs.config";
import { pages } from "virtual:heyo-docs-content/server";

export function loader({ request }: LoaderFunctionArgs) {
  const siteUrl = config.siteUrl ?? new URL(request.url).origin;
  return new Response(llmsFull(pages, siteUrl), {
    headers: { "content-type": "text/plain; charset=utf-8" },
  });
}

Include /llms-full.txt in react-router.config.ts's prerender() result when the documentation is served statically.

Next.js

Create a project

The Next.js project produced by create-heyo-docs includes the Route Handler and runs the content generator that creates markdownPages before development and production builds.

bun create @heyo-sh/heyo-docs my-docs --template next

Manual, minimal configuration

Follow the manual Next.js setup to generate the content registry and re-export config and markdownPages from app/lib/docs.ts. Then add the Route Handler:

app/llms-full.txt/route.ts
import { llmsFull } from "@heyo-sh/heyo-docs/node";

import { config, markdownPages } from "../lib/docs";

export function GET(request: Request) {
  const siteUrl = config.siteUrl ?? new URL(request.url).origin;
  return new Response(llmsFull(markdownPages, siteUrl), {
    headers: { "content-type": "text/plain; charset=utf-8" },
  });
}

Astro

Create a project

The Astro project produced by create-heyo-docs contains a static src/pages/llms-full.txt.ts API route. It is emitted during astro build alongside the documentation output.

bun create @heyo-sh/heyo-docs my-docs --template astro

Manual, minimal configuration

After configuring heyoDocsAstro({ config }), add this API route under src/pages:

src/pages/llms-full.txt.ts
import type { APIRoute } from "astro";
import { llmsFull } from "@heyo-sh/heyo-docs";

import config from "../../heyo-docs.config";
import { pages } from "virtual:heyo-docs-content/server";

export const GET: APIRoute = ({ request }) => {
  const siteUrl = config.siteUrl ?? new URL(request.url).origin;
  return new Response(llmsFull(pages, siteUrl), {
    headers: { "content-type": "text/plain; charset=utf-8" },
  });
};

Markdown endpoints

Included in starter templates

This functionality is already configured in the starter templates. Follow the complete setup in the Quickstart.

Every documentation page has a public Markdown mirror. The page at /guides/installation is available as /guides/installation.md; the home page is available as /index.md. These endpoints return the generated, frontmatter-free Markdown source with:

text
content-type: text/markdown; charset=utf-8

This is the preferred retrieval surface for AI agents. It preserves headings, lists, links, and code examples while avoiding navigation, search controls, and other HTML that would be irrelevant to an answer.

Public URLs, internal routing

The *.md URL is part of your public contract. Each framework routes it to an internal handler differently:

  • React Router redirects the public URL through middleware to a resource route.
  • Next.js rewrites it through proxy.ts to a Route Handler.
  • Astro generates a static [...,slug].md endpoint.

The implementation details stay internal; agents always request the same stable public URL. A request for an unknown page returns 404 Not Found rather than falling through to the documentation shell.

Keep the source of truth singular

Use markdownForPage() with the generated page registry rather than maintaining separate AI-facing files. That ensures the UI, search index, llms.txt, llms-full.txt, and Markdown mirrors all represent the same release of the documentation.

The Markdown is public content. Do not put secrets, private runbooks, or instructions that should not be exposed to browsers into the configured documentation directory.

React Router

Create a project

The React Router template generated by create-heyo-docs already includes the public Markdown redirect, its internal resource route, and the route registration. An agent can request /quickstart.md immediately after the project is deployed.

bun create @heyo-sh/heyo-docs my-docs --template react-router

Manual, minimal configuration

Add an internal resource route before the documentation catch-all. It resolves the requested Markdown pathname against the server-side virtual registry:

app/routes.ts
route("__heyo-docs/markdown/*", "routes/markdown.ts"),
route("*", "routes/docs.tsx"),
app/routes/markdown.ts
import { markdownForPage, pathnameFromMarkdownPath } from "@heyo-sh/heyo-docs";
import type { LoaderFunctionArgs } from "react-router";

import { pages } from "virtual:heyo-docs-content/server";

export function loader({ params }: LoaderFunctionArgs) {
  const pathname = pathnameFromMarkdownPath(`/${params["*"] ?? ""}`);
  const page = pathname
    ? pages.find((candidate) => candidate.slug === pathname)
    : undefined;

  if (!page)
    return new Response("Not Found", {
      status: 404,
      headers: { "content-type": "text/plain; charset=utf-8" },
    });

  return new Response(markdownForPage(page), {
    headers: { "content-type": "text/markdown; charset=utf-8" },
  });
}

Finally, redirect valid public *.md paths to the internal resource route from app/root.tsx:

ts
import { pathnameFromMarkdownPath } from "@heyo-sh/heyo-docs";
import type { Route } from "./+types/root";

const markdownResourcePrefix = "/__heyo-docs/markdown";

const markdownMiddleware: Route.MiddlewareFunction = async (
  { request },
  next,
) => {
  const url = new URL(request.url);
  if (
    !url.pathname.startsWith(`${markdownResourcePrefix}/`) &&
    pathnameFromMarkdownPath(url.pathname) !== undefined
  ) {
    return Response.redirect(
      new URL(`${markdownResourcePrefix}${url.pathname}${url.search}`, url),
      307,
    );
  }
  return next();
};

export const middleware = [markdownMiddleware];

Next.js

Create a project

The Next.js template generated by create-heyo-docs already includes proxy.ts and its internal Markdown Route Handler. The proxy keeps *.md URLs outside the App Router documentation catch-all.

bun create @heyo-sh/heyo-docs my-docs --template next

Manual, minimal configuration

Generate the content registry before development and builds, then re-export markdownPages from your server-only app/lib/docs.ts helper. Add the proxy:

proxy.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function proxy(request: NextRequest) {
  const { pathname } = request.nextUrl;
  if (pathname.endsWith(".md"))
    return NextResponse.rewrite(
      new URL(`/heyo-docs-internal/markdown${pathname}`, request.url),
    );
  return NextResponse.next();
}

Then add the internal Route Handler. It returns a direct Markdown response or a 404, never the rendered documentation shell:

app/heyo-docs-internal/markdown/[[...slug]]/route.ts
import {
  markdownForPage,
  pathnameFromMarkdownPath,
} from "@heyo-sh/heyo-docs/node";

import { markdownPages } from "../../../lib/docs";

export async function GET(
  _request: Request,
  { params }: { params: Promise<{ slug?: string[] }> },
) {
  const { slug } = await params;
  const pathname = pathnameFromMarkdownPath(`/${slug?.join("/") ?? ""}`);
  const page = pathname
    ? markdownPages.find((candidate) => candidate.slug === pathname)
    : undefined;

  if (!page) return new Response("Not Found", { status: 404 });

  return new Response(markdownForPage(page), {
    headers: { "content-type": "text/markdown; charset=utf-8" },
  });
}

Astro

Create a project

The Astro template generated by create-heyo-docs includes a static dynamic route for every Markdown mirror. Astro emits these files during astro build, without a runtime rewrite or middleware.

bun create @heyo-sh/heyo-docs my-docs --template astro

Manual, minimal configuration

After adding heyoDocsAstro({ config }) to astro.config.ts, add a dynamic API route that enumerates the generated page registry:

src/pages/[...slug].md.ts
import type { APIRoute } from "astro";
import { markdownForPage, pathnameFromMarkdownPath } from "@heyo-sh/heyo-docs";

import { pages } from "virtual:heyo-docs-content/server";

export function getStaticPaths() {
  return pages.map((page) => ({
    params: { slug: page.slug === "/" ? "index" : page.slug.slice(1) },
  }));
}

export const GET: APIRoute = ({ params }) => {
  const pathname = pathnameFromMarkdownPath(`/${params.slug ?? ""}.md`);
  const page = pathname
    ? pages.find((candidate) => candidate.slug === pathname)
    : undefined;

  if (!page)
    return new Response("Not Found", {
      status: 404,
      headers: { "content-type": "text/plain; charset=utf-8" },
    });

  return new Response(markdownForPage(page), {
    headers: { "content-type": "text/markdown; charset=utf-8" },
  });
};
Search< PreviousReact RouterNext >

Powered by heyo-docs

On this page

llms.txtWhat to publishHow agents should use itReact RouterCreate a projectManual, minimal configurationNext.jsCreate a projectManual, minimal configurationAstroCreate a projectManual, minimal configurationllms-full.txtWhen to use itResponse contractReact RouterCreate a projectManual, minimal configurationNext.jsCreate a projectManual, minimal configurationAstroCreate a projectManual, minimal configurationMarkdown endpointsPublic URLs, internal routingKeep the source of truth singularReact RouterCreate a projectManual, minimal configurationNext.jsCreate a projectManual, minimal configurationAstroCreate a projectManual, minimal configuration