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.
The honest caveat, first
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.catalogenumerates fornew URL(options.baseUrl), a## Productssection (title, URL, price note) is generated automatically. Likewiseconfig.sources.policies→## Policies. - Sources may return
nullor 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.sectionsappends 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 — 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 — 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
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) — safe because the output is deterministic. rebilder.com serves its own at /llms.txt.
On other stacks, call generateLlmsTxt(config, options) yourself and serve the string from any route with the same content type.