👤 你:操作 Cloudflare 面板、設定 DNS — 🤖 AI:產出 config 檔案、檢查設定、警示潛在錯誤
先通車,再裝潢。 先讓網站可以上線,再回來寫頁面內容。否則做完 13 頁才發現部署壞了 = 浪費一整天。
所有站都用同一套流程部署。差別只在要不要加 OAuth Worker + Routes。
你買了 minglab.tw → 這只是一個名字,沒有人知道這名字指向哪裡。
瀏覽器打 minglab.tw
↓
DNS 查詢:minglab.tw 的 IP 是?
↓
Cloudflare 回答:在我這裡,我是 proxy
↓
Cloudflare 處理 HTTPS / CDN / DDoS → 把請求轉給你的靜態網站
↓
瀏覽器顯示網頁
| 情境 | 做法 | 為什麼 |
| Cloudflare Pages(你的網站) | 用 Custom Domain 綁定,自動設 CNAME | Pages 幫你處理 DNS,不用手動加 A 記錄 |
| Cloudflare Worker(OAuth) | 用 Workers Routes,自動處理 | Worker 自己接 api/* 路徑 |
| 網域不在 Cloudflare 註冊 | 去原註冊商把 nameserver 指向 Cloudflare | DNS 託管權要轉移到 Cloudflare |
| DNS 改了沒生效 | 等 1-5 分鐘 | DNS 傳播有延遲,不是即時 |
最常見的 DNS 錯誤:A 記錄指向舊主機 IP
如果你在 Cloudflare DNS 面板看到 A 記錄 minglab.tw → 某個 IP,但網站是部署在 Pages 上 → 這兩者在打架 → 網站打不開。解法:刪掉 A 記錄,讓 Pages 的 Custom Domain 自己處理。
- github.com/new
- Name:
專案名稱
- 選 Private
- 不要勾 Initialize with README
- Create → 記下網址
| 陷阱 | 解法 |
| 名稱跟現有 repo 衝突 | 換一個名字或用 -v2 後綴 |
| 忘了設 Private | 去 Settings → 改成 Private |
| 不小心勾了 Initialize | 會產生 main 分支衝突 → 用 git pull --rebase 解決 |
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 failed | ssh-keyscan github.com >> ~/.ssh/known_hosts |
| 推到舊帳號 | 確認 git remote -v 的 URL 是 git@github.com:正確帳號/正確repo.git |
| 兩個帳號的 SSH Key 衝突 | Git 預設只會用 id_ed25519。多帳號需要在 ~/.ssh/config 加 Host github.com-第二帳號 並用 IdentityFile 指向不同的 Key |
config.yml 的 repo: 寫錯帳號 | Sveltia CMS 靠 config.yml 決定內容存到哪個 repo。repo: gimmi520/minglab-website — 帳號跟 GitHub 上拼法必須完全一致(含大小寫、連字號)。見 [[#trouble-git-remote |
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 exists | git remote set-url origin git@github.com:新帳號/新repo.git |
| Push 被 reject(遠端有新 commit) | git pull --rebase && git push |
忘記 git init | 整個目錄重新來 |
# 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|← 回目錄]]
public/admin/
├── index.html ← Sveltia CMS 入口(CDN 載入)
└── config.yml ← 所有 collection 定義
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 才會顯示 |
<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>
每個 collection 的資料夾至少放一個 .md 範例,否則 Sveltia CMS 不會顯示該 collection。
src/content/blog/hello-world.md ← 任何一篇初始文章
src/content/about/index.md ← 關於我(至少一筆)
# 專案名稱
## Stack
- Astro v6 + Tailwind CSS v4
- Sveltia CMS(CDN)
- Cloudflare Workers
## Dev commands
npm run dev # http://localhost:4321
npm run build # 輸出到 dist/
| 步驟 | 操作 |
| 1 | GitHub → Settings → Developer settings → OAuth Apps → New OAuth App |
| 2 | Application name:專案名稱-cms |
| 3 | Homepage URL:https://你的網域 |
| 4 | Authorization callback URL:https://你的網域/api/callback(只放一個) |
| 5 | Register → 複製 Client ID + Client Secret |
每個網站要有獨立的 OAuth App,不要共用。
| 陷阱 | 解法 |
| 多個 callback URL | GitHub 可能選錯,只用一個專屬該網域的 URL |
| Client Secret 洩漏 | 只放進 oauth-worker/index.js,不要 commit 到 repo |
這是客戶登入後台的方式。做一次,瀏覽器記住,之後不用再貼。
| 步 | 操作 | 說明 |
| 1 | GitHub → 右上頭像 → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token | github.com/settings/tokens/new |
| 2 | Note: 客戶名-網站名 | 以後知道這個 Token 是誰的 |
| 3 | Expiration: No expiration | 客戶不會半年後突然被鎖 |
| 4 | 勾選 repo + workflow | 這兩個就夠了 |
| 5 | Generate → 立刻複製(離開頁面後看不到) | 貼到 1Password / KeePass / LINE 存檔給客戶 |
| 步 | 操作 |
| 1 | 打開 https://網站/admin/ |
| 2 | 點 Token 按鈕 |
| 3 | 貼上你給的 Token → 登入 |
之後瀏覽器會記住 Token(localStorage),下次打開 /admin/ 直接進後台,不用再貼。
[[#table-of-contents|← 回目錄]]
不管你網站有沒有 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 面板 |
| 無 API / Token 登入 | 有 API / OAuth 登入 |
| 下一步 | ✅ 完成 | ⚠️ 還要加以下 |
| OAuth Worker | ❌ 不需要 | ✅ 見 §D.1 |
| Routes | ❌ 不需要 | ✅ 見 §D.3 |
| DNS | ❌ 已完成 | ❌ 已完成(第 5 步自動處理) |
| Token 登入 | OAuth 登入 |
| 部署後還要做什麼 | 0 步,直接完成 | 加 Worker + Routes |
| DNS | Custom Domain 自動 | 同 |
| 客戶體驗 | 貼 Token,瀏覽器記住 | 點 GitHub |
| 維護 | 零 | 需維護 Client ID/Secret |
預設走 Token。零額外設定。客戶不需要知道 GitHub 是什麼。
Cloudflare 偵測到你輸入的網域(如 sop.minglab.tw)在你的帳號下 → 自動建 CNAME → 自動申請 HTTPS。你只需輸入網域、點 Add。
你做的事:輸入 `sop.minglab.tw` → 點 Add → 等 1-2 分鐘
Cloudflare 自動做的事:
① 檢查 minglab.tw DNS 在你帳號下 → 是
② 自動建 CNAME: sop → xxx.workers.dev
③ 自動申請 HTTPS 憑證
④ 生效
| 情況 | 做法 |
| 網域在別的 Cloudflare 帳號下 | 去原帳號設 CNAME 指向你的 xxx.workers.dev |
| 網域剛從別處轉入 Cloudflare | 等 nameserver 生效再綁 Custom Domain |
| 以上都不符合 | 不用手動設任何東西 |
| # | 卡在哪 | 原因 | 解法 |
| 1 | Cloudflare 看不到 repo | GitHub Applications 沒勾選新 repo | 回步驟 2 |
| 2 | Deploy 失敗(npx wrangler) | Framework 被自動猜錯 | 重新 Deploy → 手動設 Framework: None |
| 3 | Custom Domain 綁不上去 | 舊 DNS 記錄卡住 | 刪掉舊記錄,等 1 分鐘再試 |
| 欄位 | 值 | ⚠️ |
| Framework preset | None | ← 關鍵!不要選 Astro |
| Build command | npm run build | |
| Build output directory | dist | |
| Deploy command(如有) | 留空 | |
選 Astro 會強制跑 npx wrangler deploy → 需要 adapter → 失敗。
- Cloudflare → Workers & Pages → Create application → Continue with GitHub
- 授權 → 選 repo → Begin setup
| 陷阱 | 解法 |
| Cloudflare Pages 找不到新 repo(最高頻率卡關) | 每開一個新 GitHub repo 都要來這裡:GitHub → 右上頭像 → Settings → Applications → Cloudflare Pages → Configure → Repository access → 搜尋新 repo → 勾選 → Save。沒勾 = Cloudflare 看不到 = 無法部署 |
| 點了 Continue with GitHub 直接跳到 Workers | repo 有舊 Workers 歷史 → 開新 repo |
Pages 專案 → Custom domains → 輸入網域 → Activate
Cloudflare 自動配發 SSL 憑證。Proxy 必須開橘雲。
curl -sI https://你的網域 | grep HTTP
# HTTP/2 200 ← 正常
[[#table-of-contents|← 回目錄]]
以下為模式 B(OAuth 登入)專用。如果你選 Token 登入(模式 A)或純展示(模式 C),Part D 整段跳過。
| 順序 | 做什麼 | 在哪裡 | 說明 |
| 1 | 建主站 | git push → Cloudflare 自動部署 | 你的 Astro 網站(npm run build → dist/) |
| 2 | 建 OAuth Worker | Workers → Create → Start with Hello World! | 獨立 Worker,只處理 GitHub 登入 |
| 3 | 貼程式碼 | Edit code → 貼 oauth-worker/index.js | 確認 Client ID + Secret 正確 |
| 4 | 設 Routes | 網域/api/* → OAuth Worker / 網域/* → 主站 | api/ 必須在上面* |
| 5 | Custom Domain | DNS 自動處理 | 輸入網域即可,Cloudflare 自動建 CNAME |
| 6 | Custom Domain + HTTPS | Workers & Pages 設定 | 等 1-2 分鐘 |
- Workers & Pages → Create → Workers → 選 Start with Hello World!
- 名稱:
專案名-oauth
- Deploy → Edit code
| 陷阱 | 解法 |
| ❌ 選 Connect to Git | 會變成完整專案 → 跟主站衝突 |
| ✅ 選 Start with Hello World! | 獨立 Worker,只處理 OAuth |
# 複製模板中的 oauth-worker/index.js 全部內容
# 貼到 Cloudflare 編輯器
# 確認第 17-18 行的 Client ID + Secret 是正確的
| 陷阱 | 解法 |
| 只按 Save 沒按 Deploy | 必須 Save → Deploy → Save and Deploy 兩個按鈕 |
| Client ID 是舊的 | curl -sI https://網域/api/auth 檢查 client_id= |
| 優先 | Route | Worker | 說明 |
| 1 | 網域/api/* | 專案名-oauth | OAuth 必須在上面 |
| 2 | 網域/* | 專案名 | 主站在下面 |
| 陷阱 | 解法 |
api/* 指錯 Worker | 從另一個專案的 OAuth 複製時忘記改 |
api/* 放在 * 下面 | /api/callback 永遠被主站攔截 → OAuth 失敗 |
| 測試 | 網址 | 預期 |
| 後台畫面 | https://網域/admin/ | Sveltia CMS 三個按鈕 |
| OAuth 回呼 | https://網域/api/auth | 302 跳轉 GitHub 授權 |
| Token 登入 | 後台點 Token → 貼上 PAT | 進入 CMS 編輯頁面 |
| Permissions | 值 |
| Account → Cloudflare Pages | Edit |
| Account → Workers Scripts | Edit |
| User → User Details | Read |
- Account Resources → 選你的帳號 → Create
# 登入驗證
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|← 回目錄]]
# 每個頁面一條
for page in "" about contact products blog admin-guide; do
curl -s -o /dev/null -w "%{http_code}" "https://網域/$page/"
echo " /$page"
done
✅ /admin/ → 三個登入按鈕(GitHub / Token / Local)
✅ Token 登入 → 進入編輯頁面
✅ Collection 列表正確、可新增/編輯/刪除
curl -sI https://網域/api/auth | grep -i location
# location: https://github.com/login/oauth/authorize?... ✅
填寫表單 → 點送出 → 應打開信箱 → 內容正確
| 檢查 | 重點 |
| 導航選單 | 漢堡選單可開關 |
| 對比表 | 卡片顯示不需左右滑 |
| 聯絡頁 | 三張卡片 + 表單正常 |
| 按鈕 | 不會被底部擋住 |
curl -s https://網域/robots.txt
curl -s https://網域/sitemap-index.xml | head
curl -s https://網域/rss.xml | head