Hosting-layer Link header for llms.txt discovery
We publish the llms-txt rel link via Firebase Hosting headers because the docs site is a Next.js static export and cannot set response headers at the framework layer.
0004 — Hosting-layer Link header for llms.txt discovery
Status: Accepted Date: 2026-04-19 Deciders: docs platform Supersedes: — Superseded by: —
Context
The llms.txt specification recommends that sites advertise their machine-readable index via the HTTP Link header with rel="llms-txt", in addition to serving the file at /llms.txt. This lets agents discover the index without guessing at conventional paths and without parsing HTML.
The Wordloop documentation site is built with Next.js 15 in static-export mode (output: 'export'). Static export does not support runtime middleware, route handlers that mutate response headers, or next.config.js headers() for the exported bundle — those hooks are only honoured by the Node server, which we are not running in production. Consequently, the Link header cannot be set at the framework layer.
The site is served by Firebase Hosting, which supports per-path response headers declaratively in firebase.json under hosting.headers.
Decision
Set the Link: </llms.txt>; rel="llms-txt", </llms-full.txt>; rel="llms-full-txt" header on every response from Firebase Hosting, via the firebase.json hosting.headers array. Additionally, set Content-Type: text/markdown; charset=utf-8 on every **/*.md path so the per-page markdown exports are served with the correct media type, and text/plain on the two llms*.txt files.
The header applies to all paths (source: "/**"). The rel advertisement is cheap and universally safe — every Wordloop documentation page is a valid entry point for an agent that then looks up the index.
Consequences
- Agents following the
llms.txtdiscovery pattern viacurl -Ior a HEAD request find the index without needing to hardcode/llms.txt. - The
.mdexports of each documentation page are served with the correct MIME type; command-line tooling (curl,wget) treats them as text. - The configuration lives in
firebase.json— a hosting-platform-specific file. If we ever migrate hosting providers, this configuration has to be reimplemented in the new provider's equivalent. This is captured in the debt annotation below.
Alternatives considered
- Set the header in a Next.js middleware. Rejected: middleware is incompatible with static export.
- Set the header via a meta tag in
<head>. Rejected: meta equivalents of theLinkheader (<link rel="llms-txt" href="...">) are not part of the spec and not observed by agents doing header-only HEAD requests. - Add an Express shim in front of the static export. Rejected: introducing a server just to set one header sacrifices the operational simplicity that motivated static export in the first place.
- Rely on convention only (
/llms.txtat the root). Rejected: the spec explicitly recommends the header. It is cheap to set and the canonical way for agents to discover the index.
Debt annotation
Principal: ~1 hour. One firebase.json edit, one ADR, one test.
Interest: Near-zero. The configuration does not drift; the header string is stable.
Multiplier: Hosting migration. If we move off Firebase, the firebase.json block has to be translated to the new hosting provider's header syntax. The content of the header does not change; only the declaration site does. If we ever move to a self-hosted Next.js runtime, the header moves to middleware and firebase.json can be discarded.
Verification
curl -I https://docs.wordloop.ai/docs/learn/architecture/overviewshows theLinkheader with bothllms-txtandllms-full-txttargets.curl -I https://docs.wordloop.ai/docs/learn/architecture/overview.mdreturnsContent-Type: text/markdown; charset=utf-8.curl -I https://docs.wordloop.ai/llms.txtreturnsContent-Type: text/plain; charset=utf-8.
Related
- Documentation principle — the dual-audience stance this header operationalises.
- Agent-Native Systems — the broader principle the discovery mechanism serves.
Stateful containers for the ML service
We run wordloop-ml as long-lived orchestrated containers rather than serverless functions to keep models warm for real-time transcription.
Docs are canonical knowledge and skills are the agent execution layer
We keep durable engineering guidance in the docs site and keep agent skills focused on triggering, context routing, tool use, safety, and verification.