From fbc562f495f5d35a9fe33e195af7245f6d7ba444 Mon Sep 17 00:00:00 2001 From: philipcheung Date: Sun, 13 Sep 2026 20:01:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20GA4=20/=20Meta=20Pixel=20?= =?UTF-8?q?=E8=BF=BD=E8=B9=A4=E8=88=87=20Cookie=20=E5=90=8C=E6=84=8F?= =?UTF-8?q?=E6=A9=9F=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 追蹤 ID 存 site_settings(空字串即關閉),於 /admin/settings 管理 - Base.astro 僅在用戶同意後載入分析工具,未同意前零請求 - 新增 /privacy 私隱政策頁與「重設 Cookie 偏好」按鈕 - 前台 SSR 頁面(首頁、blog、about、privacy)傳入 gaId / metaPixelId - seed 加入預設空值,Footer 加入私隱政策連結 - 同步更新 AGENTS.md 與 README 說明 --- AGENTS.md | 1 + README.md | 35 +++++-- scripts/seed.sql | 4 +- src/AGENTS.md | 14 ++- src/components/site/Footer.tsx | 1 + src/data/AGENTS.md | 2 +- src/data/settings-fields.ts | 15 +++ src/layouts/Base.astro | 173 +++++++++++++++++++++++++++++++ src/pages/about.astro | 15 ++- src/pages/blog/[slug].astro | 2 + src/pages/blog/index.astro | 2 + src/pages/index.astro | 2 + src/pages/privacy.astro | 182 +++++++++++++++++++++++++++++++++ 13 files changed, 434 insertions(+), 14 deletions(-) create mode 100644 src/pages/privacy.astro diff --git a/AGENTS.md b/AGENTS.md index de88885..0c1431b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,6 +25,7 @@ Astro 7 + React 19 + Chakra UI v3,部署在 Cloudflare Workers(單一 Worker - **`wrangler.jsonc` 有佔位 id**:`database_id` / KV `id` 要先用 `db:create` / `kv:create` 產生再貼上,未貼前無法部署。R2 bucket 唔使貼 id,用 `r2:create`(或 `npm run setup`)建立即可,binding 係 `MEDIA`。 - **圖片上傳**:圖片存 Cloudflare R2(binding `MEDIA`、bucket `yingfung-solar-media`),由同一個 Worker 的 `/media/*` 出圖;上傳經 `/admin/upload`,client 端先縮圖轉 WebP。本機靠 `platformProxy` 模擬 R2,雲端要先 `npm run r2:create`。圖片欄位仍可貼 URL;換圖/刪除時 `lib/media.ts` 會清舊 R2 檔。 - **上線前要改 `astro.config.mjs` 的 `site`**:sitemap / canonical / OG 全部靠它(現為 `https://example.com`)。 +- **追蹤分析(GA4 / Meta Pixel)**:ID 存 `site_settings`(`ga4_measurement_id` / `meta_pixel_id`,**空字串=關閉**),喺 `/admin/settings` 改。`Base.astro` 只會喺用戶同意(`localStorage.cookie_consent`)之後先載入,未同意前唔會有追蹤請求/Cookie;`/privacy` 有說明同「重設 Cookie 偏好」。因為係通用 key-value,**冇新 migration**,只需 `scripts/seed.sql` 有 default。 - **後台認證**:`src/middleware.ts` 保護所有 `/admin`,用 HMAC-signed cookie(`src/lib/auth.ts`);未設 `ADMIN_PASSWORD`(本機在 `.dev.vars`,已 gitignore)會回 503。 - **Chakra v3 + Emotion**:前台 React 元件要用 `Provider` / `SiteChrome`(內含 ``),theme 在 `src/theme/system.ts`。Astro 以 `client:load` 掛 island。 - **語言**:UI 文案、註解、後台全部都係繁體中文(廣東話)——新增內容請保持一致;網站只做中文,不做雙語。 diff --git a/README.md b/README.md index f26b21f..aa5bc99 100644 --- a/README.md +++ b/README.md @@ -50,21 +50,38 @@ npm run dev ## 部署到 Cloudflare -### 首次設定(一鍵) +### 1. 先設定網址(部署前一定要做) + +`sitemap` / `canonical` / `OG` 全部靠 `astro.config.mjs` 嘅 `site`,所以**先改佢**: + +```js +// astro.config.mjs +site: "https://your-domain.com", +``` + +想用 Cloudflare 自訂網域(例如 `solar.develop-cat.com`)就順手喺 `wrangler.jsonc` 加: + +```jsonc +"routes": [ + { "pattern": "solar.develop-cat.com", "custom_domain": true } +], +``` + +部署時會自動建立 DNS + TLS,唔使自己開 record。唔加就淨係用 `https://..workers.dev`;亦可以部署後喺 Dashboard → Worker → Settings → Domains & Routes 手動加。 + +### 2. 首次設定(一鍵) ```bash npm run login # 瀏覽器授權 -npm run setup # 建立 D1 / KV / R2、寫入 wrangler.jsonc、設 secret、套 migration + seed +npm run setup # 建 D1 / KV / R2、寫入 wrangler.jsonc 嘅 id、設 secret、可選 migration + seed + build + deploy ``` -`npm run setup` 會逐步問你:要唔要設定後台密碼、要唔要套 migration/seed、要唔要 build + deploy。若 `astro.config.mjs` 嘅 `site` 仍然係 `https://example.com`,會跳過 build + deploy 並提醒你改。 +`npm run setup` 會逐步問你:設定後台密碼?套 migration/seed?build + deploy?若 `site` 仍係 `https://example.com`,會跳過 build + deploy 並提醒你改(改完再 `npm run deploy`)。 -### 之後更新 - -改完 `astro.config.mjs` 嘅 `site` 做真域名後: +### 3. 之後更新 ```bash -npm run deploy +npm run deploy # = npm run build + wrangler deploy ``` ### Git push 自動部署(Cloudflare Workers Builds) @@ -76,6 +93,7 @@ npm run deploy **Migration 唔會喺 CI 自動執行**:改完 `src/db/schema.ts` 要手動跑 `npm run db:generate` → `npm run db:migrate`(雲端)→ `npm run db:seed`(如有新 seed)。 +`seed.sql` 放喺 `scripts/`(唔可以放喺 `migrations/`,否則 `db:migrate` 會連 seed 一齊種)。 ## AI 生成 Blog @@ -110,12 +128,13 @@ src/ ├─ layouts/AdminLayout.astro 後台外框 ├─ pages/ │ ├─ index.astro SSR 首頁 +│ ├─ about.astro 關於(靜態) │ ├─ blog/… Blog │ ├─ admin/… 後台(含 admin/ai、admin/upload 上傳 endpoint) │ ├─ media/[...key].ts R2 圖片出圖 endpoint │ └─ sitemap.xml.ts / robots.txt.ts ├─ components/admin/ImageField.astro 後台圖片欄(URL + 上傳 + 預覽) -├─ lib/{auth,db,env,form,media,ai,markdown}.ts +├─ lib/{auth,db,env,form,media,ai,markdown,schema-org}.ts migrations/ ├─ 0000_init.sql … Drizzle migrations scripts/ diff --git a/scripts/seed.sql b/scripts/seed.sql index 291b833..2857722 100644 --- a/scripts/seed.sql +++ b/scripts/seed.sql @@ -19,7 +19,9 @@ INSERT OR REPLACE INTO site_settings (key, value, updated_at) VALUES ('hero_image', 'https://images.unsplash.com/photo-1509391366360-2e959784a276?auto=format&fit=crop&w=1600&q=80', strftime('%s','now')*1000), ('seo_default_title', '盈豐太陽能工程有限公司 — 香港村屋太陽能一站式服務', strftime('%s','now')*1000), ('seo_default_description', '專營香港村屋太陽能系統:現場評估、合法支架、代辦申請、專業安裝及驗收認證。透明報價,專人跟進,幫你善用天台賺取發電回報。', strftime('%s','now')*1000), - ('og_image', 'https://images.unsplash.com/photo-1509391366360-2e959784a276?auto=format&fit=crop&w=1200&q=80', strftime('%s','now')*1000); + ('og_image', 'https://images.unsplash.com/photo-1509391366360-2e959784a276?auto=format&fit=crop&w=1200&q=80', strftime('%s','now')*1000), + ('ga4_measurement_id', '', strftime('%s','now')*1000), + ('meta_pixel_id', '', strftime('%s','now')*1000); INSERT OR REPLACE INTO site_settings (key, value, updated_at) VALUES ('ai_enabled', '1', strftime('%s','now')*1000), diff --git a/src/AGENTS.md b/src/AGENTS.md index 5b643fc..0e4c2ff 100644 --- a/src/AGENTS.md +++ b/src/AGENTS.md @@ -8,7 +8,7 @@ - 擁有 `src/` 全層,亦直接擁有以下冇獨立 child doc 的部分: - `theme/system.ts` — Chakra system(tokens / 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 head(canonical / OG / Twitter / theme-color / JSON-LD `jsonLd` prop / sitemap link)+ Noto Sans HK(非阻塞載入,`media="print" onload` + `