為何選擇 Next.js 搭配 Headless Ghost CMS?
在現代網站開發的浪潮中,Headless CMS 架構因其靈活性、效能和可擴展性而備受推崇。Ghost 作為一個功能強大且專注於內容的 CMS,採用 Headless 模式可以讓您將其卓越的內容管理功能與任何前端框架結合。Next.js 作為領先的 React 框架,以其伺服器端渲染 (SSR)、靜態網站生成 (SSG)、優化的圖片處理和卓越的開發體驗而聞名。
將 Ghost 作為 Headless CMS,並選擇 Next.js 建構前端,再部署於高效能平台 Vercel,您可以獲得以下優勢:
- 極致效能:Next.js 的 SSG 和 SSR 功能可顯著提升載入速度和 SEO 表現。
- 開發彈性:完全掌控前端的技術棧和使用者體驗。
- 現代化工作流程:利用 React 生態系統和 Next.js 的先進功能。
- 無縫部署:Vercel 提供與 Next.js 的完美整合,簡化部署流程。
然而,從現有的 Ghost 主題(通常基於 Handlebars 模板引擎)遷移到 Next.js(基於 React)可能是一項繁瑣的任務。這正是 AI 輔助工具 Cursor 發揮作用的地方。Cursor 能夠理解程式碼上下文,並根據自然語言指令生成、編輯和重構程式碼,大幅加速轉換過程。
準備工作:開始轉換前的必要條件
在我們深入探討使用 Cursor 轉換的步驟之前,請確保您已具備以下條件:
- Node.js 與 npm/yarn:確保您的開發環境已安裝最新穩定版的 Node.js 和套件管理器(npm 或 yarn)。
- Cursor 編輯器:下載並安裝 Cursor AI 編輯器。熟悉其基本操作介面,特別是 AI 聊天和程式碼生成功能。
- Ghost CMS 主題檔案:準備好您想要轉換的 Ghost 主題的完整原始碼檔案(通常包含
.hbs
檔案、CSS/JS 檔案、圖片等)。 - 基本的 Next.js 知識:對 Next.js 的專案結構、元件、路由和資料獲取方法(
getStaticProps
,getServerSideProps
)有基本了解。 - Ghost Content API 金鑰:登入您的 Ghost 管理後台,前往 Integrations,建立一個新的 Custom Integration,並取得 Content API Key 和 API URL。這是 Next.js 前端獲取內容所必需的。
- 版本控制 (Git):強烈建議使用 Git 進行版本控制,以便追蹤變更並在需要時回滾。
步驟一:初始化 Next.js 專案
首先,我們需要建立一個新的 Next.js 專案作為轉換後程式碼的基礎。
打開您的終端機(Terminal),執行以下指令(我們推薦使用 create-next-app
):
npx create-next-app@latest my-headless-ghost-frontend --typescript
# 或如果您偏好 JavaScript:
# npx create-next-app@latest my-headless-ghost-frontend
這將建立一個名為 my-headless-ghost-frontend
的新資料夾,其中包含基本的 Next.js 專案結構。進入該目錄:
cd my-headless-ghost-frontend
接著,使用 Cursor 打開這個新建立的專案資料夾。
步驟二:在 Cursor 中設定轉換環境
在 Cursor 中打開您的 Next.js 專案後,我們可以開始利用其 AI 功能。
- 熟悉介面:確保您知道如何與 Cursor 的 AI 互動,例如透過
Cmd+K
(Mac) 或Ctrl+K
(Windows/Linux) 來編輯選定程式碼,或使用側邊欄的聊天功能進行更廣泛的查詢和程式碼生成。 - 導入 Ghost 主題檔案:將您準備好的 Ghost 主題檔案複製到 Next.js 專案中的某個臨時資料夾(例如,
ghost-theme-source
),以便在 Cursor 中輕鬆存取和參考。
步驟三:核心轉換 - 將 Handlebars (.hbs) 轉換為 React 元件 (.jsx/.tsx)
這是轉換過程中最關鍵的部分。Ghost 主題使用 Handlebars (.hbs
) 檔案來定義頁面結構和模板。我們需要將這些檔案轉換為 Next.js 使用的 React 元件(.jsx
或 .tsx
)。
-
識別主要佈局檔案:在您的 Ghost 主題中,通常會有一個主要的佈局檔案(例如
default.hbs
),它定義了網站的整體結構(頁首、頁尾、主要內容區域)。 -
在 Cursor 中轉換
default.hbs
:- 在 Next.js 專案中,建立一個
components
資料夾,並在其中建立一個Layout.tsx
(或.jsx
) 檔案。 - 打開
ghost-theme-source/default.hbs
檔案。 - 選取
default.hbs
的全部或部分內容。 - 按下
Cmd+K
/Ctrl+K
,然後輸入類似以下的 AI 指令:“將這段 Handlebars 程式碼轉換為一個名為
Layout
的 React functional component (使用 TypeScript 和 JSX)。將{{{body}}}
替換為children
prop。保留 HTML 結構和 CSS class。” - Cursor 將會生成對應的 React 元件程式碼。仔細檢查生成的程式碼,可能需要手動調整,特別是 Handlebars 的特定 helpers 或 partials。例如,
{{@site.title}}
或{{navigation}}
需要後續透過 Ghost Content API 獲取資料來填充。
- 在 Next.js 專案中,建立一個
-
轉換其他模板檔案 (index.hbs, post.hbs, page.hbs 等):
- 根據 Next.js 的路由規則,在
pages
資料夾下建立對應的檔案。例如:index.hbs
→pages/index.tsx
post.hbs
→pages/posts/[slug].tsx
(動態路由)page.hbs
→pages/[slug].tsx
(或根據您的 URL 結構調整)
- 對於每個
.hbs
檔案,重複上述轉換過程:選取 Handlebars 程式碼,使用 Cursor AI (Cmd+K / Ctrl+K) 進行轉換。 - 範例 AI 指令 (針對
post.hbs
):“將此 Handlebars 模板轉換為一個 React functional component,用於顯示單篇文章。假設文章資料將透過 props 傳入 (例如
props.post
)。將 Handlebars 變數如{{title}}
,{{html}}
,{{primary_author.name}}
替換為對應的 prop access (例如props.post.title
,props.post.html
,props.post.primary_author.name
)。” - 處理 Handlebars Helpers:對於 Handlebars 的內建 helpers(如
#if
,#each
)或自訂 helpers,您需要特別指示 Cursor 如何轉換:{{#if condition}}...{{/if}}
: 可以轉換為 JSX 中的條件渲染({condition && ...}
或condition ? ... : ...
)。- AI 指令:“將這個
{{#if}}
區塊轉換為 JSX 條件渲染。”
- AI 指令:“將這個
{{#each collection}}...{{/each}}
: 可以轉換為 JavaScript 的.map()
方法。- AI 指令:“將這個
{{#each posts}}
迴圈轉換為使用posts.map(...)
的 JSX 列表渲染,確保為每個元素提供唯一的key
prop。”
- AI 指令:“將這個
- Partials (
{{> partial-name}}
): 需要將對應的 partial (_partial-name.hbs
) 也轉換為一個獨立的 React 元件,然後在主元件中導入並使用。- AI 指令 (轉換 partial):“將此 Handlebars partial 轉換為一個名為
PartialName
的 React functional component。” - AI 指令 (在主元件中使用):“在此處導入並使用
PartialName
元件,替換{{> partial-name}}
。”
- AI 指令 (轉換 partial):“將此 Handlebars partial 轉換為一個名為
- 根據 Next.js 的路由規則,在
-
迭代與修正:AI 生成的程式碼不一定是完美的。您需要仔細審閱、測試並修正 Cursor 生成的 React 元件,確保它們的功能和結構符合預期。Cursor 的 AI 也可以協助修正錯誤或重構程式碼(例如,選取有問題的程式碼,按
Cmd+K
/Ctrl+K
,描述問題或期望的修改)。
步驟四:整合 Ghost Content API 以獲取資料
轉換後的 Next.js 元件現在是靜態的結構。我們需要從 Headless Ghost CMS 獲取實際內容。這通常在 Next.js 的頁面檔案中使用 getStaticProps
(用於 SSG) 或 getServerSideProps
(用於 SSR) 來完成。
-
安裝 Ghost Content API SDK:
npm install @tryghost/content-api # 或 yarn add @tryghost/content-api
-
在頁面中獲取資料:以
pages/index.tsx
(首頁) 為例:- 導入 API SDK。
- 在檔案底部添加
getStaticProps
函數。 - 使用您的 API URL 和 Content API Key 初始化 SDK。
- 調用 SDK 的方法(例如
api.posts.browse()
)來獲取文章列表。 - 將獲取的資料透過
props
返回給頁面元件。
使用 Cursor 輔助生成
getStaticProps
:- 在
pages/index.tsx
文件中,您可以透過 Cursor 的聊天或Cmd+K
/Ctrl+K
功能請求生成程式碼。 - 範例 AI 指令:
“為這個 Next.js 頁面元件生成
getStaticProps
函數 (使用 TypeScript)。導入@tryghost/content-api
,使用環境變數GHOST_API_URL
和GHOST_CONTENT_API_KEY
初始化 API。獲取最新的 10 篇文章 (posts),包含作者 (author) 和標籤 (tags) 資訊。將文章列表作為posts
prop 返回。” - Cursor 將生成包含 API 調用邏輯的
getStaticProps
函數。您需要確保已在環境變數 (.env.local
) 中設定GHOST_API_URL
和GHOST_CONTENT_API_KEY
。
-
在元件中使用資料:修改您的 React 元件,使其接收並顯示從
getStaticProps
傳來的props
。例如,在IndexPage
元件中接收posts
prop,並使用.map()
渲染文章列表。 -
處理動態路由 (例如
pages/posts/[slug].tsx
):- 您需要額外實現
getStaticPaths
來告訴 Next.js 需要預先生成哪些文章頁面。這通常涉及調用 Ghost Content API 獲取所有文章的slug
。 - 在
getStaticProps
中,根據傳入的params.slug
獲取特定文章的詳細內容。 - Cursor AI 指令範例 (用於
getStaticPaths
):“為這個動態路由頁面
[slug].tsx
生成getStaticPaths
函數。使用@tryghost/content-api
獲取所有已發布文章的slug
,並將它們格式化為paths
陣列返回。設定fallback: 'blocking'
(或true
/false
根據需求)。” - Cursor AI 指令範例 (用於
getStaticProps
for dynamic route):“為這個動態路由頁面
[slug].tsx
生成getStaticProps
函數。從context.params
獲取slug
。使用@tryghost/content-api
根據slug
獲取單篇文章的詳細內容 (包含html
欄位)。將文章資料作為post
prop 返回。”
- 您需要額外實現
步驟五:遷移樣式 (CSS/Sass)
您的 Ghost 主題通常包含 CSS 或 Sass 檔案來定義外觀。將這些樣式應用到 Next.js 專案中有多種方式:
- 全域 CSS:將主要的 CSS 檔案(通常在 Ghost 主題的
assets/css
目錄下)複製到 Next.js 的styles
資料夾中,並在pages/_app.tsx
中導入。這是最簡單直接的方法,但可能導致全域命名衝突。// pages/_app.tsx import '../styles/global.css'; // 導入您的 CSS 檔案 import type { AppProps } from 'next/app'; function MyApp({ Component, pageProps }: AppProps) { return <Component {...pageProps} />; } export default MyApp;
- CSS Modules:將 CSS 檔案重命名為
[name].module.css
,並將其與對應的 React 元件放在一起。在元件中導入並像使用物件一樣使用 class 名稱。這提供了局部作用域,避免了命名衝突。Cursor 可以協助進行這種重構。- AI 指令範例:“將這個 CSS 檔案的規則轉換為 CSS Modules 格式,並更新對應的 React 元件以使用導入的樣式物件。”
- Tailwind CSS:如果您希望使用現代的 utility-first CSS 框架,可以考慮將現有樣式重構為 Tailwind CSS。Cursor 對於這種基於 class 的轉換也能提供一些幫助,但通常需要大量手動調整。
- Styled Components / Emotion:如果您偏好 CSS-in-JS 方案,可以將樣式直接寫在 React 元件中。Cursor 也能輔助生成這些樣式化元件的程式碼。
選擇哪種方法取決於您的專案需求和個人偏好。對於直接遷移,全域 CSS 或 CSS Modules 是較常見的選擇。
步驟六:處理路由和連結
確保 Next.js 應用程式中的內部連結指向正確的路徑。
- Next.js Link 元件:使用 Next.js 提供的
<Link>
元件來處理客戶端路由,以獲得最佳效能。import Link from 'next/link'; // ... <Link href={`/posts/${post.slug}`}> <a>{post.title}</a> </Link> // ...
- 檢查並更新連結:仔細檢查從 Handlebars 轉換過來的程式碼中的所有
<a>
標籤。將內部連結替換為使用<Link>
元件。Cursor 可以幫助查找和替換這些連結。- AI 指令範例:“查找此元件中所有指向
/post/
開頭的<a>
標籤,並將其替換為使用 Next.js 的<Link>
元件,保留href
和內容。”
- AI 指令範例:“查找此元件中所有指向
步驟七:部署到 Vercel
一旦您的 Next.js 前端能夠成功從 Headless Ghost CMS 獲取內容並正確顯示,就可以將其部署到 Vercel。
- 推送到 Git 倉庫:將您的 Next.js 專案推送到 GitHub, GitLab, 或 Bitbucket。
- 在 Vercel 上建立專案:登入您的 Vercel 帳戶,選擇 “Import Project”,然後選擇您的 Git 倉庫。
- 配置設定:
- Vercel 通常會自動檢測到是 Next.js 專案並選擇正確的框架預設。
- 環境變數:在 Vercel 的專案設定中,添加您之前使用的環境變數
GHOST_API_URL
和GHOST_CONTENT_API_KEY
。這是 非常重要 的一步,否則您的部署將無法連接到 Ghost CMS。
- 部署:點擊 “Deploy”。Vercel 將自動構建和部署您的 Next.js 應用程式。
部署完成後,Vercel 會提供一個 URL,您可以透過該 URL 訪問您的 Headless Ghost CMS 前端。
挑戰與注意事項
- 複雜的 Handlebars 邏輯:如果您的 Ghost 主題包含非常複雜的自訂 Handlebars helpers 或嵌套邏輯,AI 轉換可能不夠完美,需要更多手動介入。
- JavaScript 檔案:Ghost 主題中的 JavaScript 檔案可能需要進行調整才能在 React/Next.js 環境中正常工作,特別是那些直接操作 DOM 的程式碼。考慮是否可以用 React 的方式重新實現這些功能。
- 樣式細節:確保所有樣式都已正確遷移且顯示效果與原主題一致。跨瀏覽器測試是必要的。
- AI 不是萬能的:Cursor 是一個強大的輔助工具,但它不能完全取代開發者的理解和判斷。始終審查、測試和優化 AI 生成的程式碼。
結論:利用 AI 加速現代化遷移
將 Ghost CMS 主題遷移到 Next.js 是一個實現現代化、高效能網站架構的絕佳途徑。雖然這個過程涉及不同技術棧之間的轉換,但藉助於像 Cursor 這樣的 AI 驅動工具,可以顯著減少手動重寫程式碼的時間和精力。透過遵循上述步驟,結合 AI 的輔助和您自身的開發專業知識,您可以成功地將您的 Ghost 內容呈現在一個由 Next.js 驅動、部署在 Vercel 上的快速、現代化的前端應用程式中。
我們 Tenten.co 是一家專注於提供尖端數位解決方案的機構。無論您是需要進行複雜的網站架構遷移、客製化軟體開發,還是尋求提升數位產品效能的策略,我們的專業團隊都能提供協助。如果您在將 Ghost 遷移到 Next.js 或其他數位轉型項目中遇到挑戰,歡迎與我們聯繫。
立即預約免費諮詢會議,讓我們一同探討如何為您的專案帶來成功:預約免費會議