AI Agent Publish Workflow:Markdown 到公開網頁
這份文件抽出目前 publish-note 流程中的「發布層」。目標是讓另一個 AI agent 能把一份 Markdown 文件轉成公開網頁,並用可重複、可更新、可下架的方式部署到 Cloudflare Pages。
本文只涵蓋通用流程:Markdown source、HTML conversion、static build、registry、Cloudflare deploy。筆記軟體專屬語法與圖表前處理不在這份規格內。
目標行為
Agent 接到「publish this document」時,應完成以下事情:
- 找到來源 Markdown 檔。
- 產生穩定、可讀、英文小寫的 URL slug。
- 將 Markdown 轉成
build/<slug>/index.html。 - 更新發布 registry。
- 只部署固定的 static build directory。
- 回報公開 URL。
成功後的 URL 形式:
https://<cloudflare-pages-project>.pages.dev/<slug>
元件
1. Source Markdown
來源是一個 .md 檔案。建議支援 YAML frontmatter:
---
title: Example Document
tags: [strategy, reference]
---
# Example Document
Body content...
標題解析優先序:
- frontmatter
title - 第一個 H1
- 檔名去掉副檔名
2. HTML Template
用一個 HTML template 包住轉換後的 body。template 至少需要這些 placeholder:
{{TITLE}}
{{DATE}}
{{TAGS}}
{{CONTENT}}
converter 將 Markdown body 轉成 HTML,再把內容注入 template。
3. Build Directory
所有公開頁面都輸出到同一個 static build directory:
build/
├── images/
├── <slug>/
│ └── index.html
├── index.html
└── 404.html
每篇文章使用 directory-style page:build/<slug>/index.html。公開網址因此是 /<slug>,而不是 /<slug>.html。
4. Registry
registry 是發布狀態的 source of truth。建議格式:
{
"project": "cloudflare-project-name",
"base_url": "https://cloudflare-project-name.pages.dev",
"notes": [
{
"slug": "example-document",
"source": "notes/example.md",
"title": "Example Document",
"url": "https://cloudflare-project-name.pages.dev/example-document",
"published_at": "2026-05-07T00:00:00Z",
"updated_at": "2026-05-07T00:00:00Z",
"status": "active"
}
]
}
status 只需要兩種:
active
removed
下架時不要直接刪 registry entry,將 status 改成 removed,保留歷史。
5. Deploy Wrapper
Cloudflare deploy 必須走 wrapper script,不要讓 agent 任意執行 raw deploy。wrapper 負責:
- 驗證 slug。
- 驗證 build directory 是允許部署的目錄。
- 更新 registry。
- 重新產生
index.html。 - 重新產生
404.html。 - 呼叫 Cloudflare Pages deploy。
- 輸出最終 URL。
Slug 規則
slug 必須:
- 英文小寫。
- 只含
a-z、0-9、-。 - 以英數字開頭。
- 盡量 3-5 個字。
- 同一個 project 內唯一。
驗證 regex:
^[a-z0-9][a-z0-9-]*$
例子:
ai-agent-publish-workflow
forest-growth-plan
strategy-review-2026
一次性設定
需要安裝:
npm install -g wrangler
需要登入 Cloudflare:
wrangler login
第一次建立 Pages project:
wrangler pages project create <cloudflare-pages-project>
需要本機有:
node
jq
wrangler
Publish 新文件
設定變數:
SOURCE_PATH="notes/example.md"
SOURCE_RELATIVE_PATH="notes/example.md"
SLUG="example-document"
TITLE="Example Document"
SOURCE_ROOT="notes"
BUILD_DIR="published/build"
REGISTRY_PATH="published/registry.json"
TEMPLATE_PATH="template.html"
CONVERT_SCRIPT="convert.mjs"
DEPLOY_SCRIPT="deploy.sh"
CF_PROJECT="cloudflare-project-name"
步驟一:轉換 Markdown 到 HTML。
node "$CONVERT_SCRIPT" \
"$SOURCE_PATH" \
"$SLUG" \
"$BUILD_DIR" \
"$SOURCE_ROOT" \
"$TEMPLATE_PATH" \
"$REGISTRY_PATH"
預期產物:
published/build/<slug>/index.html
步驟二:發布。
REGISTRY_PATH="$REGISTRY_PATH" \
BUILD_DIR="$BUILD_DIR" \
CF_PROJECT="$CF_PROJECT" \
bash "$DEPLOY_SCRIPT" publish "$SLUG" "$SOURCE_RELATIVE_PATH" "$TITLE"
Agent 回報時至少包含:
Published: https://<cloudflare-pages-project>.pages.dev/<slug>
Update 已發布文件
更新要重新轉換,再呼叫 deploy wrapper 的 update:
node "$CONVERT_SCRIPT" \
"$SOURCE_PATH" \
"$SLUG" \
"$BUILD_DIR" \
"$SOURCE_ROOT" \
"$TEMPLATE_PATH" \
"$REGISTRY_PATH"
REGISTRY_PATH="$REGISTRY_PATH" \
BUILD_DIR="$BUILD_DIR" \
CF_PROJECT="$CF_PROJECT" \
bash "$DEPLOY_SCRIPT" update "$SLUG" "$SOURCE_RELATIVE_PATH" "$TITLE"
update 應:
- 保持同一個 URL。
- 更新
updated_at。 - 將
status設為active。 - 重新部署整個 build directory。
List 已發布文件
REGISTRY_PATH="$REGISTRY_PATH" \
BUILD_DIR="$BUILD_DIR" \
bash "$DEPLOY_SCRIPT" list
只列出 status = active 的項目。
Unpublish 下架
REGISTRY_PATH="$REGISTRY_PATH" \
BUILD_DIR="$BUILD_DIR" \
CF_PROJECT="$CF_PROJECT" \
bash "$DEPLOY_SCRIPT" unpublish "$SLUG"
unpublish 應:
- 刪除
build/<slug>/。 - 兼容刪除舊式
build/<slug>.html。 - 將 registry 裡該 slug 的
status改成removed。 - 更新
updated_at。 - 重新產生
index.html和404.html。 - 重新部署。
安全規則
Agent 必須遵守:
- 只部署 static build directory。
- 不要部署 repo root、home directory、temporary directory 或任意工作目錄到正式 project。
- 正式 project 應綁定 canonical
BUILD_DIR和REGISTRY_PATH,wrapper 需驗證路徑。 - 所有 publish / update / unpublish 都必須經過 deploy wrapper。
- 不要把秘密、token、private config 放進 build directory。
- 每次 deploy 前確認
build/<slug>/index.html存在。 - 每次 deploy 都產生
404.html,避免不存在路徑 fallback 到首頁或其他內容。
Agent Checklist
發布前:
- Source Markdown 存在。
- Title 已確認。
- Slug 符合 regex 且沒有衝突。
- Converter 成功產生
build/<slug>/index.html。 - Registry JSON 可被
jq解析。 - Build directory 沒有不該公開的檔案。
發布後:
- Wrapper 回傳成功。
- Registry 有 active entry。
- Public URL 可回報給使用者。
- 若有 git 工作流,將 source、build output、registry 一起提交。
最小實作心法
這個流程的關鍵不是 Cloudflare 指令本身,而是「把發布變成受控狀態轉移」:
Markdown source
-> convert to deterministic static page
-> update registry
-> deploy only the approved build directory
-> report stable URL
只要保住這個 contract,其他 agent 就能安全地重複 publish、update、list、unpublish,而不會把錯的資料夾發布到公開網路上。