# 把六年的 WordPress 改成自架－免年費、超高自由度，完整 Prompt 分享

https://ijuhsu.com/posts/wordpress-to-astro-migration · 2026-07-05
Category: ai · Tags: astro, wordpress, migration, vercel, tools, claude-code

---

搬了三個月，但其實純搬站只要一週——我把完整 prompt 都留在這篇了。

這篇文章記錄我把 [ijuhsu.com](https://ijuhsu.com) 從 WordPress 搬到 Astro 的完整過程。從 2026 年 4 月開始有空就動工，7 月 4 日 DNS 切換完成，前後三個月含重新設計；但如果只是單純搬站不重新設計，一週內可以解決。

一共 260 篇文章、雙語（繁中＋英文）、自訂留言系統、800 多張圖片——如果你也想要脫離 Hosting 以及更大的自由度，希望這篇能幫你少走幾條彎路 ;)

> **門檻說明**：懂基本終端機操作（`cd`、`npm run`）就夠了，不需要會寫程式——Claude Code 負責所有程式碼，你負責判斷對不對。

<figure>
  ![ijuhsu.com 遊戲風首頁](https://res.cloudinary.com/dycjoye5f/image/upload/q_auto,f_auto/ijuhsu/wordpress-to-astro-migration-01)
  <figcaption>超自由，把首頁變成橫向圈軸遊戲！</figcaption>
</figure>

---

## 為什麼要搬？

[許 i 啾不認真](https://ijuhsu.com)這個網站出生於 2020 年，感謝 [Selena](https://yuntalks.com/about/) 當初教我怎麼透過 Wordpress 架站 :D  
原本用 A2 Hosting 的共享主機跑 WordPress，三年方案 $503 美金，2027 年 5 月到期；  
不過其實遇到了不少問題…
1. **費用** - $503 美金在當時是必要的費用，但現在 AI 時代來看，會去思考是否還有需要 Hosting 的必要
2. **龐大的外掛** - 我的外掛裝到 14 個——SEO、多語言、圖片壓縮、備份、防火牆、社群發文……每個外掛都有設定頁，互相衝突的問題三不五時就出現Q_Q 有時只是想改個版面樣式，卻要先搞清楚 OceanWP 主題覆蓋了哪些 CSS…
3. **自由度** - 仍然會有很多被 Wordpress 包住的限制

近來幾個用 AI 自己架站的 [Side Projects](https://ijuhsu.com/posts/remote-claude-code)，發現架站其實並不是那麼困難；  
尤其我的發文頻率低（:P），成本也超～級低，所以不禁起了自己架站的想法。  
和 Claude Code 討論了一陣子後，選擇了使用 Astro 為架構做了幾篇實測文－－靜態輸出 + Vercel 免費方案，幾乎零主機成本；  
也完美解決了我之前遇到的幾個問題，就開始找假日的時間來搬啦！

---

## 技術
以下是我目前架構起來後和 Claude Code 一起討論出來的內容，給大家參考：
- **Astro + Vercel**：靜態輸出部署到 Vercel，免費方案完全夠用。Astro 原生支援 MDX，content collection 讓文章管理乾淨，改版型只要改 `.astro` 元件和 CSS，不用碰任何後台設定；
- **Cloudinary**：圖片 CDN，自動轉 WebP、按尺寸裁切，不用在 Astro 裡跑 `<Image />` 轉檔。也定好命名規則，之後圖片管理清爽很多；
- **Supabase**：取代 WordPress 的留言系統，直接存進 PostgreSQL；補上了 Cloudflare 的認證機制來避免惡意留言；
- **Telegram Bot**：留言的核准／刪除／回覆全部透過 Telegram 按鈕操作，不需要建 admin 後台。

---

## 搬家流程
### Phase 0：架基礎
先請 Claude Code 協助將 Astro 的骨架搭起來再說。  
首先是設計，我其實也參考了不同的設計風格，不過因為我的需求是：有日常也有專業的內容，所以希望有兩套不同的 Design System 可以明顯看出兩者區別；  
同時我也希望保留我一點插畫風格，所以決定先以這種簡單的設計上架。
- Casual 日常路線，採用原本網站的色系設計並保有一些遊戲的元素，採用 non-serif 的字型；

<figure>
  ![Casual 日常風格設計](https://res.cloudinary.com/dycjoye5f/image/upload/q_auto,f_auto/ijuhsu/wordpress-to-astro-migration-02)
  <figcaption>選了比較簡單的字型，讓畫面簡單</figcaption>
</figure>

- Pro 專業路線，採用期刊風格，找個相關的色系（深綠）並搭配網格，採用 serif 的字型。

<figure>
  ![Pro 專業期刊風格設計](https://res.cloudinary.com/dycjoye5f/image/upload/q_auto,f_auto/ijuhsu/wordpress-to-astro-migration-03)
  <figcaption>配上網格，有種學術或專業期刊的風格:P</figcaption>
</figure>

另外則是網站架構，除了雙類型、雙設計外，也有雙語的設置（我許多遊戲攻略讀者是海外人士XD），因此也需要把 URL 結構弄好－－  
繁中預設無前綴，英文加 `/en/`，對 SEO 影響最大的決定都在這邊定好。

所有內容都是在 Claude Code 建好後 npm 驗證，push 上 Github，Vercel 就會自動 Deploy。

特別建議：
在一開始計畫時選較高的模型（我選 Fable 或 Opus），然後再請 Sonnet 執行，會快很多哦！

Claude Code Prompt（Phase 0）：
```
我要把 WordPress 部落格搬到 Astro。請幫我：
1. 建立 Astro 5 骨架，支援 MDX content collection
2. 設計雙語：繁中無前綴（/posts/slug），英文 /en/posts/slug
3. Layout：(自由決定)
4. 部署目標：Vercel 靜態輸出

先給我架構規劃與資料夾結構，確認後再開始寫程式。
```

### Phase 1：搬圖片
搬圖片本來以為是複雜的事情，沒想到比想像中簡單：845 張圖片，Claude Code 寫了一支 `migrate-images.mjs` 的腳本：

1. WP REST API 批次抓媒體庫
2. 直接用 URL 上傳到 Cloudinary（省掉下載再上傳的步驟）
3. 輸出 WP URL → Cloudinary public ID 的對照表

Claude Code Prompt（Phase 1）：
```
幫我寫 migrate-images.mjs，把 WordPress 媒體庫批次搬到 Cloudinary：
1. 用 WP REST API 逐頁抓所有圖片
2. 直接用圖片原始 URL 上傳到 Cloudinary（不需下載到本機）
3. 輸出 JSON 對照表

Cloudinary 命名規則：/{slug}-{nn}（nn 兩位數流水號）
WP 網址：https://my-site.com
Cloudinary 憑證從環境變數讀取（CLOUDINARY_CLOUD_NAME / API_KEY / API_SECRET）
```

大約一兩個小時全部跑完，共 845 張，842 張成功，3 張 404（WP 那邊的孤兒QQ），成功率很高，讚讚。

### Phase 2：轉 MDX
這也是靠 Claude Code 把六年來的 147 篇 WP 文章，寫了 `migrate-posts.mjs` 腳本（最終 260 篇是加上英文翻譯與 Astro 上線後新增的文章）：

1. WP REST API 抓 HTML 文章內容
2. HTML → Markdown（用 [turndown](https://github.com/mixmark-io/turndown)）
3. 替換圖片 URL → Cloudinary 格式
4. 輸出帶完整 frontmatter 的 MDX 檔案

Claude Code Prompt（Phase 2）：
```
幫我寫 migrate-posts.mjs，把 WordPress 文章批次轉成 Astro MDX：
1. WP REST API 逐頁抓所有文章
2. HTML 內容用 turndown 轉 Markdown
3. 圖片 URL 用 migrate-images 產生的對照表替換成 Cloudinary 格式
4. 輸出 MDX 含 frontmatter：title, description, pubDate, lang, slug, category

需清理：WP shortcode、[caption] 標籤、TOC 外掛殘留 HTML、Elementor markup
輸出路徑：src/content/posts/zh/
```

最麻煩的是 WP HTML 裡各種外掛殘留：shortcode、TOC 區塊、Elementor page builder markup，每種都要寫一條 regex 清掉。  
腳本跑完之後，還需要人工審查分類——最後有 50 篇重新分類。  
這目前仍有不少 legacy 需要調整，但大部分的文章都算穩定了

### Phase 3：翻譯補全
當初 WP 的英文文章很零散——有些在 zh 資料夾裡、有些有翻有些沒翻。  
全部整理好、補齊 126 篇的英文翻譯，用 `translate-zh-to-en` skill 輔助，每篇仍需人工確認——英文版由 AI 輔助翻譯，若發現問題歡迎留言告知。  
這比較要注意的是如果在翻譯的部分有需要特別標記的，例如：樂透要翻成「Lottery」，也要在 skills 都補上。

Claude Code Prompt（Phase 3）：
```
把 src/content/posts/zh/my-post.mdx 翻成英文 MDX，存到 src/content/posts/en/。
- translationKey 和 zh 版完全一致
- 語氣保持原文風格，不要過度正式化
- 專有名詞、工具名（Astro、Cloudinary 等）不翻
- 有特殊翻譯規則的詞先列出來（例：「樂透」→「Lottery」）
```

### Phase 4：留言移轉
一共有 326 筆 WP 留言，Claude Code 寫了 `migrate-wp-comments.mjs` 兩段式匯入：  
先插頂層留言、再插回覆（保留 parent_id 巢狀結構）。  
其實有些人家已經寫好的外掛，但有些只限 Github 帳號才能使用；我很多讀者都沒有；有些要付費。  
後來研究了一下便以 Supabase 為後端，把內容架，並加入 Cloudflare Turnstile 補強，這樣就可以省去許多惡意留言。  
我也補上了 Telegram 來通知我留言、審核留言並回覆留言的功能，這樣就不需要進後台處理了！
<figure>
  ![Supabase 留言系統畫面](https://res.cloudinary.com/dycjoye5f/image/upload/q_auto,f_auto/ijuhsu/wordpress-to-astro-migration-04)
  <figcaption>留言區很簡單也清爽，也可以符合整個頁面的風格！</figcaption>
</figure>

<figure>
  ![Telegram Bot 審核留言介面](https://res.cloudinary.com/dycjoye5f/image/upload/q_auto,f_auto/ijuhsu/wordpress-to-astro-migration-05)
  <figcaption>當有留言可以在 Telegram 自動審核</figcaption>
</figure>

Claude Code Prompt（Phase 4）：
```
幫我寫 migrate-wp-comments.mjs，把 WordPress 留言匯入 Supabase。
Supabase 資料表欄位：id, post_slug, parent_id, author_name, content, created_at, approved

流程：
1. WP REST API 抓所有已核准留言
2. 兩段式插入：先插頂層留言（parent=0），取得新 id 後再插回覆（對應 parent_id）
3. post_slug 從留言的 link 欄位解析

Supabase 連線從環境變數讀取（SUPABASE_URL、SUPABASE_SERVICE_KEY）
```

### Phase 5：SEO / Redirects
這一步很容易被跳過，但最重要。WP 的舊 URL 要全部 301 到新 URL，不然 Google 要重新爬，累積的排名白白損失 ;_;
Claude Code 幫我從文章清單程式化產出 262 條 redirect 規則，直接寫進 `astro.config.mjs`。
另外補了 JSON-LD schema、hreflang 互指、自訂 404、`llms.txt`。
P.s. 我還有自己架好的 404 頁面哦:D

Claude Code Prompt（Phase 5）：
```
我的 WP 舊 URL 格式有：(請自行列出)

新 URL 格式：/posts/{slug}（繁中），/en/posts/{slug}（英文）(請根據你的來修正)

請讀 src/content/posts/zh/*.mdx 的 frontmatter，
產生 astro.config.mjs 的 redirects 陣列，每篇文章的三種舊格式都要 301 對應到新 slug。
同時幫我補上：
- hreflang 互指（zh ↔ en）
- JSON-LD Article schema
- sitemap（@astrojs/sitemap）
- 自訂 404 頁面
```

### 正式搬家啦！DNS 切換
在大致都驗證好、也把該有的圖和內容補好後，2026/07/04 正式搬家啦！  
因為原本就有用 Cloudflare，就去刪掉 A2 Hosting 的 A record，改 CNAME 指向 Vercel，設 DNS only 讓 Vercel 自動簽 SSL。
切完之後記得手動更新兩件事：
1. Cloudflare Turnstile 的允許網域
2. Telegram webhook URL（`https://api.telegram.org/bot{TOKEN}/setWebhook`）
就可以正式上線了:D

### 上線後踩坑：Google 索引的舊 URL

以為設好 redirect 就沒事了，結果上線後發現 analytics 還是有 404——原因是 Google 搜尋結果裡存著 WP 時代的各種舊 URL，而這些不是只有「舊文章網址」而已。

幾個沒預期到的坑：

**1. WP 的 en slug 會自動加 `-2`**
WP 的機制是：中英文是兩篇獨立文章，如果 slug 一樣，後建的那篇會在後面補 `-2`。所以英文文章的 Google 索引 URL 可能長這樣：
```
/en/n8n-learningjapanese-2/   ← 不是 slug 本名，是 WP 自動加的
/en/phd2uxr-2/
```
這類 URL 有 130+ 篇，要全部補 redirect。

**2. WP 的特殊頁面和分類**
WP 的 tag 頁是 `/tag/:tag/`，Astro 我用的是 `/tags/:tag/`（多一個 s）；
聯絡頁是 `/contact/`，Astro 沒有，要導到 `/about/`；
舊分類頁 `/category/:cat/` 也要導到新的 `/:cat/`。

**怎麼找到漏網之魚？**
Google Search Console 的「未找到 (404)」報告是第一線；
另外在 Google 搜 `site:你的網域` 也能看到被索引的舊頁面，逐一比對是否還能正常打開。

最後我的 `vercel.json` 從預計的 262 條規則，補到了 844 條。設好 301 redirect 後，等 Google 爬蟲重訪，舊排名就會轉移到新 URL 了。

---

## 現在的架構

```
ijuhsu.com（Vercel，靜態 + serverless API）
├── 內容：~260 篇 MDX（zh + en）
├── 圖片：Cloudinary（自動 WebP + resize）
├── 留言：Supabase + Cloudflare Turnstile（防機器人）
├── 通知管理：Telegram Bot
└── 搜尋：Fuse.js 客戶端模糊搜尋
```

發文現在也有兩種流程：短文用 Telegram 發到 n8n → GitHub Actions 自動 commit 草稿 MDX（可見[聰明透透](https://ijuhsu.com/posts/remote-claude-code)這篇的流程，我把權限開到可以編輯文章！）；
<figure>
  ![Telegram 發文流程示意](https://res.cloudinary.com/dycjoye5f/image/upload/q_auto,f_auto/ijuhsu/wordpress-to-astro-migration-06)
  <figcaption>直接在 Telegram 也可以簡易發文！</figcaption>
</figure>
長文還是 Claude Code 一條龍（收稿 → 圖片上傳 → 事實查核 → 翻譯 → 上線）。

---

## 速度變快了多少？
之前的痛點就是 PageSpeed 數字一直很差，在 WP 想要改善都沒有什麼用；搬家後比較自由，一上線後就實測 PageSpeed Insights，電腦版：

| 指標 | WordPress 時期 | Astro + Vercel |
|------|---------------|----------------|
| PageSpeed 電腦版 | 無法重測（已下線）| **99 / 100** |
| PageSpeed 行動版 Lighthouse | 一直調不好（估計 30–50）| 55 / 100 |
| LCP 電腦版 | — | 0.9 秒 |
| FCP 電腦版 | — | 0.7 秒 |

行動版 Lighthouse 55 不夠理想，但背景是「慢速 4G 節流」模擬（1.6 Mbps），而且 CJK 字型（Noto TC）固有偏重；Claude Code 認為台灣用戶實際在 WiFi / 4G 上的體驗跟桌機接近，所以就大致維持這樣了。WP 時期在 A2 Hosting 共享主機跑的分數更低——PHP 處理時間 + 14 個外掛的 JS，加在一起更慘。
<figure>
  ![PageSpeed Insights 電腦版 99 分](https://res.cloudinary.com/dycjoye5f/image/upload/q_auto,f_auto/ijuhsu/wordpress-to-astro-migration-07)
  <figcaption>以前都在 40-50 分上下，現在看到 99 也太感人啦！</figcaption>
</figure>

搬到 Astro 後還做了幾項最佳化：
- Google Fonts 改非同步載入
- 文章內 Cloudinary 圖片補 srcset（480/800/1200/1600w）+ lazy loading
- 遊戲首頁 sprite PNG → WebP（3.2 MB → 560 KB）

這些都大大改善了網站的表現 :D

---

## 搬家值得嗎？

| 面向 | WordPress + A2 Hosting | Astro + Vercel |
|------|------------------------|----------------|
| 主機費用 | $503 美金 / 3 年 | 免費（Vercel Hobby） |
| 外掛依賴 | 14 個（SEO、備份、防火牆…） | 0 |
| 改版方式 | WP 後台 + 主題 CSS 覆寫 | 直接改 `.astro` 元件 |
| 部署流程 | FTP / WP 後台手動更新 | `git push` → 自動部署 |
| 文章儲存 | MySQL 資料庫 | MDX 純文字，git 版控 |
| 圖片處理 | WP 外掛（Smush 等） | Cloudinary 自動 WebP + resize |
| 留言管理 | WP 後台審核 | Telegram 按鈕一鍵核准 |
| PageSpeed 電腦版 | 估計 30–50（難調整） | **99 / 100** |
| PageSpeed 行動版 | 更差 | 55 / 100 |
| 自訂彈性 | 受主題與外掛限制 | 完全自由 |

省了超多的主機費用，網站設計及版型想改隨時改，不用再擔心外掛版本衝突；  
文章寫作沒有像之前那麼視覺化，因為就是 git 管的純文字檔；  
但是如果習慣 markdown 的寫作其實比上 WP 寫得更快。  
代價是工時——時長約三個月，但主要是因為我只是有空才搬（我方案明年才到期，而且也在忙其他的網站如[《LinguaPass》](https://linguapasstw.com) XD），  
Claude Code 我也是用 Pro 而已，只要 limit 一到我就跑去做別的事XD

如果你的文章只有 20–30 篇，直接用 [WordPress.com](https://wordpress.com) 真的就可以了；
但 260 篇、雙語、想要完全自訂——我覺得超值得，可以把樂透放得更多，完美XD。

---

## WP → Astro 搬家 Checklist

按照這個順序走，不容易漏掉東西：

**事前準備**
- [ ] 確定技術架構（Astro 版本、部署平台）
- [ ] 設計 URL 結構（語言前綴、slug 格式）——這個決定最難改，要先定好
- [ ] 申請 Cloudinary / Supabase 帳號（若要自架留言）、取得 API Key

**Phase 0：架基礎**
- [ ] Astro 骨架 + content collection schema
- [ ] 雙語路由設定
- [ ] Layout 元件（含雙設計系統如有）
- [ ] 部署到 Vercel，確認 CI/CD 流程跑通

**Phase 1：搬圖片**
- [ ] 寫腳本批次上傳 WP 媒體庫到 Cloudinary
- [ ] 輸出 WP URL → Cloudinary publicId 對照表
- [ ] 確認對照表完整（check 404 孤兒圖）

**Phase 2：轉文章**
- [ ] 寫腳本 WP REST API → turndown → MDX
- [ ] 清理外掛殘留（shortcode、Elementor markup、TOC HTML）
- [ ] 替換圖片 URL（用 Phase 1 的對照表）
- [ ] 人工審查分類，重新分配 category

**Phase 3：翻譯**
- [ ] 整理現有英文版，補齊 translationKey 配對
- [ ] 批次翻譯（Claude Code 輔助）
- [ ] 每篇人工確認語氣與專有名詞

**Phase 4：留言**
- [ ] 建立留言資料表（Supabase）
- [ ] 寫腳本兩段式匯入（先頂層、再回覆）
- [ ] 設定 Cloudflare Turnstile 防機器人
- [ ] 設定 Telegram Bot 審核通知

**Phase 5：SEO / Redirects**
- [ ] 程式化產生 301 redirect 規則（舊 WP URL → 新 slug）
- [ ] hreflang 互指標記（雙語）
- [ ] JSON-LD Article schema
- [ ] sitemap + robots.txt
- [ ] 自訂 404 頁面

**DNS 切換**
- [ ] 在新平台完整驗證（所有連結、圖片、留言）
- [ ] 刪除舊 A record，CNAME 指向 Vercel
- [ ] Cloudflare Turnstile 更新允許網域
- [ ] Telegram webhook URL 更新
- [ ] 確認 SSL 自動簽發

---

你也想要從 WP 轉成自架網站看看嗎？
有什麼搬家相關的問題歡迎留言，或是從[關於頁面](/about)找到我的 Facebook / LinkedIn 聯絡我 😊

p.s. 有人找得到網站中的小彩蛋嗎:p
<figure>
  ![首頁小遊戲——i 啾 & 樂透](https://res.cloudinary.com/dycjoye5f/image/upload/q_auto,f_auto/ijuhsu/wordpress-to-astro-migration-08)
  <figcaption>你可以拿到最高多少分呢？</figcaption>
</figure>