12 KiB
12 KiB
盈豐太陽能工程有限公司 — 官網設計規格 (Design Spec)
- 日期:2026-09-11
- 專案代號:yingfungsolar
- 狀態:已與客戶確認方向,待寫實作計劃
1. 背景與目標
為香港村屋太陽能興建公司「盈豐太陽能工程有限公司」建立一個可以完全部署在 Cloudflare 的網站,包含:
- 面向公眾的一頁式官網
- 一個 Blog 分頁(列表 + 文章頁)
- 一個後台
/admin,讓非技術人員管理 Blog 及首頁內容
設計要求:美觀、現代化、清爽。內容參考 BrightSun Solar(村屋及工廈太陽能),但本網站只做村屋,而且版面設計不參考該站。
非目標 (Out of scope)
- 不做工廈 / 農地太陽能內容
- 不做雙語(只做繁體中文)
- 不做聯絡表單(只做 WhatsApp / 電話 / Email 連結)
- 不做圖片上傳(先用佔位圖,後台以 URL 貼圖)
- 不做多頁公司介紹(關於我們等內容併入一頁式)
2. 技術架構
沿用現有 cf-dash 骨幹,路線 A:Astro + React islands + Chakra UI。
┌──────────────── Cloudflare Worker (一個 deploy) ────────────────┐
瀏覽器 → │ Astro 7 │
│ ├─ / SSR,讀 D1 → React island (Chakra UI) │
│ ├─ /blog SSR,讀 D1 │
│ ├─ /blog/[slug] SSR,讀 D1 + Markdown 渲染 │
│ ├─ /admin/* SSR,Astro 表單 + HMAC cookie auth │
│ ├─ /sitemap.xml SSR,讀 D1 │
│ └─ /robots.txt 靜態 │
│ │ │
│ D1 (SQLite) ← Drizzle ORM │
│ KV (CACHE) ← 內容版本快取 (可選) │
└────────────────────────────────────────────────────────────────────┘
技術選型
| 層 | 選用 | 說明 |
|---|---|---|
| 框架 | Astro 7 (output: "static" + per-page prerender = false) |
沿用現有 |
| Adapter | @astrojs/cloudflare |
沿用現有 |
| UI | @chakra-ui/react v3 + @emotion/react(只淺色模式,不引入 color mode 套件) |
新增 |
| React | React 19(由 npx astro add react 加入) |
新增 |
| DB | Cloudflare D1 (SQLite) | 沿用 |
| ORM | Drizzle | 沿用 |
| Auth | HMAC-signed cookie(src/lib/auth.ts) |
沿用 |
| Markdown | marked(src/lib/markdown.ts) |
沿用 |
關鍵渲染決策
- 首頁改為 SSR(
prerender = false),因為首頁內容由 D1 提供、後台改完要即時生效。- 用
Cache-Control: public, s-maxage=60, stale-while-revalidate=300保持效能。
- 用
- 每個頁面用單一 React root island(
client:load),入面包一個<Provider>。- 原因:Chakra 的 Provider 只需一個;避免多個 island 各自建立 Provider 造成樣式重複。
- Astro 會 SSR render 呢個 island(SEO 無損),再喺 client hydrate。
- Chakra v3 SSR 樣式注入:已用 spike 實測驗證可行。
- Versions: Astro 7.3.2 +
@astrojs/react6.0.5 + React 19.3 +@chakra-ui/react3.37 +@emotion/react11.14。 - 實測結果:SSR 會將 critical CSS 以 inline
<style data-emotion>輸出(首屏即有樣式、零 FOUC);client hydrate 後 emotion 會自動把樣式整合到<head>;無 hydration error,樣式正確。 - 因此採預設
react()(streaming),每個 island 由<ChakraProvider value={system}>包裹。 - 禁止使用
client:only(會失去 SEO)。
- Versions: Astro 7.3.2 +
- Admin 沿用 Astro SSR 表單(POST
formData),不引入 React/Chakra,降低複雜度。
3. 資料庫設計 (Drizzle / D1)
3.1 posts(現有,擴充)
| 欄位 | 型別 | 說明 |
|---|---|---|
id |
text PK | UUID |
slug |
text unique | |
title |
text | |
excerpt |
text | |
content |
text | Markdown |
meta_description |
text | |
cover_image |
text | 新增,封面圖 URL |
tags |
text | 新增,逗號分隔(可選) |
status |
text | draft | published |
published_at |
integer (timestamp_ms) | |
updated_at |
integer (timestamp_ms) |
3.2 site_settings(新增,單例 key-value)
| 欄位 | 型別 | 說明 |
|---|---|---|
key |
text PK | 設定名稱 |
value |
text | 值(複雜值以 JSON 字串存放) |
updated_at |
integer (timestamp_ms) |
種子 keys:
- 公司:
company_name,company_short_name,license_no,phone,whatsapp,email,address,facebook_url - Hero:
hero_eyebrow,hero_title,hero_subtitle,hero_primary_cta,hero_secondary_cta,hero_image - SEO:
seo_default_title,seo_default_description,og_image - 信任列:
trust_stats(JSON 陣列)
3.3 content_items(新增,重複內容)
| 欄位 | 型別 | 說明 |
|---|---|---|
id |
text PK | UUID |
kind |
text | service | feature | step | faq |
title |
text | 服務名 / 特色名 / 步驟名 / 問題 |
description |
text | 描述 / 答案 |
extra |
text | 可選(icon 名、步驟編號等) |
sort_order |
integer | 排序 |
status |
text | draft | published |
updated_at |
integer (timestamp_ms) |
service:首頁服務卡(村屋太陽能相關)feature:為何揀我哋step:專業安裝流程(extra 放01–05)faq:常見問題
3.4 cases(新增,完成案例)
| 欄位 | 型別 | 說明 |
|---|---|---|
id |
text PK | UUID |
title |
text | 例:大埔上碗窯 - 雙玻光伏板 航空鋁支架 |
location |
text | 例:大埔半山 |
completed_at |
text | 例:2026年2月 |
description |
text | |
image_url |
text | 佔位圖 URL |
sort_order |
integer | |
status |
text | draft | published |
updated_at |
integer (timestamp_ms) |
索引:content_items(kind, status, sort_order)、cases(status, sort_order)、posts(status, published_at)。
4. 路由與頁面
| 路徑 | 渲染 | 內容 |
|---|---|---|
/ |
SSR | 一頁式官網 |
/blog |
SSR | 文章卡片列表 |
/blog/[slug] |
SSR | 文章頁(Markdown) |
/admin |
SSR | 儀表板:文章列表 + 內容管理入口 |
/admin/login |
SSR | 登入 |
/admin/logout |
SSR | 登出 |
/admin/post/[id] |
SSR | 新增/編輯文章 |
/admin/settings |
SSR | 公司 / 聯絡 / Hero / SEO 設定 |
/admin/content/[kind] |
SSR | 通用編輯器(service/feature/step/faq) |
/admin/cases |
SSR | 案例列表 |
/admin/cases/[id] |
SSR | 新增/編輯案例 |
/sitemap.xml |
SSR | 動態 |
/robots.txt |
靜態 |
4.1 首頁 section 順序
- Header(sticky,玻璃感):Logo/公司名、錨點導覽(服務、案例、流程、常見問題、Blog)、WhatsApp CTA;手機版 hamburger drawer
- Hero:眉題、主標題、副標、雙 CTA、主視覺圖、信任子彈點
- 信任列:電業承辦商牌照號、服務年資/案例數、客戶口碑
- 服務(村屋為主,3–4 卡)
- 為何揀我哋(feature,6 卡)
- 專業安裝流程(5 步 timeline)
- 完成案例(案例卡 + 圖)
- FAQ(accordion)
- 聯絡 CTA:電話 / WhatsApp / Email / 地址
- Footer
- 浮動 WhatsApp 掣
4.2 Blog
- 列表:卡片(封面圖、標題、摘要、日期),空狀態
- 文章頁:封面、標題、日期、Markdown prose、返回連結、SEO/OG
5. 設計系統(Chakra theme)
已過時:2026-09-11 前台改為 editorial 極簡風(暖米白+琥珀金+明體標題),以
2026-09-11-editorial-redesign-design.md為準。以下保留作歷史記錄。
檔案:src/theme/system.ts,用 createSystem(defaultConfig, defineConfig(...))。
色彩(清新天藍/綠色系)
| Token | 值 | 用途 |
|---|---|---|
brand(主,綠) |
#0B8A5E 為主,配 50–900 色階 |
主 CTA、標題點綴、標籤 |
sky(副,天藍) |
#0BA5EC / #38BDF8 |
圖示、裝飾、漸層 |
bg 頁面 |
#FFFFFF |
主背景 |
bg.subtle |
#F2F8F6 |
分段背景 |
fg |
#0F1E1A |
正文 |
fg.muted |
#5B6B66 |
次要文字 |
border |
#E2EDE9 |
卡片描邊 |
- 漸層:天藍 → 青綠(Hero 裝飾光暈)
- 語意 tokens:
bg,fg,border,brand.solid,brand.contrast,brand.muted
字體
Noto Sans HK(fallback:PingFang HK, system sans)- 標題:700/800,負字距;內文:400/500,行高 1.75
形狀與動效
- 卡片:白底、圓角
2xl(16–24px)、柔和陰影、細描邊 - 按鈕:
brand.solid圓角、hover 微加深 - 動效:捲動淡入/上移,用 CSS + IntersectionObserver,不引入 framer-motion
圖像
- 全部先用高質佔位/AI 生成圖,經
imgURL 提供 - 之後可經後台換成真實工程相
6. Admin 功能
- 沿用 Astro SSR 表單 + HMAC cookie;共用設計 token 的 CSS,令後台風格與前台一致
- 文章:列表 / 新增 / 編輯 / 發布 / 刪除(現有,加封面圖欄)
- 設定
/admin/settings:公司資料、聯絡、Hero 文案、SEO 預設(分組表單) - 內容
/admin/content/[kind]:通用編輯器,支援新增/編輯/刪除/上下排序;以kind切換 service/feature/step/faq - 案例
/admin/cases:列表 + 編輯(含圖片 URL、地點、日期)
內容更新即時生效
- Admin 儲存 → 首頁 SSR 讀 D1(最長 60 秒邊緣快取後更新)
- (可選)儲存時 bump
CACHE內的content_version,於 SSR 檢查以提早失效
7. SEO / 效能
- 沿用
Base.astro的 canonical / OG / Twitter card;補上cover_image作og:image sitemap.xml加入/、/blog、各文章robots.txtdisallow/admin- 首頁 SSR + s-maxage 邊緣快取
- 圖片 lazy load、
loading="lazy"、尺寸標註 - 目標:Lighthouse SEO/Performance/Accessibility 良好
8. 部署(Cloudflare)
npx astro add react
npm i @chakra-ui/react @emotion/react
npx wrangler d1 create yingfung-solar-db # 將 database_id 填入 wrangler.jsonc
npx wrangler kv namespace create CACHE # 將 id 填入 wrangler.jsonc
npm run db:generate
npm run db:migrate # 雲端
npm run db:migrate:local # 本機
npx wrangler secret put ADMIN_PASSWORD
# 更新 astro.config.mjs site、src/config.ts、wrangler.jsonc vars
npm run deploy
- 需更新
wrangler.jsonc的name、vars.SITE_NAME為盈豐太陽能 astro.config.mjs的site待客戶提供真域名
9. 分階段實作
- 基建:加 React + Chakra + Provider、theme、換 Base layout、驗證 SSR 樣式
- 首頁 UI:全部 section 組件(先佔位內容)
- 資料層:schema 擴充 + migration + seed(公司資料 + 樣本內容)
- Blog UI:列表 + 文章頁翻新
- Admin:settings / content items / cases 編輯器
- SEO / 效能:sitemap、快取、Lighthouse
- 部署:D1/KV/secret、上線
10. 風險與對策
| 風險 | 對策 |
|---|---|
| Chakra v3 + Astro SSR 樣式注入 | 已實測通過(見 §2.3);Astro 7 + React 19 + Chakra 3.37 無 hydration error |
Astro 7 與 @astrojs/react / React 19 版本相容 |
用 npx astro add react 自動配對版本 |
| 多個 island 造成 Provider 重複 | 每頁只一個 React root island |
| 佔位圖版權 | 使用可商用來源或 AI 生成 |
| 接觸點資訊未齊 | 全部放 site_settings,客戶可於後台自行更新 |
11. 待客戶提供
- 真實電話 / WhatsApp 號碼
- 聯絡 Email
- 辦公地址
- 電業承辦商牌照號碼
- 真域名
- 真實工程相片(可後補)