Skip to content

Discovery

The llms.txt proposal only sets the location of the file, /llms.txt. Three ways to advertise it, to combine as you like:

{# templates/base.html.twig #}
<head>
{# a <link> tag #}
{{ llms_txt_link() }}
{# <link rel="llms-txt" href="https://example.com/llms.txt"> #}
{{ llms_txt_link({rel: 'alternate', type: 'text/markdown', title: 'LLMs.txt'}) }}
{# <link rel="alternate" href="https://example.com/llms.txt" type="text/markdown" title="LLMs.txt"> #}
{# the Link header of this page only, with the link() function of WebLink #}
{% do link(llms_txt_url(), 'llms-txt') %}
</head>
# the Link header of every HTML page
llms_txt:
discovery:
link_header: true # Link: <https://example.com/llms.txt>; rel="llms-txt"

link_header goes through WebLink: the link joins the _links of the request, and WebLink writes them all in one Link header, next to your preload() and preconnect() ones. It needs framework.web_link, enabled by default when symfony/web-link is installed. The bundle does not require it: run composer require symfony/web-link before enabling link_header, or the container fails to build. The link() Twig function of the first example comes from WebLink too. The header is added to successful HTML responses of main requests only: not to sub-requests, Turbo Frames, XHR, redirects, errors, JSON or the llms.txt file itself.

llms_txt_url() returns the absolute URL alone. Both use the route of the bundle when it is imported, and /llms.txt at the root of the site otherwise.