Files
yingfungsolar/README.md
T
philip-cat fdee1aabd7 Add Zod validation layer and AI blog generation
Introduce a schema-first validation layer and an AI blog generation
feature, plus one-command Cloudflare provisioning.

- src/schemas/ holds Zod input schemas for post, content, case,
  settings, AI, and keywords; parseForm() in src/lib/form.ts validates
  FormData and returns per-field errors.
- Migrate all admin POST handlers to parseForm, showing field-level
  errors and only redirecting once validation passes.
- Add blog_keywords table and posts.focus_keyword (migration 0002);
  uniqueSlug() centralised in src/data/content.ts.
- Add src/lib/ai.ts (OpenAI-compatible chat completions + optional
  Tavily research) and /admin/ai for AI settings, keyword queue, and
  draft generation.
- Add scripts/setup.mjs (npm run setup) to provision D1/KV, set
  secrets, and optionally migrate, seed, and deploy.
- Document AI secrets, Workers Builds deploy flow, and new schemas
  across README and AGENTS docs.
2026-09-11 23:49:18 +08:00

128 lines
5.1 KiB
Markdown
Raw 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.
# 盈豐太陽能工程有限公司 — 官網(村屋太陽能)
**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 D1SQLite |
| ORM | Drizzle |
| Auth | HMAC-signed cookie`src/lib/auth.ts` |
| Markdown | `marked` |
| Icons | `lucide-react` |
> Chakra v3 用 EmotionSSR 會輸出 inline critical CSS(首屏即有樣式、零 FOUC),client hydrate 後整合到 `<head>`;已實測 Astro 7 + React 19 無 hydration error。
## 本機開發
```bash
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)。
想模擬 productionwrangler):`npm run preview`
## 部署到 Cloudflare
### 首次設定(一鍵)
```bash
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` 做真域名後:
```bash
npm run deploy
```
### Git push 自動部署(Cloudflare Workers Builds
1. Cloudflare Dashboard → Workers & Pages → 連接 GitHub repo
2. Build command`npm run build`
3. Deploy command`npx wrangler deploy`
4. 喺 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`(如開上網研究)
## 後台點用
1.`/admin`,輸入密碼登入
2. **內容總覽** → 服務 / 特色 / 流程 / 常見問題 / 完成案例 / 網站設定 / AI 生成
3. 每個項目可新增、修改、刪除、用 ↑↓ 排序、「已發布 / 草稿」控制前台顯示
4. 圖片:直接貼圖片 URL(暫時;之後可換成上傳)
5. **AI 生成**:設定供應商同關鍵字佇列,生成草稿後去文章編輯頁覆核發布
## 結構
```
src/
├─ theme/system.ts Chakra themetokens / 顏色 / 字體)
├─ components/site/*.tsx 前台 React 元件(Header/Hero/Services/Faq…)
├─ data/
│ ├─ content.ts D1 讀取 + WhatsApp/電話 link helper
│ └─ settings-fields.ts 後台設定欄位定義
├─ db/schema.ts Drizzle schemaposts / 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`
- 真實工程相片(現時用佔位圖)