Commit Graph
46 Commits
Author SHA1 Message Date
hoelee c1aa62ecca docs(project-state): E6 freshness proven end-to-end — deploy live 67s after push through a 2h edge TTL
Deploy / build (push) Successful in 45s
2026-10-17 22:57:28 +08:00
hoelee e6dee0dd57 docs(project-state): E3 queue 10 -> 69 with draft/HTTP guards, E6 edge caching measured working (Cache Rule HIT + purge proven in the run log)
Deploy / build (push) Successful in 59s
2026-10-17 22:55:37 +08:00
hoelee 112cf7de62 docs(project-state): E3 dev.to syndication automated — first cross-post live, daily cron installed
Deploy / build (push) Successful in 43s
2026-10-17 22:34:39 +08:00
hoelee 00c6c792fa docs(project-state): og-default rejection + Desktop design brief, new E9 (fonts the site never loads)
Deploy / build (push) Successful in 38s
2026-10-17 15:03:48 +08:00
hoelee 18fa79fa43 docs(project-state): 2026-10-17 re-check — E4/E5 closed, og-default rewritten, the held churn post, the nginx 301 scheme fix, GitHub mirror re-synced
Deploy / build (push) Successful in 43s
2026-10-17 14:36:58 +08:00
hoelee f4b2ce9658 docs(project-state): B4 entry (photo, About rewrite, llms.txt) and what is still open
Deploy / build (push) Successful in 52s
2026-10-16 22:17:14 +08:00
hoelee f4008d9e8b feat(structure): compact archive + tag pages + hero/featured, and fix site search
Deploy / build (push) Failing after 13m52s
Found a real bug while verifying the nav search: /pagefind/pagefind.js is an ES
module that defines no window.Pagefind, but Search.astro loaded it with a classic
<script src> and read window.Pagefind — so every query answered "Search is
unavailable." (confirmed live before the fix). Now a dynamic import; the specifier
must be a variable or Rollup resolves it at build time and the build fails.

Measured before/after in a real browser:

- archive /posts/ + /zh/posts/: 18,220px -> 3,788px (71 rows at 44px, grouped by
  year) with a client-side filter (title/tags/description text, category chips,
  14 tag chips, zero requests). Tested: "nginx" -> 6 rows, chip devops -> 28.
- tag pages for tags with >= 3 posts. Measured 235 distinct tags (an earlier brief
  claimed 74), 156 used exactly once — pages only where a topic exists: 40 tags ->
  80 pages, build 165 -> 245 pages. Pills link only when a page exists.
- homepage + ZH homepage: hero (288px) with the real scale claim, three CTAs, a
  fixed Featured 4 (scale -> automation -> observability -> a delivered result),
  Latest 10 -> 6. ZH hero had linked "关于我" to the English /about/.
- long code blocks collapse above 420px with an Expand button + gradient, copy
  button still copies the whole block (verified on the 1010px block).
- search is visible ("⌕ Search /" pill, "/" plus the existing Ctrl/Cmd+K) and the
  zero-result screen offers topic chips instead of a dead end.

Docs: project-state B3 entry, ops-runbook Pagefind gotcha.
2026-10-16 21:18:25 +08:00
hoelee 874c434576 fix(i18n,404,nginx): broken-windows batch B2 from the external review
Deploy / build (push) Successful in 3m59s
All items measured before/after with curl, on the origin and through Cloudflare:

- /posts/zh/ answered 403 (directory with no index) -> nginx 301 to the new archive
- /zh/posts/ 404'd -> new src/pages/zh/posts/index.astro (build 163 -> 165 pages)
- ZH nav pointed "关于" at /zh/ and "文章" at /zh/ -> /zh/about/ and /zh/posts/
- og:locale was "en" on every Chinese page -> zh_CN, plus og:locale:alternate on
  both languages (EN pages now advertise zh_CN as well)
- hreflang "zh" -> "zh-Hans"; <html lang> on ZH pages -> zh-Hans
- no 404 page existed -> src/pages/404.astro, served by nginx with a 404 status so
  crawlers skip it, offering search + archive + the 3 newest posts
- JSON-LD Person gained worksFor (Hoelee Enterprise); image still omitted until the
  author photo exists rather than pointing at a placeholder

nginx: config moved from the stock image file to a host bind mount
(/mnt/user/docker/nginx-hoelee-blog/conf.d/default.conf, Portainer stack 247 on
endpoint 3), validated with nginx -t in a throwaway container before the redeploy.
It also sets /_astro/* to immutable 1-year (hashed names) and HTML to
must-revalidate; unhashed /og/*.png and /banners/*.png keep the default TTL on
purpose. Note: the public HSTS and 16-day asset TTL come from Cloudflare zone
settings, not from this nginx.

Docs: ops-runbook.md (the nginx layer + why each rule), project-state.md (B2 entry
and the two open Cloudflare items my token cannot write).
2026-10-16 20:50:26 +08:00
hoelee f364084284 perf(images): WebP banners, text-only related cards, resized list thumbnails
Deploy / build (push) Successful in 56s
Measured before/after with headless Chrome + CDP (not by eye):

- article banner: <picture> WebP q78 with the PNG as fallback, because the PNG
  must stay for og:image (social scrapers do not reliably render WebP cards).
  70 banners: 6.02 MB -> 2.52 MB (42%). JPEG measured *larger* than PNG here
  (q85 = 129%) — the art is flat terminal-style with sharp text edges.
- post page related cards: dropped four 1200x630 PNGs (183 KB) to display
  526x276 where the embedded code is illegible; now text-only cards with a
  category badge, date and reading time.
- list thumbnails (home + archive): new /og/thumb/<name>-{400,800}.webp served
  via srcset/sizes. Rows display at ~398px but were pulling full 1200x630 PNGs.
  Homepage thumbnails ~450 KB -> 62 KB; archive (71 rows) ~3.2 MB -> 436 KB.
- desktop banner capped at 720px centred: 67% -> 45% of a 900px viewport,
  keeping the art intact instead of cropping it.

Post page totals: images 277 KB -> 38 KB; page height 5758 -> 5065 (desktop)
and 9423 -> 8807 (mobile). Build: 163 pages.

Script: scripts/optimize-images.py; policy: docs/design-guide.md §3; runbook
step added to docs/ops-runbook.md.
2026-10-16 17:11:27 +08:00
hoelee 9462ab2373 docs(project-state): E4 — /posts/zh/ answers 403 (no ZH archive route), measured while publishing
Deploy / build (push) Successful in 22s
2026-10-16 13:49:22 +08:00
hoelee 285905caae docs(project-state): B2o published (08fa7a9) — 16 live URLs 200, feed positions, sitemap 163 URLs
Deploy / build (push) Successful in 22s
2026-10-16 13:48:47 +08:00
hoelee 636e6f9624 docs(project-state): B2o — the four surviving posts written and dated; the other topics dropped with the user's instruction recorded
Deploy / build (push) Successful in 31s
2026-10-16 13:42:57 +08:00
hoelee db1e75c3b1 docs(project-state): B2l published (7b001dc) + B2n the backdated silent-JS post held for review
Deploy / build (push) Successful in 27s
2026-10-16 13:25:34 +08:00
hoelee 609fc75609 docs(project-state): the LinkedIn post is deleted, not parked; two new candidates from the UI/i18n work
Deploy / build (push) Successful in 14s
2026-10-16 13:20:10 +08:00
hoelee 27d3dca3c3 docs(project-state): B2l/B2m — one post parked as a draft, and why neither held post may be backdated
Deploy / build (push) Successful in 25s
2026-10-16 13:13:58 +08:00
hoelee f037aefff2 docs(project-state): B2l + B2m — the drei posts held for review, and the next-session topic queue
Deploy / build (push) Successful in 26s
2026-10-16 12:47:35 +08:00
hoelee c2f8452372 docs(project-state): B2k — the ef3f520 follow-up and the private Gitea mirror of the rewrite
Deploy / build (push) Successful in 15s
2026-10-06 17:27:25 +08:00
hoelee dca84a8ca5 docs(project-state): Step B2k — the two reader/gateway posts, the corrected upstream facts, and the backdating constraint
Deploy / build (push) Successful in 18s
2026-10-06 17:24:40 +08:00
hoelee f744cecd67 docs(project-state): Step B2j — the one-hostname post, and the tracker now wired into three sites
Deploy / build (push) Successful in 13s
2026-09-30 04:56:16 +08:00
hoelee 10500a667b docs(project-state): Umami tracker wired into the blog + digikedai, verified with a real browser; record the headless-UA pitfall
Deploy / build (push) Successful in 29s
2026-09-29 06:44:17 +08:00
hoelee e4a2da29db docs(project-state): open ^/mcp on the stats proxy provider (public MCP with Bearer key) + record the verification
Deploy / build (push) Successful in 33s
2026-09-29 06:23:42 +08:00
hoelee b7ecd27076 docs(project-state): correct the SSO rollback note (gate container is stopped, not running)
Deploy / build (push) Successful in 19s
2026-09-29 05:54:35 +08:00
hoelee 88560a8afe docs(project-state): E1 — SSO gate in front of stats.hoelee.com (authentik proxy provider pk 64, per-app flow auth-stats, skip-path tracker); record the forward_single-vs-proxy pitfall, the outpost config lag, and the post-cut-over tracker verification
Deploy / build (push) Successful in 37s
2026-09-29 05:51:41 +08:00
hoelee c5e10a0e70 docs: correct the dashboard-access note — one hostname is enough (app login + 2FA, or cookie SSO with skip-paths); a second hostname is the SaaS-scale ingest-vs-app split
Deploy / build (push) Successful in 18s
2026-09-29 05:21:56 +08:00
hoelee 8f3befaf72 docs: stats.hoelee.com hardening (A+B) — rotate password/APP_SECRET, add the umami-gateway, dashboard LAN-only, tracker verified end-to-end
Deploy / build (push) Successful in 21s
2026-09-29 05:12:31 +08:00
hoelee ca02aaa624 docs: stats.hoelee.com is live via DNS+DSM reverse proxy (not CF) — record the exposure path, the client-IP header fix, and the open default-credential item
Deploy / build (push) Successful in 34s
2026-09-29 04:35:41 +08:00
hoelee 2beea7b219 docs: record the self-hosted Umami deployment (E1) and what is still blocked on Cloudflare
Deploy / build (push) Successful in 23s
2026-09-29 04:16:57 +08:00
hoelee b0ada17fa7 docs: live re-audit (2026-09-29) + Phase E distribution backlog
Deploy / build (push) Successful in 29s
Re-checked the Sept research against the live site and the repo:
- 53 posts x 2 languages, 127 sitemap URLs, 133/133 internal links 200
- Mark C1 (per-post OG), D1 (search), B2b (draft bank) as done — they were stale as open
- New Phase E (top of the queue): E1 analytics (CF Web Analytics + GSC), E2 main-site ->
  blog link (deferred to the www.hoelee.com overhaul), E3 dev.to syndication, E4 ZH nav +
  /zh/posts/, E5 og:locale, E6 Cloudflare HTML caching, E7 volume guardrail, E8 hygiene
- New section 4: measured evidence table; conventions section renumbered
2026-09-29 03:07:51 +08:00
hoelee 95b21e3456 Add 5 posts (EN + ZH): fully on-chain SVG NFTs, the CRLF art trap, a Chainlink VRF v2.5 lottery, page-by-page PDF verification, JPA @Version
Deploy / build (push) Successful in 20s
Five posts with custom OG + banner and hire CTAs. Three are web3, giving
that category its first posts — /categories/web3/ previously 404'd while the
index advertised it as '0 posts - coming soon'.

Backdated where the work genuinely is older: the foundry-nft and
hardhat-smartcontract-lottery commits date to 2024-08-15..19, so those two
posts fill the empty 2024-10 and 2024-12 archive months with updatedDate
holding the real date. The two 2026-08-19 posts use their real work date.

TERMINALS/BANNERS entries for all five slugs are committed this time (both
generators were clean; diffs verified purely additive).
2026-09-29 02:41:58 +08:00
hoelee 9889ef58f8 Backdate 2 of the 6 posts dated 2026-09-29 into empty archive months (EN + ZH)
Deploy / build (push) Successful in 18s
2026-09-29 01:54:39 +08:00
hoelee 48472e0daa Add 3 posts (EN + ZH): the Synology Spreadsheet API container, the 401-with-correct-password gotcha, and reading a container's own API docs
Deploy / build (push) Successful in 24s
2026-09-29 01:43:00 +08:00
Hermes Agent d88a5f6f2c docs: record the two agent-safety/CDP posts in the project state (Step B2f)
Deploy / build (push) Successful in 29s
2026-09-29 01:40:57 +08:00
hoelee e8c5124db1 Add 4 monitoring posts (EN + ZH): smartctl exit 32, Grafana no-data variable, percentage alert thresholds, one Prometheus for 3 hosts
Deploy / build (push) Successful in 28s
Backdated into the 2026-03-25 -> 2026-09-04 archive gap (pubDate 2026-04-14/05-17/06-24/07-29)
with updatedDate 2026-09-29 holding the real date, so sitemap lastmod stays honest.
Custom OG + banner per post, hire CTA, language switch verified.
2026-09-29 01:37:23 +08:00
hoelee d588e9691b docs: record the two SSO posts in the project state (Step B2e)
Deploy / build (push) Successful in 34s
2026-09-29 01:15:48 +08:00
hoelee 8dbf124437 Fix pubDate to the actual publish date (2026-09-29) for the Chrome tabs post
Deploy / build (push) Successful in 17s
2026-09-29 01:12:42 +08:00
hoelee 893675e6a3 Add post: Why Chrome Forgets Its Tabs in a Container (EN + ZH)
Deploy / build (push) Successful in 17s
- docker/Chrome/CDP gotcha: the container kills the browser, so it never exits
  cleanly and no restore mechanism fires (flag, Preferences, managed policy all
  verified failing) -> 60s snapshot + replay keeper
- also covers the stale Singleton* lock and custom-cont-init.d permission traps
- custom OG + banner art, EN + ZH, backlog B2 updated
2026-09-29 01:10:39 +08:00
hoelee 1951b02df8 docs: record the dependency-vetting post in the project state (Step B2d)
Deploy / build (push) Successful in 16s
2026-09-29 01:09:39 +08:00
hoelee a77fb0b5d3 docs: record the English-mode post in the project state
Deploy / build (push) Successful in 28s
2026-09-29 01:06:14 +08:00
hoelee 378aff24d0 docs: check off Workbench/MariaDB gotcha post (B2)
Deploy / build (push) Successful in 16s
2026-09-20 04:20:45 +08:00
hoelee a9a91a25d4 Draft bank: 2 CodeIgniter posts (EN+ZH), held unpublished
Deploy / build (push) Successful in 18s
Two finished posts written from the numerology-report migration work, kept as
draft: true so they build no pages and appear in no listing until published.
Content bank for weeks when there is nothing fresh to write.

- migrating-codeigniter-iis-to-openlitespeed (engineering)
  IIS -> OpenLiteSpeed/CyberPanel. The two fatals that only appeared once the
  authentik SSO gate was gone, the docroot public/ separation, and the
  loopback self-call that becomes a real outbound HTTPS request on LiteSpeed.
- upgrading-codeigniter-46-to-47 (notes)
  The two fatal config properties NOT in the official upgrade guide
  (permittedURIChars, jsonEncodeDepth), why Composer never merges app/Config,
  and the property-diff script that finds the whole class of problem at once.

Both fill the starved engineering (1 post) and notes categories. project-state.md
records them as Step B2b with the publish checklist.
2026-09-20 04:19:37 +08:00
hoelee ab16b8f935 docs: record RDPGuard/IPBan gotcha post in B2 backlog
Deploy / build (push) Successful in 19s
2026-09-19 19:53:27 +08:00
hoelee 9fa366a0ac Add case study: self-hosted speech-to-text API (EN + ZH)
Deploy / build (push) Successful in 25s
New flagship case study covering a GPU-backed whisper.cpp transcription API
reachable from Windows, iPhone, iPad and Android behind an authenticated
gateway — framed as a service offering with the office-productivity case
(roughly 5x typing throughput, unlimited, audio never leaves the premises).

Content:
- EN + ZH posts (same slug -> auto language switch)
- "Why it matters" opener, hire CTA with clickable WhatsApp + mailto
- Four documented traps: incomplete CUDA component selection, loopback bind
  mistaken for a firewall problem, n8n Code nodes discarding binary + the
  data0 key name, and nginx default.conf hijacking port 80
- Honest scoping of the auth model (access control, not hardened public API)

Assets:
- Custom OG image + 16:9 banner (generator entries appended, not patched
  inside the template-literal maps)

Also marks Mem0 (B1) done and adds B1b to project-state.md.
2026-09-19 07:55:29 +08:00
hoelee 53f1ec5de7 project-state: mark C3 done, C4 partially done (zh categories live, zh posts pending)
Deploy / build (push) Successful in 18s
2026-09-14 00:14:56 +08:00
hoelee a9554212a1 Add post: Why Telegram Bot Notifications Die (IPv6/DNS/multipart debugging)
Deploy / build (push) Successful in 36s
2026-09-09 05:45:10 +08:00
hoelee f0fce15dee docs: update project-state, add post-guideline reference
Deploy / build (push) Successful in 11s
- Refresh project-state.md with all completed work this session
- Add docs/post-guideline.md (title case, locale structure, frontmatter, publish flow)
- Reference it in README + hoelee-blog skill
2026-09-06 07:08:05 +08:00
hoelee e0d4b0fbb7 feat: locale routing (en flat, zh subfolder), language switcher, dark default
Deploy / build (push) Successful in 11s
- Derive lang from folder (posts/zh/* -> zh, else en); remove lang: frontmatter
- Change post route to [...slug] to capture nested zh paths
- Add nav language switcher (EN <-> 中文) + /zh/ landing page
- Default theme to dark (light opt-in via toggle)
- Translate hello-world-zh placeholder into English intro post
- Update case study: docker-compose sample + real install gotchas (commit history)
- Add docs/project-state.md (Tier 1/2/3 backlog)
2026-09-06 06:37:34 +08:00