74792c595a0961cd303a528b2bbac7be6e97c8bf
盈豐太陽能工程有限公司 — 官網(村屋太陽能)
Astro 7 + React 19 + Chakra UI v3 + Cloudflare Workers + D1 + Drizzle。全部部署喺 Cloudflare,零維運。
一頁式官網(村屋太陽能)+ Blog + 內容管理後台。
功能
- 一頁式官網
/(SSR,讀 D1):Hero、服務、特色、流程、完成案例、FAQ、聯絡 CTA - Blog
/blog、/blog/[slug]:封面卡片列表 + Markdown 文章頁 - 後台
/admin(密碼登入):管理文章、首頁內容(服務/特色/流程/FAQ)、完成案例、網站設定(公司資料/聯絡/Hero/SEO) - AI 生成 Blog
/admin/ai:設定 AI 供應商、維護關鍵字佇列,一按生成完整草稿(DeepSeek 相容 API,可選 Tavily 上網研究) - SEO:canonical、OG/Twitter card、
/sitemap.xml、/robots.txt、結構化語意 HTML - 首頁/Blog 用邊緣快取(
s-maxage),後台改完約 1 分鐘內生效
技術棧
| 層 | 選用 |
|---|---|
| 前端框架 | Astro 7(output: "static" + per-page SSR) |
| UI | React 19 + @chakra-ui/react v3 + @emotion/react(editorial 極簡 theme:暖米白底、琥珀金 accent) |
| Adapter | @astrojs/cloudflare(一個 Worker) |
| DB | Cloudflare D1(SQLite) |
| ORM | Drizzle |
| Auth | HMAC-signed cookie(src/lib/auth.ts) |
| Markdown | marked |
| Icons | lucide-react |
Chakra v3 用 Emotion,SSR 會輸出 inline critical CSS(首屏即有樣式、零 FOUC),client hydrate 後整合到
<head>;已實測 Astro 7 + React 19 無 hydration error。
本機開發
npm install
# 建本機 D1 + 套 migration
npm run db:migrate:local
# 匯入種子資料(同 migration 分開,可重複執行)
npm run db:seed:local
# 開發 server(:4321)
npm run dev
本機後台密碼喺 .dev.vars(ADMIN_PASSWORD=changeme-local,已 gitignore)。
想模擬 production(wrangler):npm run preview。
部署到 Cloudflare
首次設定(一鍵)
npm run login # 瀏覽器授權
npm run setup # 建立 D1 / KV、寫入 wrangler.jsonc、設 secret、套 migration + seed
npm run setup 會逐步問你:要唔要設定後台密碼、要唔要套 migration/seed、要唔要 build + deploy。若 astro.config.mjs 嘅 site 仍然係 https://example.com,會跳過 build + deploy 並提醒你改。
之後更新
改完 astro.config.mjs 嘅 site 做真域名後:
npm run deploy
Git push 自動部署(Cloudflare Workers Builds)
- Cloudflare Dashboard → Workers & Pages → 連接 GitHub repo
- Build command:
npm run build - Deploy command:
npx wrangler deploy - 喺 Dashboard 設 secrets:
ADMIN_PASSWORD、AI_API_KEY、TAVILY_API_KEY
Migration 唔會喺 CI 自動執行:改完 src/db/schema.ts 要手動跑
npm run db:generate → npm run db:migrate(雲端)→ npm run db:seed(如有新 seed)。
AI 生成 Blog
後台 /admin/ai:
- 設定 AI 供應商(OpenAI 相容 Base URL + 模型)、寫作風格、公司背景
- 維護關鍵字佇列(新增 / 略過 / 刪除)
- 「生成草稿」= 自由輸入主題;「生成下一篇」= 攞佇列下一個 pending
- 生成係同步進行(約 10–40 秒),完成後一律存為草稿並跳去文章編輯頁覆核
- 需要 secret:
AI_API_KEY(必需)、TAVILY_API_KEY(如開上網研究)
後台點用
- 去
/admin,輸入密碼登入 - 內容總覽 → 服務 / 特色 / 流程 / 常見問題 / 完成案例 / 網站設定 / AI 生成
- 每個項目可新增、修改、刪除、用 ↑↓ 排序、「已發布 / 草稿」控制前台顯示
- 圖片:直接貼圖片 URL(暫時;之後可換成上傳)
- AI 生成:設定供應商同關鍵字佇列,生成草稿後去文章編輯頁覆核發布
結構
src/
├─ theme/system.ts Chakra theme(tokens / 顏色 / 字體)
├─ components/site/*.tsx 前台 React 元件(Header/Hero/Services/Faq…)
├─ data/
│ ├─ content.ts D1 讀取 + WhatsApp/電話 link helper
│ └─ settings-fields.ts 後台設定欄位定義
├─ db/schema.ts Drizzle schema(posts / site_settings / content_items / cases / blog_keywords)
├─ schemas/ Zod 驗證 schema(表單輸入 + AI 輸出)
├─ layouts/Base.astro SEO head + fonts
├─ layouts/AdminLayout.astro 後台外框
├─ pages/
│ ├─ index.astro SSR 首頁
│ ├─ blog/… Blog
│ ├─ admin/… 後台(含 admin/ai)
│ └─ sitemap.xml.ts / robots.txt.ts
├─ lib/{auth,db,env,form,ai,markdown}.ts
migrations/
├─ 0000_init.sql … Drizzle migrations
└─ seed.sql 種子資料(用 db:seed 另外執行)
scripts/setup.mjs 一鍵 Cloudflare provision
待客戶提供(可喺 /admin/settings 自行更新)
- 真實電話 / WhatsApp / Email / 地址
- 電業承辦商牌照號碼
- 真域名(
astro.config.mjs嘅site) - 真實工程相片(現時用佔位圖)
Languages
TypeScript
50.1%
Astro
45.8%
JavaScript
4.1%