# [llms.txt](https://rebilder.com/docs/llms-txt)

> Deterministic llms.txt generation from your gateway config, shipped because it’s cheap and merchants ask for it, with an honest note on what it actually does.

- **Updated:** 2026-08-12
- **Publisher:** Rebilder

## One caveat, first

> **llms.txt is not the strategy** Content negotiation (`Accept: text/markdown`) measured **~4.2x more effective** than llms.txt for accurate retrieval (300k-domain study, mid-2026), and llms.txt alone shows **no citation lift**. We ship it because it’s cheap to generate, free to serve, and merchants ask for it, but the gateway’s markdown path is the strategy, not this file.

## generateLlmsTxt

`generateLlmsTxt(config, options)` (root export of `@rebilder/gateway`) produces spec-shaped markdown (H1 site name, blockquote description, H2 sections of link lists) **deterministically, with injected values only, no LLM anywhere**. Same input → same output, which is why it’s safe to cache hard.

- If `config.sources.catalog` enumerates for `new URL(options.baseUrl)`, a `## Products` section (title, URL, price note) is generated automatically. Likewise `config.sources.policies` → `## Policies`.
- Sources may return `null` or throw for the base URL; both are tolerated as "nothing to list". A malformed price omits its note rather than breaking the file or emitting a wrong value.
- `options.sections` appends manual sections after the auto-generated ones, in order. Sections with no links are omitted.

| Option | Type | Notes |
| --- | --- | --- |
| `baseUrl` | `string` | The store’s canonical base URL. Catalog/policy sources are called with `new URL(baseUrl)` to enumerate site-wide entries, so wire them to return the full list for the base URL if you want auto sections. |
| `siteName` | `string` | The H1. Injected verbatim. |
| `description` | `string` | One-line description, rendered as the blockquote. Injected verbatim. |
| `sections` | `LlmsTxtSection[]` (optional) | Manual sections: `{ title, links: [{ title, url, note? }] }`. Links render as `- [title](url): note`. |

## Next.js route helper

app/llms.txt/route.ts

```
// app/llms.txt/route.ts
import { createLlmsTxtRouteHandler } from '@rebilder/gateway/next'
import { gatewayConfig } from '../../lib/gateway-config'

export const GET = createLlmsTxtRouteHandler(gatewayConfig, {
  baseUrl: 'https://store.example.com',
  siteName: 'Acme Outdoors',
  description: 'Trail footwear and gear, shipped from Bend, OR.',
  sections: [{ title: 'Guides', links: [{ title: 'Sizing guide', url: 'https://store.example.com/pages/sizing' }] }],
})
```

The route handler serves `text/plain; charset=utf-8` with long shared-cache headers (`public, max-age=300, s-maxage=3600, stale-while-revalidate=86400`), which is safe because the output is deterministic. rebilder.com serves its own at [/llms.txt](/llms.txt).

On other stacks, call `generateLlmsTxt(config, options)` yourself and serve the string from any route with the same content type.