|
1 | | -## Zakk Blog |
2 | | - |
3 | | -Multi-language personal site built with [Hugo](https://gohugo.io/) + [Blowfish](https://blowfish.page/) theme. |
4 | | - |
5 | | -### Tech Stack |
6 | | -- Hugo static site (content in English / 繁體中文 / 简体中文) |
7 | | -- Blowfish theme with custom partial overrides & shortcodes |
8 | | -- Custom Cloudflare Stats Worker (PV / UV counting, batch list queries, popular posts via D1) |
9 | | -- Cloudflare Pages / CDN + custom domain assets |
10 | | - |
11 | | -### Directories |
12 | | -| Path | Purpose | |
13 | | -|------|---------| |
14 | | -| `content/` | Markdown content (posts, about, timeline, localized `_index` files) | |
15 | | -| `layouts/` | Custom partials, list templates, shortcodes (e.g. `topPosts`) | |
16 | | -| `assets/js/` | Front-end ES modules processed by Hugo Pipes (`cloudflare-stats.js`, `cloudflare-top.js`) | |
17 | | -| `i18n/` | Translation bundles (adds `stats.*` keys for popular posts widget) | |
18 | | -| `cloudflare-stats-worker/` | Worker + D1 schema & infra docs | |
19 | | - |
20 | | -### Cloudflare Stats Integration |
21 | | -The worker exposes: |
22 | | -- `GET /api/count?url=/path/` increment + return PV/UV (page + site) |
23 | | -- `GET /api/batch?urls=/a,/b` batch read up to 50 paths |
24 | | -- `GET /api/stats?url=/path/` read only (no increment) or omit `url` for site totals |
25 | | -- `GET /api/top?limit=5&min_pv=10` popular posts (D1 backed) |
26 | | -- `GET /health` health & version |
27 | | - |
28 | | -Front-end scripts auto-detect placeholders by ID prefix `views_` and `[data-stats-site]` attributes. Popular section is rendered via the `{{< topPosts >}}` shortcode inserting a container with `data-stats-top` consumed by `cloudflare-top.js`. |
29 | | - |
30 | | -### Development |
| 1 | +## Zakk Blog / 雙語部落格 |
| 2 | + |
| 3 | +Personal bilingual site (English / 繁體中文 / 简体中文) powered by [Hugo](https://gohugo.io/) + [Blowfish](https://blowfish.page/). Clean content first; minimal custom code kept inside this repo. |
| 4 | + |
| 5 | +### ✨ Features |
| 6 | +- Multilingual content & navigation |
| 7 | +- Lightweight PV/UV stats (self‑hosted Cloudflare Worker + KV + D1) |
| 8 | +- Popular posts widget (server sorted by D1 `/api/top`) |
| 9 | +- Batch list page stats (reduces requests) |
| 10 | +- Fully static build deployed via Cloudflare Pages |
| 11 | + |
| 12 | +### 📂 Structure (kept small) |
| 13 | +| Dir | Description | |
| 14 | +|-----|-------------| |
| 15 | +| `content/` | Articles, about page, timeline, localized `_index.*.md` | |
| 16 | +| `layouts/` | Only necessary overrides (partials, shortcode `topPosts`) | |
| 17 | +| `assets/js/` | Front-end logic: `cloudflare-stats.js`, `cloudflare-top.js` | |
| 18 | +| `i18n/` | Translation files (adds `stats.*` keys) | |
| 19 | +| `cloudflare-stats-worker/` | Worker project + D1 schema + verify scripts | |
| 20 | + |
| 21 | +### 🧮 Stats API (Worker) |
| 22 | +| Endpoint | Purpose | |
| 23 | +|----------|---------| |
| 24 | +| `/api/count?url=/path/` | Increment + return page + site PV/UV | |
| 25 | +| `/api/batch?urls=/a,/b` | Read many pages (no increment) | |
| 26 | +| `/api/stats?url=/path/` | Read single page (no increment) | |
| 27 | +| `/api/stats` | Site totals only | |
| 28 | +| `/api/top?limit=5` | Popular posts by PV (D1) | |
| 29 | +| `/health` | Health & version | |
| 30 | + |
| 31 | +Front-end auto-detects `span[id^="views_"]` and `[data-stats-site]` placeholders; no inline framework needed. |
| 32 | + |
| 33 | +### 🚀 Develop |
31 | 34 | ```bash |
32 | | -# Run Hugo local server |
| 35 | +# Start site |
33 | 36 | hugo server -D |
34 | 37 |
|
35 | | -# (Optional) Dev the Cloudflare worker in parallel |
| 38 | +# (Optional) Worker dev (in sub dir) |
36 | 39 | cd cloudflare-stats-worker |
37 | 40 | wrangler dev --local --persist-to=./.data |
38 | 41 | ``` |
39 | 42 |
|
40 | | -### Popular Posts (D1) |
41 | | -`cloudflare-stats-worker/schema.sql` defines `page_stats` table. Each `/api/count` syncs PV/UV into D1 (best-effort). The `/api/top` endpoint reads and caches results (60s edge cache). |
| 43 | +### 🔄 Deploy (manual outline) |
| 44 | +```bash |
| 45 | +git add . |
| 46 | +git commit -m "chore: content & stats update" |
| 47 | +git push origin main # Triggers Cloudflare Pages build |
42 | 48 |
|
43 | | -### i18n Additions |
44 | | -Added keys under `stats.*` used by the popular widget: |
45 | | -``` |
46 | | -stats.popularTitle |
47 | | -stats.loading |
48 | | -stats.error |
49 | | -stats.empty |
| 49 | +# Deploy worker (if code changed) |
| 50 | +cd cloudflare-stats-worker |
| 51 | +wrangler deploy |
50 | 52 | ``` |
51 | 53 |
|
52 | | -### License |
| 54 | +### 🌐 i18n Keys Added |
| 55 | +`stats.popularTitle`, `stats.loading`, `stats.error`, `stats.empty` |
| 56 | + |
| 57 | +### 📜 License |
53 | 58 | MIT |
54 | 59 |
|
55 | | ---- |
56 | | -See `cloudflare-stats-worker/README.md` for the full worker / cost / architecture documentation. |
| 60 | +More infra / cost notes: see `cloudflare-stats-worker/README.md`. |
0 commit comments