first commit

This commit is contained in:
2026-09-11 15:49:41 +08:00
commit 5b69bc818a
98 changed files with 30551 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
# docs/AGENTS.md
## Purpose
專案的設計規格與實作計劃文件。
## Ownership
- 擁有 `docs/` 全樹,包括 `docs/superpowers/specs/``docs/superpowers/plans/`
## Local Contracts
- **設計權威**`superpowers/specs/` 係已確認的設計規格,係設計決策的權威來源。實作與 spec 有出入時,以 spec 為準,或先更新 spec。
- **實作計劃**`superpowers/plans/` 用 checkbox 追蹤進度;計劃與實際實作有偏差時同步更新。
- **檔名**`YYYY-MM-DD-<slug>.md`
- 內容繁體中文(廣東話)。
## Work Guidance
- 做大改動前先讀對應 spec / plan;完成後如設計有變,更新文件而唔係留低過時描述。
- 呢啲係設計記錄,唔係日常 diary;只記穩定決策同計劃。
## Verification
無自動化檢查;靠人工對照 spec 同實作。
## Child DOX Index
無(`superpowers/` 由本文件覆蓋)。
@@ -0,0 +1,180 @@
# 盈豐太陽能官網 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 將現有 Astro + Cloudflare + D1 骨幹改造成盈豐太陽能工程有限公司的村屋太陽能一頁式官網(Chakra UI)+ Blog + 內容管理後台。
**Architecture:** Astro 7`output: "static"` + per-page `prerender=false`)作全疊框架,`@astrojs/react` 提供 React islandChakra UI v3Emotion)負責前台 UI。首頁 SSR 讀 D1,經 `Cache-Control: s-maxage` 邊緣快取。後台沿用 Astro SSR 表單 + HMAC cookie。資料層用 Drizzle + D1。
**Tech Stack:** Astro 7.3 / @astrojs/react 6 / React 19 / @chakra-ui/react 3.37 / @emotion/react / Drizzle ORM / Cloudflare D1 + KV / marked。
**已驗證(spike):** Chakra v3 + Astro SSR 可正常運作,inline critical CSS、零 FOUC、無 hydration error。
---
## 檔案結構
```
src/
├─ theme/system.ts # Chakra systemtokens/semanticTokens/recipes/fonts
├─ components/site/
│ ├─ Provider.tsx # <ChakraProvider value={system}>
│ ├─ SiteChrome.tsx # Header + main + Footer 外框
│ ├─ Header.tsx Hero.tsx TrustBar.tsx Services.tsx Features.tsx
│ ├─ Process.tsx Cases.tsx Faq.tsx ContactCta.tsx Footer.tsx
│ ├─ WhatsAppFab.tsx Section.tsx SectionHeading.tsx
│ ├─ HomePage.tsx # 組合首頁所有 section
│ ├─ BlogIndex.tsx BlogPost.tsx
├─ data/content.ts # D1 讀取:settings/items/cases,型別化
├─ db/schema.ts # posts + site_settings + content_items + cases
├─ db/seed.ts # 種子公司資料 + 樣本內容
├─ layouts/Base.astro # SEO head / fonts / global reset
├─ layouts/AdminLayout.astro # 後台外框(沿用 + 換色)
├─ pages/index.astro # SSR 讀 D1 → <HomePage client:load>
├─ pages/blog/index.astro # SSR → <BlogIndex client:load>
├─ pages/blog/[slug].astro # SSR → <BlogPost client:load :html>
├─ pages/admin/** # login/logout/index/post/settings/content/cases
├─ pages/sitemap.xml.ts robots.txt.ts
└─ lib/{auth,db,env,markdown}.ts(沿用)
```
---
## Phase 1 — Foundation
### Task 1: Chakra theme system
**Files:** Create `src/theme/system.ts`
- [ ] 定義 tokens`colors.brand`#0B8A5E 色階)、`colors.sky`#0BA5EC 色階)、`fonts.heading/body = Noto Sans HK`
- [ ] 定義 semanticTokens`bg`, `bg.subtle`, `fg`, `fg.muted`, `border`, `brand.solid`, `brand.contrast`, `brand.muted`
- [ ] `createSystem(defaultConfig, config)` 匯出 `system`
- [ ] 驗證:`npm run build` 無 TypeScript/Chakra token 錯誤
### Task 2: Provider + SiteChrome
**Files:** Create `src/components/site/Provider.tsx`, `src/components/site/SiteChrome.tsx`, `Section.tsx`, `SectionHeading.tsx`
- [ ] `Provider` = `<ChakraProvider value={system}>{children}</ChakraProvider>`
- [ ] `SiteChrome` = `<Provider><Header/><Box as="main">{children}</Box><Footer/><WhatsAppFab/></Provider>`
- [ ] 驗證:build 過
### Task 3: Base.astro SEO layout
**Files:** Modify `src/layouts/Base.astro`
- [ ] 保留 canonical / OG / Twitter / robots 邏輯;加 `og:image`cover prop
- [ ] 加 Google FontsNoto Sans HK`<link>`,加中文字體 fallback
- [ ] 移除舊的純 CSS 樣式(改由 Chakra 負責),只保留最小 global reset(可在 Chakra `globalCss`
- [ ] 驗證:build 過
---
## Phase 2 — Data layer
### Task 4: Drizzle schema
**Files:** Modify `src/db/schema.ts`
- [ ] `posts``cover_image` (text), `tags` (text)
- [ ] 新增 `site_settings`key PK, value, updated_at
- [ ] 新增 `content_items`id, kind, title, description, extra, sort_order, status, updated_at+ index(kind,status,sort_order)
- [ ] 新增 `cases`id, title, location, completed_at, description, image_url, sort_order, status, updated_at+ index(status,sort_order)
- [ ] 匯出型別
- [ ] 驗證:`npm run db:generate` 產生 migration
### Task 5: Seed
**Files:** Create `src/db/seed.ts`(以 drizzle 插入種子,可 idempotent
- [ ] 公司資料:盈豐太陽能工程有限公司(電話/WhatsApp/email/地址/牌照號用佔位)
- [ ] Hero 文案、SEO 預設
- [ ] services(村屋太陽能、天台空間、合法支架、代辦申請、降室溫、回報計算)
- [ ] features(熟悉香港環境、流程清晰、專人跟進、美觀效率、施工安全、真誠建議)
- [ ] steps(初步諮詢/現場評估 → 申請文件 → 安裝施工 → 驗收認證 → 掛表發電)
- [ ] faqs(村屋天台可否安裝、回本期、需要幾大面積、是否合法、保養、申請邊個)
- [ ] cases(大埔上碗窯、元朗山下村、西貢西澳村 — 佔位圖)
- [ ] 驗證:`npm run db:migrate:local` 後 SQL 查得到
### Task 6: Content access helpers
**Files:** Create `src/data/content.ts`
- [ ] `getSettings(db)` → Record<string,string>
- [ ] `getItems(db, kind)` → published, order by sort_order
- [ ] `getCases(db)` → published, order by sort_order
- [ ] `getPublishedPosts(db)` / `getPostBySlug(db, slug)`
- [ ] 型別 `Settings`, `ContentItem`, `CaseItem`
- [ ] 驗證:TS build 過
---
## Phase 3 — Homepage UI
### Task 716: Sections
**Files:** Create 各 section 元件(見檔案結構)
每個 section 一個 task,包含:完整 Chakra markup、響應式、內容 props、設計(清新天藍/綠)。
- [ ] Headersticky、玻璃感、手機 drawer、錨點導覽、WhatsApp CTA
- [ ] Hero(眉題/標題/副標/雙 CTA/主視覺圖/信任子彈)
- [ ] TrustBar(牌照號、案例數、口碑)
- [ ] Services(卡片 grid
- [ ] Features6 卡)
- [ ] Process5 步 timeline
- [ ] Cases(案例卡 + 圖)
- [ ] FaqAccordion
- [ ] ContactCtaWhatsApp/電話/email/地址)
- [ ] Footer + WhatsAppFab
### Task 17: HomePage 組裝 + index.astro
- [ ] `HomePage.tsx` 接收 `{ settings, services, features, steps, faqs, cases }` props,用 `<SiteChrome>` 包住所有 section
- [ ] `src/pages/index.astro``prerender=false`,讀 D1`<HomePage ... client:load />`,設 `Cache-Control`
- [ ] 驗證:`astro dev` 開 / 無 console errorRWD 檢查
---
## Phase 4 — Blog
### Task 18: Blog UI
- [ ] `BlogIndex.tsx`(卡片:封面/標題/摘要/日期,空狀態)
- [ ] `BlogPost.tsx`(封面/標題/日期/prose/返回)
- [ ]`blog/index.astro``blog/[slug].astro` 用新元件(改 SSR propless → props
- [ ] 驗證:build + 瀏覽器
---
## Phase 5 — Admin
### Task 1922
- [ ] `/admin/settings`:分組表單(公司/聯絡/Hero/SEO),POST upsert
- [ ] `/admin/content/[kind]`:通用 list + 編輯 + 上下排序(service/feature/step/faq
- [ ] `/admin/cases``/admin/cases/[id]`CRUD
- [ ] `/admin/post/[id]`:加封面圖欄位
- [ ] 驗證:登入後可改,前台即刻反映(SSR)
---
## Phase 6 — SEO / Deploy
### Task 2324
- [ ] 更新 `sitemap.xml.ts`(含 /blog 文章 cover)、`robots.txt.ts`
- [ ] `wrangler.jsonc`name=`yingfung-solar``SITE_NAME`=盈豐太陽能、佔位 d1/kv id
- [ ] `astro.config.mjs``site``react()`(已加)
- [ ] `src/config.ts`:公司名/tagline
- [ ] README 更新部署步驟
- [ ] 驗證:`npm run build``npm run preview`、Lighthouse
---
## 驗證指令
- `npm run build` 必須成功
- `npm run db:migrate:local` 建本機 DB
- `NODE_OPTIONS= npx astro dev` 開 :4321
- 瀏覽器:無 console error、RWD、錨點、FAQ accordion、WhatsApp link 正確
- 每個 phase 完成後 commit(如已初始化 git)
@@ -0,0 +1,80 @@
# 盈豐太陽能 — 前台 Editorial 極簡重新設計 (Redesign Spec)
- **日期**2026-09-11
- **狀態**:已與客戶確認方向
- **背景**:初版 UI(見 `2026-09-11-ying-fung-solar-design.md`)被客戶評為「AI 模板感太重」。本規格取代該 spec 的 §5 設計系統部分;其餘架構/資料庫/路由/SEO 決策不變。
---
## 1. 設計方向
**暖米白 × 琥珀金 × 明體標題** 的 editorial 極簡風,似高端工程公司官網。
要消滅嘅「AI 模板痕跡」:
- 綠→天藍漸層(logo 磚、hero 光暈、流程圓圈、CTA 橫額)→ 全站零漸層、零光斑
- 膠囊形按鈕(`rounded-full`)→ 直角或微圓角(≤4px
- Pill badge 眉題 →「琥珀短線+細字 letterspaced 眉題」
- Hero 圖上浮卡 → 圖下髮絲線統計列
- Icon 放淺色圓角磚嘅卡片網格 → 編號式清單/髮絲線格網,無卡片陰影
- 柔和陰影卡片 → 髮絲邊框(hairline)分隔
## 2. 範圍
- **只改前台**`src/theme/system.ts``src/layouts/Base.astro``src/components/site/*.tsx`
- **唔郁**:資料層、D1 schema、路由、admin`/admin` 後台維持現有純 CSS 色系)
## 3. 新 Design Tokens`src/theme/system.ts`
### 色彩
| Token | 值方向 | 用途 |
|---|---|---|
| `bg` 頁面 | 暖米白 `#FAF8F4` | 主背景 |
| `bg.subtle` | 略深米白 `#F3EFE7` | 分段背景 |
| `ink`(深色 surface | 墨黑 `#1A1917` | CTA / Footer / 深色 section |
| `fg` | 墨 `#1A1917` | 正文 |
| `fg.muted` | 暖灰 `#6E6862` | 次要文字 |
| `border.subtle` | 髮絲 `#E7E2D9` | 分隔線、邊框 |
| `brand`(唯一彩色) | 琥珀金階梯,主色 `#C2410C``#D97706` 一帶 | CTA、編號、重點數字 |
- 語意 token 名保留(`brand.*``fg.muted``border.subtle``bg.subtle`)以減少改動;舊 `sky` 色階移除。
- `bg.hero` token 移除(Hero 用主背景)。
### 字體
- 標題:`Noto Serif HK`700/900),serif fallback
- 內文:維持 `Noto Sans HK`
- `Base.astro` 的 Google Fonts link 加入 Noto Serif HK 字重;global body 背景轉米白
### 形狀與動效
- 按鈕:實心墨黑或琥珀金,直角/微圓角(`rounded="sm"``none`),唔再係膠囊
- 卡片:去大圓角去陰影,以髮絲線分隔
- 動效:保留簡單 hover(透明度/位移),唔加新動畫庫
## 4. 各 Section 重構
1. **Header**:去玻璃模糊 → 米白實底+髮絲底線;logo 改純文字 wordmarkserif 公司名,唔再係漸層 icon 磚);CTA 改墨黑直角實心掣;手機 drawer 保留但跟新色
2. **Hero**:serif 超大標題;眉題改琥珀短線+細字;剷走圖上浮卡 → 圖下方髮絲線統計列(回本期/系統年期/牌照);次 CTA 改文字連結「睇完成案例 →」;去背景光斑
3. **TrustBar**:四欄髮絲分隔列,幼線 icon+細字,無底色無框
4. **Services**:icon 卡片 → 編號式清單(01/02/03),serif 標題+列頂髮絲線,hover 出現箭嘴
5. **Features**:白卡 → 髮絲線格網(報紙分欄感),編號+serif 標題
6. **Process**:漸層圓圈 → 超大 serif 琥珀數字+髮絲連線
7. **Cases**:去圓角去陰影;首案例 featured 放大(非對稱);地點 pill badge 改細字標籤
8. **FAQ**:白卡 accordion → 髮絲線裸列,serif 問題
9. **ContactCta**:漸層橫額 → 墨黑實底 section,serif 白標題+琥珀實心掣
10. **Footer**:深綠底 → 墨黑底;logo 磚改文字 wordmark;髮絲分隔線
11. **WhatsAppFab**:綠色圓掣 → 墨黑圓掣(icon 保持白色)
12. **Blog 列表/文章頁**:serif 標題、髮絲線、琥珀 accent,跟新 tokens
13. **SectionHeading**pill eyebrow → 琥珀短線+細字眉題;預設左對齊
## 5. 驗證
- `npm run build` 通過
- `npm run dev` 目測:RWD、錨點、FAQ accordion、WhatsApp link、無 hydration error
## 6. 文件同步
- `src/AGENTS.md`token 名單更新(移除 `sky``bg.hero`;加入 `ink`
- `src/components/site/AGENTS.md`:樣式慣例更新(editorial 風、禁用漸層/膠囊/陰影卡)
@@ -0,0 +1,302 @@
# 盈豐太陽能工程有限公司 — 官網設計規格 (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
- 辦公地址
- 電業承辦商牌照號碼
- 真域名
- 真實工程相片(可後補)