Files
yingfungsolar/docs/superpowers/specs/2026-09-11-ying-fung-solar-design.md
2026-09-11 15:49:41 +08:00

303 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 盈豐太陽能工程有限公司 — 官網設計規格 (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/* SSRAstro 表單 + 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` | 沿用 |
### 關鍵渲染決策
1. **首頁改為 SSR**`prerender = false`),因為首頁內容由 D1 提供、後台改完要即時生效。
-`Cache-Control: public, s-maxage=60, stale-while-revalidate=300` 保持效能。
2. **每個頁面用單一 React root island**`client:load`),入面包一個 `<Provider>`
- 原因:Chakra 的 Provider 只需一個;避免多個 island 各自建立 Provider 造成樣式重複。
- Astro 會 SSR render 呢個 islandSEO 無損),再喺 client hydrate。
3. **Chakra v3 SSR 樣式注入**:**已用 spike 實測驗證可行**。
- Versions: Astro 7.3.2 + `@astrojs/react` 6.0.5 + React 19.3 + `@chakra-ui/react` 3.37 + `@emotion/react` 11.14。
- 實測結果:SSR 會將 critical CSS 以 inline `<style data-emotion>` 輸出(首屏即有樣式、零 FOUC);client hydrate 後 emotion 會自動把樣式整合到 `<head>`**無 hydration error**,樣式正確。
- 因此採預設 `react()`streaming),每個 island 由 `<ChakraProvider value={system}>` 包裹。
- 禁止使用 `client:only`(會失去 SEO)。
4. **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 順序
1. **Header**sticky,玻璃感):Logo/公司名、錨點導覽(服務、案例、流程、常見問題、Blog)、WhatsApp CTA;手機版 hamburger drawer
2. **Hero**:眉題、主標題、副標、雙 CTA、主視覺圖、信任子彈點
3. **信任列**:電業承辦商牌照號、服務年資/案例數、客戶口碑
4. **服務**(村屋為主,34 卡)
5. **為何揀我哋**feature6 卡)
6. **專業安裝流程**5 步 timeline
7. **完成案例**(案例卡 + 圖)
8. **FAQ**accordion
9. **聯絡 CTA**:電話 / WhatsApp / Email / 地址
10. **Footer**
11. **浮動 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`1624px)、柔和陰影、細描邊
- 按鈕:`brand.solid` 圓角、hover 微加深
- 動效:捲動淡入/上移,用 CSS + IntersectionObserver,不引入 framer-motion
### 圖像
- 全部先用高質佔位/AI 生成圖,經 `img` URL 提供
- 之後可經後台換成真實工程相
---
## 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.txt` disallow `/admin`
- 首頁 SSR + s-maxage 邊緣快取
- 圖片 lazy load、`loading="lazy"`、尺寸標註
- 目標:Lighthouse SEO/Performance/Accessibility 良好
---
## 8. 部署(Cloudflare
```bash
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. 分階段實作
1. **基建**:加 React + Chakra + Provider、theme、換 Base layout、驗證 SSR 樣式
2. **首頁 UI**:全部 section 組件(先佔位內容)
3. **資料層**schema 擴充 + migration + seed(公司資料 + 樣本內容)
4. **Blog UI**:列表 + 文章頁翻新
5. **Admin**settings / content items / cases 編輯器
6. **SEO / 效能**sitemap、快取、Lighthouse
7. **部署**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
- 辦公地址
- 電業承辦商牌照號碼
- 真域名
- 真實工程相片(可後補)