Added stateless llms.txt service with dependency injection (#28042)
ref https://github.com/TryGhost/Ghost/pull/27400 Implements the llms.txt specification for Ghost, providing machine-readable content to AI agents and LLM tooling. The feature is gated behind a private labs flag (llmsTxt) and the existing llms_enabled setting, so it ships dark by default. **Endpoints and routing** Four routes serve the index and full-text files: /llms.txt, /llms-full.txt, and their .well-known/ aliases. Per-entry markdown is available at /<slug>.md via scoped suffix routes registered directly on CollectionRouter and StaticPagesRouter, reusing the existing entryLookup pipeline rather than a broad regex. This preserves _respectDominantRouter, permalink redirect handling, and all other routing features. Content negotiation via Accept: text/markdown on canonical post/page URLs also works, returning the same markdown with Vary: Accept and a Content-Location header. **Architecture** The service layer is fully stateless — no in-memory cache, no event listeners. Every request computes its response fresh and relies on HTTP Cache-Control (default 1h) for CDN/proxy caching. All dependencies are injected via factory functions (createLlmsService, createLlmsHandler, createLlmsDiscovery) with no module-level singleton imports; the service is created once at boot in site.js and exposed via Express app.set(). markdown.js is a pure module with zero Ghost imports. **Content handling** llms-full.txt uses paginated DB queries (100 per batch) with a 5 MiB budget to bound response size on large sites. Queries include withRelated: ['tags', 'authors'] so the URL service can substitute :primary_tag/:primary_author in permalink templates. Non-public .md requests return 403 with a markdown explanation rather than a silent 404. Discovery headers (Link and X-Llms-Txt) are injected into all HTML responses via on-headers middleware when the feature is enabled. **Observability** Handler errors are logged with structured fields ([llms] prefix, event name, route) and forwarded to Sentry with matching tags, following the theme upload error pattern. Co-Authored-By: John O'Nolan <john@onolan.org>
H
Hannah Wolfe committed
1d7179f991d4ce0344e03f02230111035e620872
Parent: 96b5fe5
Committed by GitHub <noreply@github.com>
on 5/28/2026, 1:09:20 PM