Czym jest llms.txt i skąd się wziął
llms.txt to propozycja standardu opisana na llmstxt.org, która zakłada umieszczenie w głównej ścieżce witryny pliku /llms.txt. Jego zadaniem jest dostarczenie modelom językowym pomocnej informacji w momencie wnioskowania (Inference time to moment, w którym model generuje odpowiedź na zapytanie użytkownika — w odróżnieniu od fazy treningu.).
Twórcy standardu wyszli z konkretnej obserwacji: modele coraz mocniej polegają na treściach z witryn, ale uderzają w twarde ograniczenie — ich Okno kontekstowe to maksymalna liczba tokenów (tekstu), jaką model może przetworzyć w jednym zapytaniu naraz. są zbyt małe, by zmieścić większość stron w całości. Konwersja zaśmieconego HTML-a z nawigacją, reklamami i JavaScriptem na czysty tekst zrozumiały dla LLM jest trudna i nieprecyzyjna. Witryny obsługują zarówno ludzi, jak i modele, ale to drugie korzystają najbardziej z eksperckiej, zwięzłej informacji zebranej w jednym, łatwo dostępnym miejscu.
Plik celowo używa Markdowna zamiast XML-a. Markdown to dzisiaj najszerzej i najłatwiej rozumiany format, a jednocześnie wystarczająco rygorystyczny, by parsowały go standardowe narzędzia programistyczne.
Warto też rozróżnić dwa pokrewne pliki, ponieważ różnica między nimi jest istotna: llms.txt to indeks — swego rodzaju spis treści z linkami do najważniejszych stron, i to właśnie jego potrzebuje większość witryn. llms-full.txt to już pełny eksport treści całej witryny w jednym dużym dokumencie Markdown, używany zwykle dla dokumentacji deweloperskiej lub ingestii danych strukturalnych. Co ciekawe, ekosystem Astro ma trzeci wariant — llms-small.txt — przefiltrowaną i kompaktową wersję dla modeli z mniejszym oknem kontekstowym.
robots.txt kontra llms.txt: dwa różne przepływy
robots.txt i llms.txt nie są wersjami tego samego — obsługują dwa fundamentalnie różne modele dostępu do treści.
Tradycyjne crawlery wyszukiwarek działają w trybie wsadowym: systematycznie skanują i indeksują całą witrynę, regularnie wracają w poszukiwaniu zmian, słuchają reguł robots.txt i sitemap.xml, a treść przechowują długoterminowo do późniejszego serwowania w wynikach.
Modele językowe rządzą się zupełnie inną logiką. Dostęp do treści uzyskują dopiero w chwili, gdy użytkownik zadaje pytanie — nie indeksują ani nie „pamiętają” Twojej strony na stałe. Wchodzą i wychodzą. Pracują w ograniczonym oknie kontekstowym, pomijają treści, które nie są wyraźnie podlinkowane lub łatwe do odczytania, i mają trudność z witrynami mocno opartymi na JavaScripcie i z zaśmieconym HTML-em.
Zestawienie pokazuje to najlepiej:
| Aspekt | robots.txt (stare crawlery) | llms.txt (agenty AI) |
|---|---|---|
| Adresat | Googlebot, Bingbot | ChatGPT, Claude, Perplexity, agenty IDE |
| Moment dostępu | Wsadowo, cyklicznie | W chwili zapytania (inference time) |
| Format | Dyrektywy User-agent / Disallow | Markdown |
| Cel | Kontrola crawlowania i indeksacji | Dostarczenie skondensowanego kontekstu |
| Pamięć | Długoterminowa indeksacja | Brak trwałej pamięci |
Jest jednak niuans, który trzeba postawić wprost, zanim potraktujesz llms.txt jako magiczny przełącznik. Stan na 2026: główne crawlery LLM jeszcze masowo go nie pobierają, a badania nad cytowalnością w odpowiedziach AI nie wykazują mierzalnej poprawy pozycji. Dźwignią, która dziś realnie kontroluje, jak systemy AI traktują Twoją witrynę, wciąż pozostaje robots.txt z odpowiednio skonfigurowanymi regułami User-agent dla botów AI (jak GPTBot to crawler OpenAI pobierający treści z sieci na potrzeby ChatGPT i trenowania modeli., ClaudeBot to crawler Anthropic pobierający treści z sieci na potrzeby Claude., Google-Extended to token User-agent, którym kontrolujesz wykorzystanie treści przez modele AI Google (Gemini), niezależnie od indeksacji w Search. czy CCBot to crawler Common Crawl — otwartego archiwum sieci wykorzystywanego do trenowania wielu modeli.).
Dlaczego więc każdy poważny serwis developer-tools i tak wdraża llms.txt? Bo koszt to pół dnia pracy, a w dniu, w którym duży dostawca LLM zdecyduje się go respektować, będziesz już gotowy. Ekosystem agentów w IDE już z niego korzysta. Trzymaj robots.txt w aktualności i nie spodziewaj się skoku ruchu z dnia na dzień.
llms.txtmówi modelowi co warto przeczytać, ale torobots.txtdecyduje, czy w ogóle wolno mu wejść.
Struktura pliku: jak poprawnie sformatować llms.txt
Specyfikacja jest rygorystyczna w kwestii kolejności sekcji. Plik nazwany llm.txt w liczbie pojedynczej nie zostanie rozpoznany — to częsty błąd, który sam neutralizuje całą pracę. Kodowanie musi być UTF-8, a plik musi leżeć w katalogu głównym.
Oto wymagana struktura w odpowiedniej kolejności:
- H1 z nazwą projektu lub witryny — to jedyna obowiązkowa sekcja.
- Blockquote (
>) z krótkim podsumowaniem, zawierającym kluczowe informacje potrzebne do zrozumienia reszty pliku. - Zero lub więcej sekcji Markdown (akapity, listy) dowolnego typu, ale bez nagłówków — z dodatkowym kontekstem.
- Sekcje z linkami oznaczone nagłówkami H2, gdzie każdy link ma format
[Tytuł strony](URL): krótki opis. - Opcjonalna sekcja
## Optionaldla treści drugorzędnych, które model może pominąć przy ograniczonym kontekście.
Minimalny, poprawny przykład wygląda tak:
Tylko strony indeksowalne — odfiltruj URL-e oznaczone
noindexlub zablokowane wrobots.txt, by nie ujawniać ukrytych treści.Tylko adresy kanoniczne — każdy link prowadzi do głównej wersji strony, bez duplikatów.
Świadomy dobór, a nie wszystko — jeśli wylistujesz każdy produkt i każdy wpis, model przekroczy okno kontekstowe i przestanie czytać, pomijając krytyczne sekcje jak FAQ. Lepsza jest mapa sztabowa hubów kategorii niż kompletna inwentaryzacja magazynu.
Implementacja w Astro
Astro daje tu dwie ścieżki, a jej wybór zależy od tego, czy chcesz plik statyczny, czy generowany dynamicznie z kolekcji treści.
Wariant 1: katalog public/ (najprostszy)
Zawartość katalogu public/ jest kopiowana do outputu builda dosłownie, bez przetwarzania. Dla małego serwisu bez automatyzacji wystarczy ręcznie utworzyć public/llms.txt. To rozwiązanie zerowego nakładu, ale wymaga ręcznej aktualizacji — czyli prędzej czy później rozjedzie się z treścią.
Wariant 2: endpoint API generowany z kolekcji (zalecany)
Dla bloga czy dokumentacji generuj plik dynamicznie z Content Collections. Tworzysz plik src/pages/llms.txt.ts:
Endpoint generuje się w czasie builda, więc ma zerowy wpływ na wydajność runtime’u. Używamy obiektu site z konfiguracji do budowy bezwzględnych URL-i i zwracamy standardowy Response z nagłówkiem text/plain, by crawler dostał dokładnie to, czego oczekuje.
Jeśli korzystasz z integracji @astrojs/sitemap, endpointy są domyślnie wykluczane z mapy strony, więc nie musisz nic robić, by uniknąć duplikacji. Gdybyś chciał, żeby plik był odnajdywalny przez Google, dodaj go ręcznie do customPages.
Wariant 3: gotowa integracja
Tam, gdzie nie zależy Ci na pisaniu od zera, sięgnij po gotowe integracje: astro-llms-generate czy @4hse/astro-llms-txt generują llms.txt, llms-small.txt i llms-full.txt podczas astro build, z opcjami includePatterns / excludePatterns. Dla witryn opartych na Starlight jest dedykowany starlight-llms-txt.
Generowanie llms-full.txt w Astro
Indeks to za mało, jeśli zależy Ci, by model dostał pełną treść bez wchodzenia na poszczególne podstrony. Tu wkracza llms-full.txt — jeden plik z całą treścią w Markdownie. W Astro tworzysz osobny endpoint src/pages/llms-full.txt.ts, który zamiast samych linków wstawia pełne body każdego wpisu:
W tym przykładzie każda sekcja zawiera tytuł, URL i opis — to minimalny, bezpieczny wariant. Jeśli chcesz dołączyć pełną treść wpisu, potrzebujesz surowego Markdown: w Astro 5/6 z glob loaderem nie ma bezpośredniego post.body, dlatego treść odczytujesz przez readFile z dysku (tak jak w wariancie Next.js poniżej) albo przez render(post) i ekstrakcję tekstu. Sekcje rozdzielamy separatorem ---, żeby model widział granice między dokumentami z chirurgiczną precyzją. Przy dużych blogach pamiętaj, że llms-full.txt urośnie do setek kilobajtów — jeśli przekroczysz rozsądny rozmiar, dorzuć obok llms-small.txt z samymi tytułami i opisami dla modeli z mniejszym oknem.
Automatyczne filtrowanie noindex i draftów
Specyfikacja jest tu jednoznaczna: do llms.txt nie trafiają strony oznaczone noindex ani zablokowane w robots.txt. W praktyce w Astro masz dwa źródła takich flag — pole draft w schemacie kolekcji oraz dedykowane pole noindex (jeśli je prowadzisz). Filtr w getCollection obsłuży oba naraz:
Zaletą tego podejścia jest to, że filtr żyje obok schematu kolekcji — jedno źródło prawdy steruje równocześnie indeksacją, sitemapą i llms.txt. Nie ma ryzyka, że oznaczysz wpis jako draft, a on i tak wycieknie do modeli AI.
Implementacja w Next.js
W Next.js (App Router) najczystszym podejściem jest Funkcja eksportowana z pliku route.ts w App Routerze, obsługująca metodę HTTP (GET, POST itd.). Przyjmuje standardowy Request i zwraca Response — to webowy odpowiednik dawnych API Routes.. Tworzysz plik app/llms.txt/route.ts:
Kluczowy jest force-static to tryb Route Handlera w Next.js wymuszający wygenerowanie odpowiedzi raz, podczas builda, i serwowanie jej jako statycznego pliku. — wymusza wygenerowanie pliku na etapie builda zamiast przy każdym żądaniu. Dla treści, która zmienia się tylko przy deployu, to idealny tryb pracy.
Jeśli wolisz statyczny plik bez logiki, w Next.js wystarczy umieścić llms.txt w katalogu public/ — tak jak w Astro będzie serwowany z roota.
Generowanie llms-full.txt w Next.js
Analogicznie do indeksu tworzysz app/llms-full.txt/route.ts, ale zamiast samego linku wstawiasz pełną treść wpisu. Zakładam tu, że Twoja warstwa danych (@/lib/posts) zwraca surowy Markdown w polu content — jeśli trzymasz treść w plikach MDX, najprościej odczytać ją funkcją pomocniczą czytającą pliki z dysku:
Jeśli treść trzymasz w MDX i nie masz jej jeszcze jako surowego stringa, pomocnik do odczytu wygląda tak:
Automatyczne filtrowanie noindex i draftów
W Next.js flagi sterujące indeksacją żyją zwykle we frontmatterze MDX (draft, noindex) i są mapowane na metadata.robots w funkcji generateMetadata poszczególnych stron. Żeby llms.txt nie rozjechał się z tym, co faktycznie pozwalasz indeksować, zastosuj ten sam filtr na liście wpisów:
Spójność z robots.txt
Filtrowanie treści to jedna strona medalu — druga to robots.txt. W Next.js generujesz go przez app/robots.ts:
To właśnie reguły User-agent w robots.txt (dla GPTBot, ClaudeBot, Google-Extended, CCBot) dziś faktycznie sterują dostępem botów AI — llms.txt mówi modelowi, co warto przeczytać, ale robots.txt decyduje, czy w ogóle wolno mu wejść.
Przewaga w ekosystemach Next.js i Astro
Dlaczego akurat te dwa frameworki tak dobrze grają z llms.txt? Bo oba mają wbudowaną warstwę treści strukturalnej — Content Collections w Astro i konwencje MDX/route handlers w Next.js — z której plik generuje się niemal za darmo jako produkt uboczny istniejącego pipeline’u. Nie tworzysz przy tym osobnego źródła prawdy.
Spójność — plik aktualizuje się automatycznie przy każdym buildzie, więc nigdy nie rozjedzie się z faktyczną treścią.
Higiena architektury — sam proces tworzenia
llms.txtzmusza do przemyślenia, które treści naprawdę się liczą. Ta wartość istnieje nawet gdyby żaden model nigdy pliku nie przeczytał.Gotowość operacyjna — plik możesz od razu wykorzystać wewnętrznie: wgrać do projektu w Claude albo umieścić w katalogu Cursora jako kontekst, gdy pracujesz z asystentem AI nad audytem czy strategią treści.
