llms.txt с Cloudflare Pages

Два подхода: разместить статический файл в каталоге сборки для мгновенного развёртывания без настройки или использовать Cloudflare Pages Function для динамического content.

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

Подход 1: статический файл в результате сборки

Самый простой вариант. Cloudflare Pages напрямую отдаёт каждый файл из каталога сборки через свою глобальную CDN. Не нужны Workers, Functions или изменения конфигурации.

static file, framework directory map
# For any framework deployed on Cloudflare Pages,
# place llms.txt in the directory that gets published.
#
# Framework       → file location
# Astro           → public/llms.txt
# Next.js         → public/llms.txt
# SvelteKit       → static/llms.txt
# Hugo            → static/llms.txt
# Eleventy        → _site root (copy via passthrough)
# Plain HTML      → project root or output folder

# After deploy, Cloudflare serves it at /llms.txt from their global CDN.
# Verify:
curl -I https://your-domain.com/llms.txt
# Expected: HTTP/2 200 | Content-Type: text/plain | CF-Cache-Status: HIT

Правильное расположение зависит от вашего фреймворка:

  • Astropublic/llms.txt (скопировано в dist/ автоматически)
  • Next.jspublic/llms.txt (адаптер Cloudflare Pages для Next.js поддерживает это)
  • SvelteKitstatic/llms.txt
  • Hugostatic/llms.txt
  • Eleventy → добавьте копирование без изменений: eleventyConfig.addPassthroughCopy("llms.txt")
  • Обычный HTML → поместите в папку, заданную как каталог вывода сборки

После развёртывания Cloudflare обслуживает файл через свою периферийную сеть по всему миру. Content-Type: text/plain заголовок задаётся автоматически на основе .txt расширение.

Подход 2: Cloudflare Pages Function

Cloudflare Pages Functions позволяют обрабатывать определённые маршруты кодом TypeScript, выполняемым в среде выполнения Cloudflare Workers. Создайте файл по адресу functions/llms.txt.ts и автоматически обрабатывает запросы к /llms.txt.

functions/llms.txt.ts, hardcoded content
// functions/llms.txt.ts
// Cloudflare Pages Functions use the file path as the route.
// This file handles GET requests to /llms.txt

interface Env {
  // Add KV namespace or D1 bindings here if needed
}

export const onRequestGet: PagesFunction<Env> = async (context) => {
  // Build content, hardcode here or pull from KV / D1 / API
  const content = [
    '# My Site',
    '',
    '> One-sentence description of what this site is about.',
    '',
    '## Documentation',
    '',
    '- [Getting started](https://yoursite.com/docs/getting-started/): first steps.',
    '- [API reference](https://yoursite.com/docs/api/): full endpoint catalog.',
    '',
    '## Optional',
    '',
    '- [Changelog](https://yoursite.com/changelog/): version history.',
  ].join('\n');

  return new Response(content, {
    headers: {
      'Content-Type': 'text/plain; charset=utf-8',
      // Cache at the edge for 1 hour, allow stale for 24h
      'Cache-Control': 'public, max-age=3600, stale-while-revalidate=86400',
    },
  });
};

Когда использовать: когда нужно создать файл из источника данных (базы данных, CMS API, KV-хранилища) без полной пересборки сайта. Пример с Пространство имён KV:

functions/llms.txt.ts, KV-backed content
// functions/llms.txt.ts, pulling content from KV
// Useful if you update the file from a CMS webhook without redeploying.

interface Env {
  LLMS_TXT: KVNamespace;
}

export const onRequestGet: PagesFunction<Env> = async ({ env }) => {
  const content = await env.LLMS_TXT.get('content');

  if (!content) {
    return new Response('# My Site\n\n> Content not configured yet.', {
      status: 200,
      headers: { 'Content-Type': 'text/plain; charset=utf-8' },
    });
  }

  return new Response(content, {
    headers: {
      'Content-Type': 'text/plain; charset=utf-8',
      'Cache-Control': 'public, max-age=300, stale-while-revalidate=3600',
    },
  });
};

С подходом KV вы можете обновлять содержимое /llms.txt через запись в пространство имён KV (через API, панель управления или вебхук из вашей CMS), не запуская полный деплой Pages.

Альтернатива: Cloudflare Worker

Если ваш сайт размещён не в Cloudflare Pages, но использует Cloudflare как прокси CDN/DNS, вы можете перехватить /llms.txt путь с отдельным Cloudflare Worker с помощью шаблон маршрута:

Cloudflare Worker, standalone
// Cloudflare Worker, wrangler.toml config
// Use this if you want a standalone Worker (not tied to Pages).

// wrangler.toml
// name = "llms-txt-worker"
// main = "src/index.ts"
// compatibility_date = "2024-09-01"
//
// [[routes]]
// pattern = "yoursite.com/llms.txt"
// zone_name = "yoursite.com"

// src/index.ts
export default {
  async fetch(request: Request): Promise<Response> {
    const content = `# My Site

> One-sentence description.

## Core pages

- [Getting started](https://yoursite.com/docs/getting-started/): first steps.
- [API reference](https://yoursite.com/docs/api/): full endpoint catalog.
`;

    return new Response(content, {
      headers: {
        'Content-Type': 'text/plain; charset=utf-8',
        'Cache-Control': 'public, max-age=3600',
      },
    });
  },
} satisfies ExportedHandler;

Заголовки кэша и поведение CDN

Cloudflare автоматически кэширует статические файлы из результатов сборки. Для статических файлов не нужно задавать заголовки кэша: Cloudflare учитывает TTL по умолчанию в настройках проекта Pages.

Для Pages Functions задайте Cache-Control явно в ответе. Рекомендуется:

  • public, max-age=3600, кэшируйте на периферии 1 час (подходит для файлов, поддерживаемых вручную).
  • public, max-age=3600, stale-while-revalidate=86400, отдавайте устаревшую версию до 24h при фоновой повторной проверке.
  • public, max-age=300, кэш на 5 минут для содержимого на KV, которое может часто обновляться.

При развёртывании новой версии Cloudflare автоматически очищает кэш изменённых статических файлов. Для Pages Functions используйте панель или API Cloudflare, чтобы очистить кэш конкретного URL, если нужна немедленная инвалидация.

Проверьте после публикации

verify
# Check headers, look for Content-Type and CF-Cache-Status
curl -I https://yoursite.com/llms.txt

# Check content
curl https://yoursite.com/llms.txt

# Purge Cloudflare cache if you deployed a new version:
# Dashboard → Caching → Configuration → Purge Everything
# or via API:
curl -X POST "https://api.cloudflare.com/client/v4/zones/{ZONE_ID}/purge_cache" \
  -H "Authorization: Bearer {CF_API_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{"files":["https://yoursite.com/llms.txt"]}'

Проверив заголовки, вставьте свой рабочий URL в валидатор чтобы подтвердить соответствие спецификации: ровно один H1, корректный синтаксис ссылок, все URL абсолютны, пустых разделов нет.

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

Источники