Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

👤 你:操作 Cloudflare 面板、設定 DNS🤖 AI:產出 config 檔案、檢查設定、警示潛在錯誤

先通車,再裝潢。 先讓網站可以上線,再回來寫頁面內容。否則做完 13 頁才發現部署壞了 = 浪費一整天。

所有站都用同一套流程部署。差別只在要不要加 OAuth Worker + Routes。

DNS 原理 — 知道為什麼才不會矇查

你買了 minglab.tw → 這只是一個名字,沒有人知道這名字指向哪裡。

瀏覽器打 minglab.tw
    ↓
DNS 查詢:minglab.tw 的 IP 是?
    ↓
Cloudflare 回答:在我這裡,我是 proxy
    ↓
Cloudflare 處理 HTTPS / CDN / DDoS → 把請求轉給你的靜態網站
    ↓
瀏覽器顯示網頁
情境做法為什麼
Cloudflare Pages(你的網站)用 Custom Domain 綁定,自動設 CNAMEPages 幫你處理 DNS,不用手動加 A 記錄
Cloudflare Worker(OAuth)用 Workers Routes,自動處理Worker 自己接 api/* 路徑
網域不在 Cloudflare 註冊去原註冊商把 nameserver 指向 CloudflareDNS 託管權要轉移到 Cloudflare
DNS 改了沒生效等 1-5 分鐘DNS 傳播有延遲,不是即時

最常見的 DNS 錯誤:A 記錄指向舊主機 IP 如果你在 Cloudflare DNS 面板看到 A 記錄 minglab.tw → 某個 IP,但網站是部署在 Pages 上 → 這兩者在打架 → 網站打不開。解法:刪掉 A 記錄,讓 Pages 的 Custom Domain 自己處理。

A.1 建立 Private Repo

  1. github.com/new
  2. Name:專案名稱
  3. Private
  4. 不要勾 Initialize with README
  5. Create → 記下網址
陷阱解法
名稱跟現有 repo 衝突換一個名字或用 -v2 後綴
忘了設 Private去 Settings → 改成 Private
不小心勾了 Initialize會產生 main 分支衝突 → 用 git pull --rebase 解決

A.2 SSH Key 設定(多帳號管理)

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N "" -C "信箱"
cat ~/.ssh/id_ed25519.pub

把輸出的內容貼到 github.com/settings/ssh/new

多帳號設定(如 gimmi520 + minglabtw):

# 第二組 Key
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_第二帳號 -N "" -C "第二信箱"
cat ~/.ssh/id_ed25519_第二帳號.pub
# 貼到第二個 GitHub 帳號的 Settings → SSH Keys
陷阱解法
SSH Host key verification failedssh-keyscan github.com >> ~/.ssh/known_hosts
推到舊帳號確認 git remote -v 的 URL 是 git@github.com:正確帳號/正確repo.git
兩個帳號的 SSH Key 衝突Git 預設只會用 id_ed25519。多帳號需要在 ~/.ssh/configHost github.com-第二帳號 並用 IdentityFile 指向不同的 Key
config.yml 的 repo: 寫錯帳號Sveltia CMS 靠 config.yml 決定內容存到哪個 repo。repo: gimmi520/minglab-website — 帳號跟 GitHub 上拼法必須完全一致(含大小寫、連字號)。見 [[#trouble-git-remote

A.3 Git Init + First Push

git init && git add . && git commit -m "初始版本"
git branch -M main
git remote add origin git@github.com:帳號/專案名.git
git push -u origin main
陷阱解法
remote origin already existsgit remote set-url origin git@github.com:新帳號/新repo.git
Push 被 reject(遠端有新 commit)git pull --rebase && git push
忘記 git init整個目錄重新來

A.4 Push 前檢查清單

# 1. 確認 git remote 推對帳號
git remote -v

# 2. 確認 config.yml repo 名稱正確
grep "repo:" public/admin/config.yml

# 3. 確認沒有殘留舊 GitHub Pages 部署檔
ls .github/workflows/deploy.yml 2>/dev/null && echo "❌ 多餘!應刪除" || echo "✅"

# 4. 確認 .gitignore 有排除 node_modules/dist/.astro
cat .gitignore

[[#table-of-contents|← 回目錄]]


Part B:本地 → GitHub(後台設定)

B.1 Sveltia CMS 檔案結構

public/admin/
├── index.html      ← Sveltia CMS 入口(CDN 載入)
└── config.yml      ← 所有 collection 定義

B.2 config.yml 完整範本

backend:
  name: github
  repo: gimmi520/專案名          # ⚙️ 改這裡
  branch: main
  base_url: https://你的網域      # ⚙️ 改這裡
  auth_endpoint: /api/auth
locale: 'zh_TW'
media_folder: "public/images"
public_folder: "/images"

collections:
  - name: "blog"
    label: "部落格"
    folder: "src/content/blog"
    create: true; extension: "md"; format: "frontmatter"
    fields:
      - { name: "title", label: "標題", widget: "string" }
      - { name: "body", label: "內文", widget: "markdown" }
陷阱解法
repo 名稱忘記改grep "repo:" public/admin/config.yml 檢查
YAML 縮排錯誤(fields: 跑掉)用 2 空格縮排,fields: 必須在 collection 下縮 4 格
create: false 讓 collection 消失Sveltia CMS 需要 create: true 才會顯示

B.3 index.html(CDN 載入)

<body>
  <script src="https://unpkg.com/@sveltia/cms/dist/sveltia-cms.js"></script>
  <div class="admin-btns">
    <a href="/admin-guide">?</a>
    <a href="/">🏠</a>
  </div>
</body>

B.4 Content .md 範例

每個 collection 的資料夾至少放一個 .md 範例,否則 Sveltia CMS 不會顯示該 collection。

src/content/blog/hello-world.md    ← 任何一篇初始文章
src/content/about/index.md         ← 關於我(至少一筆)

B.5 AGENTS.md + PROJECT_NOTES.md

# 專案名稱
## Stack
- Astro v6 + Tailwind CSS v4
- Sveltia CMS(CDN)
- Cloudflare Workers

## Dev commands
npm run dev      # http://localhost:4321
npm run build    # 輸出到 dist/

B.6 GitHub OAuth App 建立

步驟操作
1GitHub → Settings → Developer settings → OAuth Apps → New OAuth App
2Application name:專案名稱-cms
3Homepage URL:https://你的網域
4Authorization callback URL:https://你的網域/api/callback只放一個
5Register → 複製 Client ID + Client Secret

每個網站要有獨立的 OAuth App,不要共用。

陷阱解法
多個 callback URLGitHub 可能選錯,只用一個專屬該網域的 URL
Client Secret 洩漏只放進 oauth-worker/index.js,不要 commit 到 repo

B.7 建立 Token 登入(客戶第一次使用)

這是客戶登入後台的方式。做一次,瀏覽器記住,之後不用再貼。

你幫客戶做的(一次性)

操作說明
1GitHub → 右上頭像 → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new tokengithub.com/settings/tokens/new
2Note: 客戶名-網站名以後知道這個 Token 是誰的
3Expiration: No expiration客戶不會半年後突然被鎖
4勾選 repo + workflow這兩個就夠了
5Generate → 立刻複製(離開頁面後看不到)貼到 1Password / KeePass / LINE 存檔給客戶

客戶第一次用

操作
1打開 https://網站/admin/
2Token 按鈕
3貼上你給的 Token → 登入

之後瀏覽器會記住 Token(localStorage),下次打開 /admin/ 直接進後台,不用再貼。

[[#table-of-contents|← 回目錄]]


Part C:Cloudflare 部署(前台)

C.1 部署流程(所有站通用)

不管你網站有沒有 OAuth 登入,前面 5 步完全一樣。

做什麼說明
1👤GitHub 開 Private repo存放原始碼。忘了設 Private → 去 Settings 改成 Private
2👤GitHub → Settings → Applications → Cloudflare Pages → Repository access → 勾選新 repo每個新 repo 都要來一次。 漏掉 = Cloudflare 看不到
3👤Cloudflare → Workers & Pages → Create → Continue with GitHub → 選 repo → Deploy直接部署,不用改任何設定
4👤等 1-2 分鐘 → 確認網站正常打開 URL 看內容正確
5👤Custom Domain → 輸入 你的網域Cloudflare 自動建 DNS,不需進 DNS 面板

第 5 步之後:要不要加 OAuth

無 API / Token 登入有 API / OAuth 登入
下一步完成⚠️ 還要加以下
OAuth Worker❌ 不需要✅ 見 §D.1
Routes❌ 不需要✅ 見 §D.3
DNS❌ 已完成❌ 已完成(第 5 步自動處理)

Token vs OAuth — 選哪個

Token 登入OAuth 登入
部署後還要做什麼0 步,直接完成加 Worker + Routes
DNSCustom Domain 自動
客戶體驗貼 Token,瀏覽器記住點 GitHub
維護需維護 Client ID/Secret

預設走 Token。零額外設定。客戶不需要知道 GitHub 是什麼。

C.2 Custom Domain 詳解

為什麼不用手動設 DNS

Cloudflare 偵測到你輸入的網域(如 sop.minglab.tw)在你的帳號下 → 自動建 CNAME → 自動申請 HTTPS。你只需輸入網域、點 Add。

你做的事:輸入 `sop.minglab.tw` → 點 Add → 等 1-2 分鐘
Cloudflare 自動做的事:
  ① 檢查 minglab.tw DNS 在你帳號下 → 是
  ② 自動建 CNAME: sop → xxx.workers.dev
  ③ 自動申請 HTTPS 憑證
  ④ 生效

什麼時候才需要手動設 DNS

情況做法
網域在別的 Cloudflare 帳號下去原帳號設 CNAME 指向你的 xxx.workers.dev
網域剛從別處轉入 Cloudflare等 nameserver 生效再綁 Custom Domain
以上都不符合不用手動設任何東西

最常見的三個卡關點

#卡在哪原因解法
1Cloudflare 看不到 repoGitHub Applications 沒勾選新 repo回步驟 2
2Deploy 失敗(npx wrangler)Framework 被自動猜錯重新 Deploy → 手動設 Framework: None
3Custom Domain 綁不上去舊 DNS 記錄卡住刪掉舊記錄,等 1 分鐘再試

C.3 Build 設定

欄位⚠️
Framework presetNone← 關鍵!不要選 Astro
Build commandnpm run build
Build output directorydist
Deploy command(如有)留空

選 Astro 會強制跑 npx wrangler deploy → 需要 adapter → 失敗。

C.4 Connect GitHub → 自動部署

  1. Cloudflare → Workers & Pages → Create applicationContinue with GitHub
  2. 授權 → 選 repo → Begin setup
陷阱解法
Cloudflare Pages 找不到新 repo(最高頻率卡關)每開一個新 GitHub repo 都要來這裡:GitHub → 右上頭像 → Settings → Applications → Cloudflare Pages → Configure → Repository access → 搜尋新 repo → 勾選 → Save。沒勾 = Cloudflare 看不到 = 無法部署
點了 Continue with GitHub 直接跳到 Workersrepo 有舊 Workers 歷史 → 開新 repo

C.5 Custom Domain 綁定

Pages 專案 → Custom domains → 輸入網域 → Activate

C.6 HTTPS / SSL 確認

Cloudflare 自動配發 SSL 憑證。Proxy 必須開橘雲。

curl -sI https://你的網域 | grep HTTP
# HTTP/2 200 ← 正常

[[#table-of-contents|← 回目錄]]


Part D:OAuth 模式部署(模式 B 專用)

以下為模式 B(OAuth 登入)專用。如果你選 Token 登入(模式 A)或純展示(模式 C),Part D 整段跳過。

OAuth 模式總覽

順序做什麼在哪裡說明
1建主站git push → Cloudflare 自動部署你的 Astro 網站(npm run builddist/
2建 OAuth WorkerWorkers → Create → Start with Hello World!獨立 Worker,只處理 GitHub 登入
3貼程式碼Edit code → 貼 oauth-worker/index.js確認 Client ID + Secret 正確
4設 Routes網域/api/* → OAuth Worker / 網域/* → 主站api/ 必須在上面*
5Custom DomainDNS 自動處理輸入網域即可,Cloudflare 自動建 CNAME
6Custom Domain + HTTPSWorkers & Pages 設定等 1-2 分鐘

D.1 OAuth Worker 建立

  1. Workers & Pages → Create → Workers → 選 Start with Hello World!
  2. 名稱:專案名-oauth
  3. Deploy → Edit code
陷阱解法
❌ 選 Connect to Git會變成完整專案 → 跟主站衝突
✅ 選 Start with Hello World!獨立 Worker,只處理 OAuth

D.2 OAuth Worker 程式碼

# 複製模板中的 oauth-worker/index.js 全部內容
# 貼到 Cloudflare 編輯器
# 確認第 17-18 行的 Client ID + Secret 是正確的
陷阱解法
只按 Save 沒按 Deploy必須 SaveDeploySave and Deploy 兩個按鈕
Client ID 是舊的curl -sI https://網域/api/auth 檢查 client_id=

D.3 Workers Routes 設定

優先RouteWorker說明
1網域/api/*專案名-oauthOAuth 必須在上面
2網域/*專案名主站在下面
陷阱解法
api/* 指錯 Worker從另一個專案的 OAuth 複製時忘記改
api/* 放在 * 下面/api/callback 永遠被主站攔截 → OAuth 失敗

D.4 後台登入測試

測試網址預期
後台畫面https://網域/admin/Sveltia CMS 三個按鈕
OAuth 回呼https://網域/api/auth302 跳轉 GitHub 授權
Token 登入後台點 Token → 貼上 PAT進入 CMS 編輯頁面

D.5 Cloudflare API Token(給 OpenCode 代理用)

步驟操作
1dash.cloudflare.com/profile/api-tokensCreate Token
2Custom Token
Permissions
Account → Cloudflare PagesEdit
Account → Workers ScriptsEdit
User → User DetailsRead
  1. Account Resources → 選你的帳號 → Create

D.6 wrangler CLI 基本用法

# 登入驗證
CLOUDFLARE_API_TOKEN=你的token npx wrangler whoami

# 部署 Pages(靜態網站)
npx wrangler pages project create 專案名 --production-branch main
npx wrangler pages deploy dist/ --project-name=專案名

# 部署 Worker(API)
npx wrangler deploy --name worker名稱

[[#table-of-contents|← 回目錄]]


Part E:部署後驗證清單

E.1 全站頁面 200 檢查

# 每個頁面一條
for page in "" about contact products blog admin-guide; do
  curl -s -o /dev/null -w "%{http_code}" "https://網域/$page/"
  echo " /$page"
done

E.2 後台 CMS 可編輯

✅ /admin/ → 三個登入按鈕(GitHub / Token / Local)
✅ Token 登入 → 進入編輯頁面
✅ Collection 列表正確、可新增/編輯/刪除

E.3 OAuth 回呼正常

curl -sI https://網域/api/auth | grep -i location
# location: https://github.com/login/oauth/authorize?... ✅

E.4 聯絡表單 mailto 測試

填寫表單 → 點送出 → 應打開信箱 → 內容正確

E.5 手機版檢查

檢查重點
導航選單漢堡選單可開關
對比表卡片顯示不需左右滑
聯絡頁三張卡片 + 表單正常
按鈕不會被底部擋住

E.6 SEO 基礎檢查

curl -s https://網域/robots.txt
curl -s https://網域/sitemap-index.xml | head
curl -s https://網域/rss.xml | head