Skip to content

Markdown and llms.txt

The Markdown version of every page, the llms.txt indexes and llms-full.txt that every site publishes, and the routes behind them.

AI-generated · awaiting reviewUpdated

Every Nimbus site publishes a plain-text copy of itself for agents and other tools. New sites have the routes already.

What every site publishes

Path What it is
/<slug>/index.md The page as clean Markdown, with components converted to text. Links to its .mdx source.
/<slug>/index.mdx The page’s authored source, with imports, JSX and directives. Not published for API pages.
/llms.txt An index of the current docs: top-level pages and a link to each section’s index.
/<section>/llms.txt An index for each top-level group and collection, and each folder below it, linked from its parent.
/llms-full.txt Every current page in one Markdown document. Over 25 MiB, it becomes an index of one llms-full.txt per section.
/<version>/llms.txt An index for each older docs version, which the site index leaves out.

On a versioned site, every Markdown version’s frontmatter has a version: key, so agents can pin a version. Every page’s head also carries JSON-LD structured data. Pages with draft: true or noindex: true are left out of the indexes; see Docs for agents for the full rules.

Add your own frontmatter

Each page’s Markdown version carries title, description, image and, where the page has one, version. To add other fields, declare them in schemaFields and name them in markdownFields:

src/content.config.tsts
changelog: defineCollection(
  docsCollection({
    base: "changelog",
    schemaFields: {
      date: z.coerce.date(),
      tags: z.array(z.string()).default([]),
    },
    markdownFields: ["date", "tags"],
  }),
),

The fields follow Nimbus’s own keys, in the order you list them, in both index.md and index.mdx. Values can be strings, numbers, booleans, dates, or arrays of those; a field a page leaves empty is left out.

A date at midnight UTC is written as 2026-07-02, and any other time in full with Z. Write dates without a time, or with an offset (2026-07-02T09:30:00+02:00): a time without an offset is read in the build machine’s timezone.

Add the routes to an older site

A site created before these routes shipped adds five endpoints. The Nimbus integration must already be present in astro.config.ts.

1. Add alternate page versions

Create the clean Markdown version:

src/pages/[...slug]/index.md.tsts
import { markdownRoute } from "@cloudflare/nimbus-docs/agent-endpoints";

export const { GET, getStaticPaths } = markdownRoute();

Create the MDX source version:

src/pages/[...slug]/index.mdx.tsts
import { markdownSourceRoute } from "@cloudflare/nimbus-docs/agent-endpoints";

export const { GET, getStaticPaths } = markdownSourceRoute();

These two routes serve every collection, including docs versions, a blog at /blog, and API references. API pages have a .md version but no .mdx source. Pages in hidden versions have neither. Collections you add later need no new route files. To customize the output for some or all pages, see Override a default.

On a static site these routes build ahead of time. With a rendering policy, a page’s Markdown follows its collection’s rendering mode automatically: a request-rendered collection serves its Markdown and MDX versions on request from these same routes, and prerendered collections keep their static files. Run nimbus-docs check --fix after changing the policy to write each route’s mode into the file.

2. Add the site index

Create the site-wide discovery index:

src/pages/llms.txt.tsts
import { llmsRoute } from "@cloudflare/nimbus-docs/agent-endpoints";

export const { GET } = llmsRoute();

3. Add llms-full.txt

Create the file containing all discoverable documentation:

src/pages/llms-full.txt.tsts
import { llmsFullRoute } from "@cloudflare/nimbus-docs/agent-endpoints";

export const { GET } = llmsFullRoute();

This file is optional. Without it, Nimbus doesn’t build llms-full.txt and llms.txt doesn’t link to it.

When the document would be over 25 MiB (Cloudflare’s per-file limit), /llms-full.txt becomes an index of one llms-full.txt per section, such as /reference/llms-full.txt. Nimbus serves those files from a route of its own, beside this one, so there’s nothing to add. Wrapping this route’s GET doesn’t change the section files.

  • A section under the limit holds its pages in full, as llms-full.txt does. The index gives its size.
  • A section over the limit is itself an index: it links its sub-folders’ files, marked “split further” where they’re split again, and links each of its own pages’ Markdown. A folder over the limit with no sub-folders is a list of links to its pages, marked “links to its pages”.
  • Pages at the top of the site are linked from /llms-full.txt, not included in it.

The build log lists the files it wrote. On Cloudflare (the adapter, or a wrangler file), the build warns about any agent file over 25 MiB, including a single page’s Markdown, because that file would fail the deploy.

4. Add section indexes

Create the route for paths such as /writing/llms.txt and /reference/functions/llms.txt:

src/pages/[...section]/llms.txt.tsts
import { llmsSectionRoute } from "@cloudflare/nimbus-docs/agent-endpoints";

export const { GET, getStaticPaths } = llmsSectionRoute();

Each section index lists the pages in its folder, then links each sub-folder’s llms.txt under “Sections”, so an agent descends one level at a time. A folder with only an index.mdx is a page of its parent.

A section is named by its index page’s sidebar.group.label, then its title, then the folder name.

Each GET returns 404 for an unknown section. Rendered on request, it returns a 500 without details when an index can’t be read, and logs the error. To change what a route serves, see Override a default.

The llms.txt endpoints follow the rendering policy too: the site index and llms-full.txt use rendering.default, and a section index uses its collection’s mode.

The build warns when a prerendered collection’s Markdown or llms.txt has no route, and names the route to add.

Verify

Run a production build, then start Astro’s production preview:

pnpm build
pnpm preview

In another terminal, replace guides/install and writing with routes that exist in the project. If Astro has a deployment base, prefix each path with it:

curl --fail http://localhost:4321/guides/install/index.md
curl --fail http://localhost:4321/guides/install/index.mdx
curl --fail http://localhost:4321/llms.txt
curl --fail http://localhost:4321/llms-full.txt
curl --fail http://localhost:4321/writing/llms.txt

Each command should return content with a success status. A 404 means the route file is missing, or the collection isn’t a page collection; wrap a custom loader with withNimbusMarkdown().

If a section index is missing, check that the section has discoverable pages and appears in /llms.txt.

Direct rendering

renderEntryAsMarkdown() and getEntryMarkdown() remain available for entry bodies that do not contain <Render>. Passing a body with <Render> throws. Use the endpoints above for alternate authored Markdown versions and llms.txt indexes. getEntryMarkdown() also loads API citation data and is intended for prerendered routes.

Next steps

Type to search…

↑↓ navigate↵ selectEsc close