Hugo, Netlify i dylemat z plikiem llms.txt
Temat llms.txt i dyskusje wokół niego budzą ostatnio spore kontrowersje.
Z jednej strony zespół Google odpowiedzialny za relacje z wyszukiwarką (Search Relations, prowadzony przez Johna Muellera i Gary’ego Illyesa) wprost zadeklarował, że pliki llms.txt w żaden sposób nie wpływają na SEO ani pozycję w wynikach wyszukiwania. Z drugiej strony zespół rozwijający narzędzia dla deweloperów dodał niedawno do Lighthouse oraz PageSpeed Insights eksperymentalną kategorię „Agentic Browsing” (przeglądanie autonomiczne), która sprawdza obecność pliku llms.txt podczas audytu strony.
Może się to wydawać sprzeczne, ale wszystko układa się w logiczną całość, gdy oddzielimy indeksowanie stron w wyszukiwarce od nawigacji realizowanej bezpośrednio na stronie.
Spojrzenie zespołu ds. wyszukiwarki — John Mueller
Krytyka ze strony Johna Muellera skupia się wyłącznie na kwestiach związanych z SEO, indeksowaniem stron oraz zaufaniem.
Wyszukiwarka Google ignoruje plik llms.txt, ponieważ zawiera on informacje deklaratywne, tworzone przez samych właścicieli stron. Jeśli dana marka napisze w swoim pliku llms.txt: „Jesteśmy absolutnie najlepszą kancelarią prawną w Koszalinie”, sztuczna inteligencja nie może na tej podstawie uplasować jej wyżej od konkurencji. Mueller porównał to rozwiązanie do starych tagów meta keywords z lat dwutysięcznych — webmasterzy zbyt łatwo mogliby nimi manipulować lub upychać tam spam. Z tego powodu wyszukiwarka Google oraz sekcja AI Overviews (podsumowania AI) opierają się na standardowym kodzie HTML oraz zewnętrznych sygnałach określających autorytet strony.
PageSpeed a przeglądanie autonomiczne (Agentic Browsing)
Nowe audyty w sekcji Agentic Browsing w PageSpeed Insights nie oceniają Twojej strony pod kątem SEO. Ich celem jest sprawdzenie, jak łatwo agent AI może wchodzić w interakcję ze stroną i z niej korzystać po tym, jak już na nią trafi.
Gdy agent AI odwiedza Twoją witrynę w celu wykonania konkretnego zadania, potrzebuje jasnych wskazówek.
Plik llms.txt działa jak mapa lub spis sklepów umieszczony przy wejściu do centrum handlowego. Informuje on bota o istnieniu kluczowych podstron, dzięki czemu nie marnuje on czasu ani tokenów okna kontekstowego na bezmyślne przeszukiwanie całej struktury HTML.
O ile temat llms.txt to jedna kwestia, o tyle niezwykle interesująca okazała się analiza pod kątem dostępności (accessibility).
PageSpeed Insights to świetne miejsce do oceny kondycji Twojej strony. Jeśli wykryjesz tam jakieś błędy, możesz nad nimi popracować, aby ulepszyć witrynę. Problem pojawia się w sytuacji – szczególnie gdy Twoje statystyki są słabe i strona nie zalicza testu Core Web Vitals – kiedy dane nie odświeżają się z dnia na dzień. Możesz naprawić wszystkie usterki dzisiaj, ale na to, by zobaczyć, jak wprowadzone zmiany wpłyną na końcowy wynik, przyjdzie Ci poczekać 28 dni lub dłużej.
Drzewo dostępności (Accessibility Tree) i wskaźnik CLS: Upewnij się, że układ strony jest stabilny i prawidłowo oznaczony etykietami. Dzięki temu agent AI analizujący kod (lub robiący zrzuty ekranu) nie przeoczy ważnych przycisków ani nie kliknie w puste miejsce, jeśli zawartość strony nagle się przesunie.
Temat llms.txt nie jest już żadną nowością. Wiele osób tworzących swoje strony za pomocą generatorów witryn statycznych (SSG), takich jak Hugo, zdążyło już wypracować sposoby na automatyczne wdrażanie tego rozwiązania.
Ja również postanowiłem pójść tą drogą, ale zależało mi na stworzeniu bardziej uniwersalnego szablonu. Część moich witryn jest dostępna wyłącznie po angielsku, inne tylko po polsku, ale mam też takie, które obsługują dwa lub trzy języki — szablon musiał więc bezproblemowo radzić sobie w każdym z tych scenariuszy.
Dla sztucznej inteligencji język nie ma aż tak dużego znaczenia jak dla nas, ludzi. Choć polszczyzna została uznana za jeden z najlepszych języków dla AI ze względu na swoją precyzję i opisowość (co zresztą sprawia, że obcokrajowcom tak trudno się jej nauczyć, w przeciwieństwie do angielskiego, w którym wiele niuansów umyka w tłumaczeniu), zdecydowałem, że na wszystkich moich stronach plik llms.txt będzie generowany po angielsku.
Warto pamiętać, że funkcja Agentic Browsing weryfikuje przede wszystkim to, czy plik llms.txt spełnia wytyczne opisane na stronie llmstxt.org.
Zgodnie z oficjalną specyfikacją plik wymaga konkretnej struktury podzielonej na sekcje: głównego tytułu (
#), krótkiego opisu, opcjonalnej listy kluczowych szczegółów, a następnie sekcji dla głównych podstron (##) oraz zasobów zewnętrznych.
Zanim jednak przejdę do samego szablonu, muszę odpowiednio skonfigurować Hugo, aby generował ten plik automatycznie — zwyczajnie nie mam czasu na ręczne aktualizowanie go przy każdej zmianie.
Hugo — Konfiguracja
W pliku konfiguracyjnym Hugo hugo.toml muszę znaleźć sekcję [outputs] i dodać opcję generowania odpowiednich plików.
Struktura llms.txt powinna być minimalistyczna, aby nie przeciążać AI nadmiarem informacji. Nie ma sensu wrzucać całej zawartości witryny do jednego pliku.
Inspirując się artykułem Getting our Hugo+Netlify site agent compatible autorstwa Steph Locke, zdecydowałem się na podejście oparte na dwóch osobnych plikach:
llms.txt— uporządkowany indeks stronllms-full.txt— wersja z pełną zawartością do głębszego indeksowania
Mój wpis w konfiguracji będzie wyglądał następująco:
[outputs]
page = [ "html"]
home = [ "html", "rss", "llms", "llmsfull"]Po tym kroku musimy zdefiniować te dwa formaty i określić, za co dokładnie odpowiada każdy z nich.
[outputFormats.llms]
baseName = "llms"
isPlainText = true
mediaType = "text/plain"
[outputFormats.llmsfull]
baseName = "llms-full"
isPlainText = true
mediaType = "text/plain"Hugo — Poprawka nagłówka w Netlify
Jeśli po prostu wygenerujesz plik llms.txt za pomocą Hugo, Netlify zaserwuje go ze standardowym nagłówkiem text/plain (zgodnie z rozszerzeniem). Jednak ze względu na to, że plik ten zawiera składnię Markdown, przeglądarki oraz zaawansowane agenty AI mogą mieć problem z jego prawidłowym zinterpretowaniem.
Aby temu zaradzić, warto wymusić na Netlify przesyłanie pliku jako Markdown, nawet jeśli zachowuje on rozszerzenie .txt. Możesz to skonfigurować bezpośrednio w pliku netlify.toml, dzięki czemu Netlify doda odpowiedni nagłówek przy każdym zapytaniu o ten plik:
[[headers]]
for = "/llms.txt"
[headers.values]
Content-Type = "text/markdown; charset=utf-8"
[[headers]]
for = "/llms-full.txt"
[headers.values]
Content-Type = "text/markdown; charset=utf-8"Albo korzystając z mojej ulubionej metody, czyli za pomocą pliku _headers umieszczonego w katalogu static.
/llms.txt
Content-Type: text/markdown; charset=utf-8
/llms-full.txt
Content-Type: text/markdown; charset=utf-8Hugo — Szablon
Mając to wszystko przygotowane, mogę przejść do stworzenia szablonu.
Podczas weryfikacji obecności pliku
llms.txt, funkcja Agentic Browsing na ten moment nie szuka go w podfolderach — sprawdza wyłącznie katalog główny domeny. Jeśli jednak moja główna strona znajduje się w katalogu/, a pozostałe wersje językowe w podfolderach (np./en/), chcę zachować strukturę analogiczną do map stron (sitemaps). Szczególnie w przypadku witryn wielojęzycznych zależy mi na tym, aby informować AI o innych dostępnych wersjach językowych oraz o plikullms-full.txt.
Zaczynamy od pliku layout/home.llms.txt, który posłuży do wygenerowania llms.txt
# {{ .Site.Title }} [Language: {{ .Language.Name | upper }}]
> {{ .Site.Params.description | default "Website content index for AI agents." }}
{{ if .IsTranslated -}}
## Alternative Languages
{{ range .AllTranslations -}}
- [{{ .Language.Label }}]({{ .Permalink }}llms.txt)
{{ end }}
{{- end }}
## Key Information
- Current Language: {{ .Language.Lang }}
- Full Content Archive: {{ with .OutputFormats.Get "llmsfull" }}{{ .Permalink }}{{ else }}{{ "llms-full.txt" | absURL }}{{ end }}
## Main Sections
{{ range .Site.Sections -}}
- [{{ .Title }}]({{ .Permalink }}): {{ .Description | default (printf "Browse the %s section." .Title) }}
{{ end }}
## Recent Content
{{ range first 15 .Site.RegularPages -}}
- [{{ .Title }}]({{ .Permalink }}): {{ .Summary | plainify | htmlUnescape | chomp }}
{{ end }}A następnie przechodzimy do pliku home.llmsfull.txt, który wygeneruje llms-full.txt
# Full Content Archive for {{ .Site.Title }} [{{ .Language.Name | upper }}]
This document contains the complete text content of the website for comprehensive AI context and analysis.
{{ range .Site.RegularPages }}
---
## {{ .Title }}
- **URL:** {{ .Permalink }}
- **Date:** {{ .Date.Format "2006-01-02" }}
{{ with .Params.tags -}}- **Tags:** {{ delimit . ", " }}{{ end }}
### Content
{{ .RawContent }}
{{ end }}To podejście pozwala uzyskać uniwersalny i inteligentnie dopasowany do kontekstu efekt. Szablon dynamicznie wykrywa bieżący język, automatycznie zmienia nagłówki i wyświetla listę stron należących wyłącznie do tej konkretnej wersji językowej.
W przypadku mojej strony, kiedy Hugo generuje plik /llms.txt, zmienna .Language.Lang ma wartość "pl". Nagłówki zmieniają się na polskie, a pętla .Site.RegularPages przetwarza tylko artykuły napisane po polsku.
Gdy z kolei Hugo przechodzi do budowania pliku /en/llms.txt, zmienna .Language.Lang przyjmuje wartość "en". Nagłówki natychmiast przełączają się na język angielski, a system generuje listę składającą się wyłącznie z anglojęzycznych wpisów.
Jeśli w konfiguracji hugo.toml masz zdefiniowany trzeci lub czwarty język, ten szablon nie wymaga absolutnie żadnych modyfikacji w kodzie i od razu działa bez zarzutu!
W ten prosty sposób, bez względu na to, czy chcesz się w to zagłębiać, czy nie, całość działa w trybie „ustaw i zapomnij” – a PageSpeed Insights w sekcji Agentic Browsing bez problemu zaliczy test obecności pliku llms.txt.
Oto moje pliki wygenerowane już po wdrożeniu, jeśli chcesz sprawdzić, jak wyglądają i co zawierają:






Komentarze i Reakcje