Files
yingfungsolar/src/AGENTS.md
T

9.7 KiB
Raw Blame History

src/AGENTS.md

Purpose

src/ 係全疊應用程式碼:Astro 路由、React/Chakra 前台 UI、D1/Drizzle 資料層、基礎工具,以及 theme 同 layout。

Ownership

  • 擁有 src/ 全層,亦直接擁有以下冇獨立 child doc 的部分:
    • theme/system.ts — Chakra systemtokens / semanticTokens / fonts / globalCss),前台顏色同字體的唯一來源。現行設計:editorial 極簡風(暖米白 #FAF8F4 底、琥珀金 brand accent、墨黑 ink、Noto Serif HK 標題),詳見 docs/superpowers/specs/2026-09-11-editorial-redesign-design.md
    • layouts/Base.astro — 前台 SEO headcanonical / OG / Twitter / theme-color / JSON-LD jsonLd prop / sitemap link)+ Noto Sans HK(非阻塞載入,media="print" onload + <noscript> fallback)+ 同意後先載入嘅 analytics(gaId / metaPixelId props,見下面 Analytics & consent)。
    • layouts/AdminLayout.astro — 後台外框:墨黑左側 sidebar(/admin 總覽、內容管理、系統分組)+米白內容區,純 CSS、色值集中喺 CSS variables--ink / --brand / --bg 等),手機用純 CSS checkbox 漢堡開合;同時保留 R2 上傳 script(ImageField 依賴 .image-url / .image-preview / .image-status)。
    • config.ts — build-time 靜態頁用的 SITE_NAME / SITE_TAGLINE(可管理內容一律放 D1,唔放呢度)。
    • middleware.ts — 保護 /admin:設 locals.isAdmin,無 ADMIN_PASSWORD 回 503,未登入導向 /admin/login
    • env.d.tsApp.Locals.isAdmin 型別宣告。
    • schemas/ — Zod 驗證層:admin 表單輸入(post / content / case / settings / ai / keyword)同 AI 輸出格式;配合 lib/form.tsparseFormlib/ai.ts 的生成流程使用(lib/ 細節由 lib/AGENTS.md 擁有)。
    • pages/ — 路由層同 /admin 後台(詳見下面 Routes & SSR / Admin,因 Astro 限制冇獨立 child doc)。
    • components/admin/ImageField.astro — 後台圖片欄位(URL text input + 揀檔上傳/預覽);client 端縮圖同 fetch /admin/upload 嘅 script 喺 layouts/AdminLayout.astro

Local Contracts

  • 架構Astro 7output: "static" + per-page SSR+ @astrojs/react + Chakra UI v3Emotion),單一 Cloudflare Worker。
  • 環境變數:一律 getEnv()src/lib/env.ts)。Astro v6 起已移除 Astro.locals.runtime.env
  • 資料流.astro 頁面 → getDb(getEnv().DB)src/data/content.ts 查詢 → props 傳畀 React island。元件唔直接讀 DB。
  • 語言:所有 UI 文案、註解、後台文案都係繁體中文(廣東話),網站唔做雙語。
  • 產生檔唔好手改dist/.astro/.wrangler/worker-configuration.d.ts

Routes & SSRpages/

  • 預設靜態astro.config.mjsoutput: "static"。要讀 D1 或 request-time 資料的頁面/endpoint 必須在檔案內寫 export const prerender = false
    • 目前 SSRindex.astroabout.astroprivacy.astroblog/index.astroblog/[slug].astroadmin/**media/[...key].tssitemap.xml.ts
    • 保持靜態:robots.txt.ts
  • 環境變數:只用 getEnv(),且只可喺 prerender = false 的頁面/endpoint 用。
  • 前台動態頁:讀 D1 → 傳 props 畀單一 React islandclient:idle,內容仍 SSR 出 HTML),並設邊緣快取 Cache-Control: public, s-maxage=60, stale-while-revalidate=300
  • 404blog/[slug].astro 找唔到文章 → 設 Astro.response.status = 404 並 render noindex 頁。
  • Endpoint:用 APIRoutesitemap.xml.ts 由 D1 讀已發布文章(updatedAt<lastmod>)並設 s-maxage=3600
  • 圖片 endpoints/admin/uploadPOST,受 middleware 保護,寫入 R2 MEDIA);/media/[...key]GET,公開讀 R2 出圖,設 Cache-Control: public, max-age=31536000, immutable 同 ETag304)。
  • AI 生成(同步)/admin/ai 的生成喺 admin POST 內同步 await 完成先 redirect。如日後要改做背景處理,可用 Astro.locals.cfContextCloudflare ExecutionContext)嘅 waitUntil,唔使改現有流程。
  • SEO:用 Base.astrocanonical / OG / sitemap 全部靠 astro.config.mjssite(現為佔位 https://example.com,上線前要改)。所有頁面都要有單一 h1section 標題用 h2、項目用 h3,唔可以跳級(heading 語意一律用 Chakra as,唔可以淨靠字級)。JSON-LD 由 lib/schema-org.ts 砌,經 Base.astrojsonLd prop 輸出:首頁 LocalBusiness + FAQPage、文章 BlogPosting + BreadcrumbList
  • ID 放 D1GA4 / Meta Pixel 的 ID 存 site_settingsga4_measurement_id / meta_pixel_idadmin /admin/settings 可改);空字串=唔載入,冇 enabled boolean。因為係通用 key-value唔使 migration,只需 scripts/seed.sql 有 default。
  • 注入方式Base.astro 收 optional props gaId / metaPixelId;只有 SSR 頁讀到 D1 再傳落去(靜態頁要傳就必須轉 prerender = false)。GA4 / Meta script 一律喺 consent 之後由 inline JS 動態 append,未同意前唔會有任何追蹤請求或 Cookie(亦 Meta <noscript> pixel)。
  • Consent:單一接受/拒絕,存 localStorage key cookie_consentgranted / denied);banner 同載入邏輯都喺 Base.astro(純 HTML/CSS + is:inline,唔用 React)。已同意者每次載入即追蹤。
  • /privacypages/privacy.astroSSR)記錄 Cookie / GA4 / Meta 用途,並提供「重設 Cookie 偏好」清除 localStorage
  • 免維護原則:唔使抄參考專案嘅 singleton 表/APIReact 動態注入(本站係 MPA,每次載入=一次 pageview)。

Adminpages/admin/

  • 所有 /admin 路由必須 export const prerender = false
  • 視覺:全部用 AdminLayout.astro 的墨黑 sidebar shell,色值一律用其 CSS variables(唔好硬編色)。/admin 係總覽 dashboard。
  • 認證middleware.ts 統一處理;登入喺 admin/login.astrocheckPassword + createSession),登出喺 logout.ts
  • UI:全部用 AdminLayout.astro,純 Astro SSR 表單(POST + formData),唔引入 React / Chakra。
  • 流程:每個 POST 處理完 Astro.redirect 返對應列表頁;/admin/ai 用 POST/Redirect/Get + ?ok=<key> + okMessages 顯示成功提示(避免重複提交)。成功提示用 .notice(唔好再用 .badge.published)。
  • 總覽index.astro/admin)係 dashboard,資料由 data/content.tsgetDashboardData(db) 提供(統計卡/待辦提示/最近更新文章/系統狀態);AI secrets 由頁面層 getEnv() 讀。
  • 表單驗證:所有 admin 表單經 parseForm(form, schema)src/schemas/),失敗時以 errors 逐欄顯示,唔好手寫逐欄檢查。
  • 通用動作add / save / delete / up / down(排序以交換 sortOrder 實作)。
  • 通用內容編輯器content/[kind].astrokind ∈ service | feature | step | faq(見 db/schema.tsCONTENT_KINDS),欄位標籤由檔案內 META 定義。
  • 網站設定settings.astrodata/settings-fields.tsSETTINGS_GROUPS / ALL_SETTING_KEYS 產生表單,逐 key upsert。
  • 文章:列表喺 posts.astro/admin/posts)、編輯喺 post/[id].astroid === "new" 為新增);slug 自動 slugify 並用 uniqueSlug 去重。文章存/刪後 redirect 去 /admin/posts
  • AI 生成ai.astro/admin/ai)管 AI 設定 + 關鍵字佇列,同步呼叫 generateBlogPost;成功會 redirect 去新草稿 /admin/post/<id>。生成按鈕用 inline onsubmit 顯示「生成中…」。
  • 圖片:圖片欄位(settings 的 hero_image / og_imagecases.imageUrlposts.coverImage)用 components/admin/ImageField.astro,可揀檔即時上傳去 R2(binding MEDIA),亦可貼 URLclient 端縮到最大寬 1600px 並轉 WebP 先上傳。上傳 endpoint /admin/upload(受 middleware 保護,scope ∈ settings | cases | posts、JPG/PNG/WebP/GIF、上限 8MB),出圖 endpoint /media/[...key](公開、immutable cache)。換圖/刪除時由 lib/media.tsdeleteMedia 清舊 R2 檔。
  • 前台可見性靠 statuspublished / draft);列表頁顯示全部,前台只顯示 published。

Work Guidance

  • 改前台視覺先睇 theme/system.ts 的 tokens,優先重用語意 token,唔好散落硬編色值。
  • 新增 endpoint 或 SSR 頁後,確認 prerender = false 同相應快取 header 都有。
  • 新增一個內容欄位:先改 db/schema.tsnpm run db:generate,再改對應 schemas/ 輸入 schema、admin 表單同 data/content.ts
  • 唔好喺 src/pages/.md 文件(例如 AGENTS.md):Astro 會將佢變成公開路由(例如 /AGENTS/admin/AGENTS)。Astro 只支援用 _ 前綴豁免,但同 DOX 的 AGENTS.md 命名衝突,所以 pages/ 的合約一律寫喺本文件。其餘 src/ 子目錄的 AGENTS.mddata/db/lib/components)唔會被路由。

Verification

  • npm run build(唯一的 build/type 驗證;冇 test/lint/typecheck script)。
  • npm run dev(:4321)目測前台/Blog/後台;測 /blog/[slug] 404、登入/登出流程。

Child DOX Index

Path Scope
components/site/AGENTS.md 前台 React island 與 Chakra UI 元件
data/AGENTS.md D1 讀取查詢層與後台設定欄位定義
db/AGENTS.md Drizzle schemamigration 的唯一來源)
lib/AGENTS.md auth / env / db / form / media / ai / markdown 基礎工具