llms.txt с Astro

Два подхода: положить файл в public/ для мгновенного развёртывания или динамически генерировать его из коллекций контента с помощью конечной точки TypeScript.

Последнее обновление:

Подход 1. Статический файл в public/

Самый простой вариант. Создайте обычный текстовый файл по адресу public/llms.txt в корне проекта. Astro копирует весь public/ каталог без изменений в dist/ во время astro build, поэтому файл доступен по адресу /llms.txt с нулевой конфигурацией.

static approach, public/llms.txt
# Place the file at: public/llms.txt
# Astro copies everything in public/ to the output directory as-is.
# Result: served at https://yoursite.com/llms.txt, no code changes needed.

# After deploy, verify:
curl -I https://yoursite.com/llms.txt
# Expected: HTTP/2 200 | Content-Type: text/plain

Когда использовать: если ваш контент меняется нечасто, вам не нужны накладные расходы во время сборки или вы обслуживаете файл вручную. Одинаково работает на Cloudflare Pages, Vercel, Netlify и любом другом хостинге Astro.

Подход 2, конечная точка TypeScript с getCollection()

Astro соответствует двойному расширению .txt.ts и рассматривает src/pages/llms.txt.ts в качестве эндпоинта API, отвечающего по адресу /llms.txt. В режиме SSG (по умолчанию) Astro предварительно генерирует его в статический dist/llms.txt во время сборки, без затрат на выполнение.

src/pages/llms.txt.ts
// src/pages/llms.txt.ts
// Astro treats src/pages/foo.ext.ts as a route for /foo.ext
// In SSG mode (default), it pre-renders to dist/llms.txt at build time.

import type { APIRoute } from 'astro';
import { getCollection } from 'astro:content';

export const GET: APIRoute = async () => {
  // Replace 'docs' with your actual content collection name
  const docs = await getCollection('docs');

  const lines = [
    '# My Site',
    '',
    '> One-sentence description of what this site is about.',
    '',
    '## Documentation',
    '',
    ...docs
      .filter((d) => !d.data.draft)
      .sort((a, b) => (a.data.order ?? 999) - (b.data.order ?? 999))
      .map((d) => `- [${d.data.title}](https://yoursite.com/${d.slug}/): ${d.data.summary ?? ''}`.trimEnd()),
    '',
    '## Optional',
    '',
    '- [Changelog](https://yoursite.com/changelog/): version history.',
  ];

  return new Response(lines.join('\n'), {
    headers: { 'Content-Type': 'text/plain; charset=utf-8' },
  });
};

Основные моменты:

  • Заменить 'docs' с фактическим названием коллекции из src/content/config.ts.
  • Отфильтруйте черновики перед построением карты: !d.data.draft.
  • Каждая строка-аннотация (: short note) необязателен, но настоятельно рекомендуется: он даёт большим языковым моделям контекст о каждой странице, не заставляя их получать её.
  • Всегда устанавливайте Content-Type: text/plain; charset=utf-8 в ответе.

Добавление llms-full.txt

llms-full.txt сопутствующий файл встраивает полное содержимое каждой страницы, что удобно для RAG-конвейеров и клиентов LLM, которым нужен весь корпус сразу. Создайте параллельную конечную точку:

src/pages/llms-full.txt.ts
// src/pages/llms-full.txt.ts
// Generates the full-content companion file.
// Each entry gets its full Markdown body inlined, useful for RAG pipelines.

import type { APIRoute } from 'astro';
import { getCollection } from 'astro:content';

export const GET: APIRoute = async () => {
  const docs = await getCollection('docs');
  const sections: string[] = [];

  for (const doc of docs.filter((d) => !d.data.draft)) {
    sections.push(
      `# ${doc.data.title}`,
      '',
      `URL: https://yoursite.com/${doc.slug}/`,
      '',
      doc.body,   // raw Markdown, no HTML, ideal for LLMs (Astro 4+)
      '',
      '---',
      '',
    );
  }

  return new Response(sections.join('\n'), {
    headers: { 'Content-Type': 'text/plain; charset=utf-8' },
  });
};

doc.body содержит исходный Markdown (доступен начиная с Astro 4), что идеально для LLM: никаких HTML-тегов, чистый семантический текст. Для Astro 3 используйте render() вспомогательную функцию и удалите теги простым регулярным выражением.

Проверка после сборки

verify
# Build the project
npx astro build

# Check static output (works for both approaches in SSG mode)
cat dist/llms.txt

# Or start preview server and curl:
npx astro preview &
curl http://localhost:4321/llms.txt
curl http://localhost:4321/llms-full.txt

После развёртывания вставьте действующий URL в валидатор для проверки соответствия спецификации: ровно один H1, корректный синтаксис ссылок (- [title](https://...)), все URL абсолютны, пустых разделов нет.

Какой подход выбрать

  • Статический public/llms.txt, лучше всего для сайтов, которые обновляются нечасто. Нулевые накладные расходы, TypeScript не требуется, работает везде.
  • Конечная точка TypeScript src/pages/llms.txt.ts, лучше всего подходящий сайтам документации с большим числом автоматически создаваемых страниц. Файл автоматически синхронизируется при каждой сборке без ручного редактирования.

Полное руководство по созданию · Руководство по Next.js · Руководство по WordPress

Источники