回到頂部

🤖 幫 195 篇文章自動生成 llms.txt:用 80 行 Node 解鎖 GEO

靜態站想被 ChatGPT、Perplexity 引用?不用等 SEO 寫完,80 行 Node 腳本就能在每次 build 自動產出全文索引。

為什麼會做這個

我的網站有 195 篇 AI 主題文章。SEO 慢慢做沒問題,但有一個更快的流量來源:讓 LLM 引用我

當有人在 ChatGPT 問「2026 有哪些 AI 教學網站?」,如果 ChatGPT 知道我的站,它會直接把我列出來。問題是:ChatGPT 怎麼會知道?

答案是 llms.txt 規範。這是社群提案的標準,讓網站像 robots.txt 一樣告訴 AI 爬蟲「我有什麼內容、在哪裡找」。目前 ChatGPT、Claude、Perplexity 都會抓這個檔案。

痛點:手動維護不可能

llms.txt 本身只是一份 Markdown 連結清單,寫一次很簡單:

# Mason AI Lab

> 中文 AI 知識站,涵蓋 195 篇教學與產業洞察。

## 學習入門
- [AI 新手村](https://masonailab.com/learn/beginners/)
- [Prompt 寫作入門](https://masonailab.com/learn/prompt-basics/)
...

每寫一篇新文章就要手動更新一次 llms.txt,這不是工程問題,是紀律問題——而我已經被自己騙過太多次了。任何需要紀律的事都會被遺忘

我需要一個會自動跑的東西。

解法:prebuild hook + 80 行 Node

Astro 的 package.json 支援 npm 的 prebuild 生命週期,意思是每次 npm run build 之前會自動跑這個腳本:

{
  "scripts": {
    "prebuild": "node scripts/gen-llms-full.mjs",
    "build": "astro build"
  }
}

這保證了只要我部署網站,llms-full.txt 就一定是最新的——不需要記得、不需要規律,完全自動。

腳本核心邏輯

import { readFileSync, writeFileSync, readdirSync, statSync } from 'node:fs';
import { join, relative, sep, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
const CONTENT_DIR = join(ROOT, 'src', 'content');
const SITE = 'https://masonailab.com';

// 1. 遞迴掃描所有 .md 檔
function walk(dir) {
  const out = [];
  for (const name of readdirSync(dir)) {
    const p = join(dir, name);
    const s = statSync(p);
    if (s.isDirectory()) out.push(...walk(p));
    else if (name.endsWith('.md')) out.push(p);
  }
  return out;
}

// 2. 解析 frontmatter,抽出 title / description / body
function parse(file) {
  const raw = readFileSync(file, 'utf8');
  const m = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
  if (!m) return null;
  // ... 抽 title, description, slug, section
}

// 3. 依分類排序、串接、寫檔
const articles = walk(CONTENT_DIR).map(parse).filter(Boolean);
articles.sort(/* 依 section 順序 */);

const out = articles.flatMap(a => [
  `## ${a.title}`,
  `Source: ${SITE}/${a.section}/${a.slug}/`,
  a.body,
  '---',
]).join('\n\n');

writeFileSync(join(ROOT, 'public/llms-full.txt'), out);

完整版 80 行,連 Windows 路徑空格的 bug 都處理了(fileURLToPath 別忘了)。

結果

[gen-llms-full] wrote 195 articles -> public/llms-full.txt (1096.7 KB)

每次 push 上 Cloudflare Pages,llms.txt 與 llms-full.txt 都是最新的。195 篇文章從此會自動出現在任何抓 llms.txt 的 AI 引擎裡

學到的事

  1. GEO(Generative Engine Optimization)和 SEO 是兩種戰場。SEO 等 Google 排名要 3-6 個月,GEO 是「我有沒有被 AI 看到」,可以即時生效。
  2. 靜態站的優勢被 AI 時代放大了。Astro 把所有內容變成 .md,讓全站索引變成 80 行腳本就能搞定的事——換成 WordPress 或 React SPA 會痛苦十倍。
  3. 任何需要紀律的事都應該被自動化。Prebuild hook 是被低估的工程實踐:零維護成本、零遺忘風險、隨 build 同步。
  4. llms.txt 不是銀彈,它只是讓 LLM「找得到」你。內容好不好、有沒有獨特觀點、能不能被引用,還是要自己寫。

接下來要做的事

  • 觀察 server log,看哪些 AI bot 真的在抓 llms.txt(GPTBot、ClaudeBot、PerplexityBot)
  • 為每篇文章加結構化的「TL;DR」區塊,讓 AI 引用時更容易截取重點
  • 寫一個監測腳本,定期問 ChatGPT「2026 中文 AI 教學網站有哪些?」,看我的站有沒有被列出來

原始碼在 scripts/gen-llms-full.mjs (連結待補)。歡迎 fork 改造成你的版本。