Cloudflare Pages 上的 llms.txt

两种做法:把静态文件放到构建输出目录中即可零配置即时部署,或者用 Cloudflare Pages Function 处理动态内容。

最近更新:

方法 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 允许你使用运行在 Cloudflare Workers 运行时上的 TypeScript 代码处理特定路由。创建文件: 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 的 webhook),而无需触发完整的 Pages 部署。

替代方案:Cloudflare Worker

如果你的网站不在 Cloudflare Pages 上,但使用 Cloudflare 作为 CDN/DNS 代理,则可以拦截 /llms.txt 路径通过一个独立的 Cloudflare Worker 提供,该 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 会遵循 Pages 项目设置中的默认 TTL。

对于 Pages Functions,请在响应中明确设置 Cache-Control 在响应中明确设置。建议:

  • public, max-age=3600,在边缘缓存 1 小时(适合手动维护的文件)。
  • public, max-age=3600, stale-while-revalidate=86400,在后台重新验证期间最多提供 24 小时的陈旧内容。
  • public, max-age=300,为可能频繁更新、由 KV 支持的内容设置 5 分钟缓存。

当你部署新版本时,Cloudflare 会自动使已更改静态 文件的缓存失效。对于 Pages Functions,如需立即失效,请使用 Cloudflare 仪表板或 API 清除特定 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 指南

来源