建立專案與品牌設定

建立 Saavo 專案,完成本機初始化、網站文案和主題色彩設定。

上一篇已決定產品範圍和技術方案。這篇會建立正式的 Saavo 專案,完成本機執行、網站文案和主題色彩設定。

建立 WebpageToPDF 專案

完成原型驗證後,就可以開始使用 Saavo 建立正式專案。

前面的原型階段,主要用來驗證功能和方案是否可行。進入正式開發後,需要先準備好開發環境,再將已驗證的功能逐步移植到 Saavo 範本。

這次教學使用 Windows,終端機使用 PowerShell,開發工具則使用 Cursor 和 Codex。後續內容也會以這組環境示範。

這只是我個人的工具組合,並不是 Saavo 的必要條件。如果你已有慣用的編輯器或 AI 程式設計工具,繼續使用即可,不需要為了跟著教學操作而更換。

準備帳號與基本環境

前面的事前準備已介紹詳細步驟。如果直接從這篇實作教學開始,請先確認以下項目:

  1. Saavo 帳號與範本使用權限:先完成註冊與購買。購買後,可以在帳號中心的「我的產品」看到 Saavo Starter。之後授權 CLI 時,也需登入這個具有範本使用權限的帳號。
  2. Git:依安裝 Git完成安裝,用來儲存程式碼修改記錄。之後請 AI 修改程式碼時,也方便檢查實際改動。
  3. Node.js 與 npm:依安裝 Node.js完成安裝。目前 CLI 和範本要求 Node.js 至少為 22.13.0,依事前準備的步驟安裝 Node.js 24 LTS 即可,npm 會一併安裝。
  4. Cloudflare 帳號:這個專案最後會部署到 Cloudflare,需依註冊 Cloudflare完成註冊、電子郵件驗證和 R2 啟用。不過,只在本機執行 Saavo 範本時,還不需要遠端資源,可以在部署前再完成,也不用現在就手動建立資料庫、Bucket 和佇列。

安裝後,重新開啟 PowerShell,檢查指令是否可用:

git --version
node -v
npm -v

三個指令都應輸出版本號碼。如果找不到指令,請先回到對應的安裝文件處理。若 PowerShell 提示禁止執行 npm.ps1,請參考 Node.js 安裝頁面的說明,可以先用 npm.cmd、npx.cmd 執行,不需要重新安裝 Node.js。

網域、郵件、付款和第三方登入,不需要一開始就全部設定好。我已註冊 webpagetopdf.dev,但本機開發不依賴網域。現階段先讓範本正常執行,等開發到郵件、付費或部署功能時,再設定對應服務即可。詳細內容可參考選用服務。

安裝 Cursor 和 Codex

如果想使用與我相同的工具,還需要安裝 Cursor 和 Codex。Cursor 主要用來查看及修改程式碼、執行終端機指令,Codex 則用來分析專案、撰寫程式碼和排查問題。Cursor 也提供 AI 功能,實際開發時使用哪個工具完成工作,依個人習慣決定即可。

  • Cursor:開啟 Cursor 下載頁面,選擇適合自己系統的桌面版並安裝。第一次啟動時,依提示登入帳號並完成基本設定,是否匯入其他編輯器的設定,可以自行決定。
  • Codex:這裡使用桌面版,請依 OpenAI 官方桌面版安裝說明下載並安裝。Windows 使用者可直接查看 Windows 安裝頁面。安裝後,使用自己的 ChatGPT 帳號登入,依提示完成初始設定。之後需要讓它開啟本機專案目錄,而不只是將程式碼複製到聊天視窗。

這兩個工具的帳號與 Saavo 帳號是分開的。安裝後,先確認想使用的 AI 功能可以正常運作,可用模型和額度以各自帳號顯示的內容為準。

建立並初始化專案

開啟 PowerShell 或 CMD,進入準備存放專案的上層目錄,再執行:

npx saavo-cli@latest create webpagetopdf

這個指令會在目前目錄建立 webpagetopdf 資料夾。如果前面的原型專案已使用這個名稱,請換一個目錄,避免覆寫原始程式碼。

第一次執行時,npx 可能會提示安裝 saavo-cli,確認後繼續即可,不需要預先全域安裝 CLI。

接著會開啟 Saavo 的瀏覽器授權頁面。請登入具有範本使用權限的帳號,確認授權內容後允許存取,再回到終端機。如果帳號有多個可用範本,依提示選擇這次使用的範本即可。

下載範本後,CLI 會詢問是否準備本機開發環境:

Prepare the project for local development?
Installs dependencies, creates .env, and initializes local databases.

這裡選擇 Yes。CLI 會安裝相依套件,再呼叫範本的 saavo:init,建立本機 .env、產生 SAAS_SECRET 和 Cloudflare 型別、初始化本機 D1 資料庫,最後執行 doctor 檢查設定。這些步驟不需要再手動重做,Wrangler 也會隨專案相依套件一起安裝。

終端機顯示 Project is ready for local development 時,代表本機初始化已完成。如果略過初始化,或安裝相依套件、初始化的過程失敗,請先解決終端機指出的問題,再進入已下載的專案目錄補做:

cd webpagetopdf
npm install
npm run saavo:init

完整的授權與初始化截圖,可參考建立專案。

開啟專案,確認能正常執行

在 Cursor 開啟整個 webpagetopdf 資料夾,不要只開啟單一檔案。接著在 Codex 新增本機專案,同樣選擇這個資料夾。開啟後,根目錄應能看到 package.json、config/、src/ 和 AGENTS.md。

Cursor 開啟專案結構

範本已內建 AGENTS.md 和 .cursor/rules/ 的專案規則,使用 AI 修改程式碼時,請勿刪除這些檔案。Cursor 和 Codex 可以同時開啟同一個專案,但盡量不要同時修改同一批檔案,避免內容被覆寫。

在 Cursor 終端機確認目前目錄為 webpagetopdf,再執行:

npm run dev

使用瀏覽器開啟終端機顯示的本機網址,先確認首頁、文件、登入和註冊頁面都能正常存取。

在本機執行的畫面

這時看到的應該仍是 Saavo 預設頁面,先不要急著移植原型程式碼。如果範本本身出現錯誤,請先依在本機執行的說明排查,確認基本環境正常後再繼續開發。

此時,初始化指令碼已產生 .env 檔案。裡面的金鑰不要提交到 Git,也不要直接複製到其他專案使用。

範本在本機開發時,會透過本機執行環境模擬資料庫和儲存服務。郵件、Stripe、第三方登入等外部服務暫時不需設定,等開發到對應功能時,再填入相關驗證資訊。

頁面能正常開啟,只代表專案已在本機成功執行,不代表外部服務已設定完成。

修改網站文案

初始化範本後,先不用處理主題樣式或頁面內容,首要工作是確認網站的三個要素:網域、標題和描述。

domain: webpagetopdf.dev
title: Webpage to PDF
description: Convert a URL to PDF online. Capture full webpages, customize PDF layouts, and hide unwanted content with a visual editor before exporting.

接著不需要手動修改,只需在 Codex 執行專案內附的 Agent,即可初始化內容。提示詞如下:

使用下列參數執行 $saavo-initialize-content:

{
  "domain": "webpagetopdf.dev",
  "title": "Webpage to PDF",
  "description": "Convert a URL to PDF online. Capture full webpages, customize PDF layouts, and hide unwanted content with a visual editor before exporting."
}

執行後,開啟 config/base.ts,確認內容已更新為:

export const websiteBaseCfg = {
    siteName: {
        value: "Webpage to PDF",
        key: 'website.title',
    },

    siteDescription: {
        value: "Convert a URL to PDF online. Capture full webpages, customize PDF layouts, and hide unwanted content with a visual editor before exporting.",
        key: 'website.description',
    },

    siteOGImage: '',
    siteOGImageAlt: '',
    siteOGImageWidth: 1200,
    siteOGImageHeight: 630,

    twitterSite: '',
    twitterCreator: '',
    twitterImage: '',

    fbAppId: '',

    // 精確比對的允許清單。應用程式驗證該位址後才授予管理員角色。
    // 這些值刻意不進行電子郵件別名比對。
    adminEmails: ['admin@saavo.dev'],
    supportEmail: 'support@saavo.dev',
    fromEmailAddress: {
        name: "Webpage to PDF",
        email: 'send@mail.saavo.dev',
    },
}

也順便更新電子郵件設定:

export const websiteBaseCfg = {
    ...
    adminEmails: ['admin@webpagetopdf.dev'],
    supportEmail: 'support@webpagetopdf.dev',
    fromEmailAddress: {
        name: "Webpage to PDF",
        email: 'send@mail.webpagetopdf.dev',
    },
}

接著最好在 Codex 再檢查一次,避免 Agent 執行時有所遺漏:

依照上方的 Webpage to PDF 產品說明,獨立檢查網站,直接修正已確認的遺漏、舊品牌內容、不一致的文案、翻譯問題與非預期修改。不要依賴先前的報告,也不要呼叫初始化技能。避免無關修改,執行相關檢查,並簡要說明已修正的內容與剩餘問題。

確認後,重新執行 npm run dev,檢查網站資訊是否已更新。

更新後的本機執行畫面

調整主題色彩

執行前面的初始化 Agent 後,網頁文案已換成新內容,但主題色彩仍是預設值。接下來調整色彩。

只需調整專案的 styles/base.css,不必手動逐項修改,直接請 Codex 處理即可。

找到先前的原型專案,請 Codex 依固定格式擷取配色資訊:

擷取目前原型的配色,填入下方 CSS 範本。

要求:
1. 優先使用原始碼中的實際顏色。如果只有螢幕擷取畫面,則從畫面擷取顏色。保留原型的品牌特徵與視覺風格。
2. 如果原型沒有深色主題,建立中性的炭灰色主題。背景、卡片與側邊欄保持中性色,品牌色主要用於按鈕與強調元素。
3. 計算對比度:一般文字(包括次要文字)與其背景的對比度至少為 4.5:1。必要的控制項邊界與焦點指示器,與相鄰顏色的對比度至少為 3:1,必要時調整顏色。
4. 只替換 <HEX> 與 <SHADOW>。保留選取器、變數名稱、順序、分組及其他所有設定。使用小寫六位 HEX 色碼,陰影顏色使用 rgb(R G B / A)。
5. 只輸出完整的 CSS。不要遺漏變數、保留預留位置或修改專案檔案。

:root {
  color-scheme: light;
  --radius: 0.75rem;

  --background: <HEX>;
  --foreground: <HEX>;
  --card: <HEX>;
  --card-foreground: <HEX>;
  --popover: <HEX>;
  --popover-foreground: <HEX>;
  --primary: <HEX>;
  --primary-foreground: <HEX>;
  --secondary: <HEX>;
  --secondary-foreground: <HEX>;
  --muted: <HEX>;
  --muted-foreground: <HEX>;
  --accent: <HEX>;
  --accent-foreground: <HEX>;
  --destructive: <HEX>;
  --destructive-foreground: <HEX>;
  --border: <HEX>;
  --input: <HEX>;
  --ring: <HEX>;

  --brand-primary: <HEX>;
  --brand-primary-strong: <HEX>;
  --brand-warm: <HEX>;
  --brand-success: <HEX>;
  --brand-danger: <HEX>;
  --brand-info: <HEX>;
  --brand-from: <HEX>;
  --brand-to: <HEX>;

  --chart-1: <HEX>;
  --chart-2: <HEX>;
  --chart-3: <HEX>;
  --chart-4: <HEX>;
  --chart-5: <HEX>;

  --sidebar: <HEX>;
  --sidebar-foreground: <HEX>;
  --sidebar-primary: <HEX>;
  --sidebar-primary-foreground: <HEX>;
  --sidebar-accent: <HEX>;
  --sidebar-accent-foreground: <HEX>;
  --sidebar-border: <HEX>;
  --sidebar-ring: <HEX>;

  --shadow-xs-value: <SHADOW>;
  --shadow-sm-value: <SHADOW>;
  --shadow-md-value: <SHADOW>;
  --shadow-lg-value: <SHADOW>;
}

.dark {
  color-scheme: dark;

  --background: <HEX>;
  --foreground: <HEX>;
  --card: <HEX>;
  --card-foreground: <HEX>;
  --popover: <HEX>;
  --popover-foreground: <HEX>;
  --primary: <HEX>;
  --primary-foreground: <HEX>;
  --secondary: <HEX>;
  --secondary-foreground: <HEX>;
  --muted: <HEX>;
  --muted-foreground: <HEX>;
  --accent: <HEX>;
  --accent-foreground: <HEX>;
  --destructive: <HEX>;
  --destructive-foreground: <HEX>;
  --border: <HEX>;
  --input: <HEX>;
  --ring: <HEX>;

  --brand-primary: <HEX>;
  --brand-primary-strong: <HEX>;
  --brand-warm: <HEX>;
  --brand-success: <HEX>;
  --brand-danger: <HEX>;
  --brand-info: <HEX>;
  --brand-from: <HEX>;
  --brand-to: <HEX>;

  --chart-1: <HEX>;
  --chart-2: <HEX>;
  --chart-3: <HEX>;
  --chart-4: <HEX>;
  --chart-5: <HEX>;

  --sidebar: <HEX>;
  --sidebar-foreground: <HEX>;
  --sidebar-primary: <HEX>;
  --sidebar-primary-foreground: <HEX>;
  --sidebar-accent: <HEX>;
  --sidebar-accent-foreground: <HEX>;
  --sidebar-border: <HEX>;
  --sidebar-ring: <HEX>;

  --shadow-xs-value: <SHADOW>;
  --shadow-sm-value: <SHADOW>;
  --shadow-md-value: <SHADOW>;
  --shadow-lg-value: <SHADOW>;
}

再將擷取的資訊填入 styles/base.css 即可。

調整主題色彩

本篇檢查

完成本篇後,應能在本機開啟專案,並確認網站文案、電子郵件設定和主題色彩都已更新。

教學總覽 · 上一篇:產品設計與原型驗證 · 下一篇:移植 PDF 轉換功能