Cloudflare Pages での llms.txt

2つの方法があります。ビルド出力ディレクトリに静的ファイルを置いて設定なしですぐデプロイするか、動的コンテンツ用の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.txtdist/ (自動的にコピー)
  • 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 機能

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 Namespace:

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と ルートパターン:

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;

Cacheヘッダーと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が正確に1つあること、リンク構文が有効であること、すべてのURLが絶対URLであること、空のセクションがないことを確認してください。

完全な作成ガイド · Astroガイド · Next.js ガイド

ソース