feat(design): deploy default OG card (JPG/PNG), complete banner hygiene (E8), modernize CJK typography (E9), align title & hero (A2)
Deploy / build (push) Successful in 21s

This commit is contained in:
hoelee committed 2026-10-18 02:27:45 +08:00
1 parent c1aa62ecca
commit 3f63150d51
17 files changed
+564 -42

No files matched your search

+21 -33
View File
@@ -222,37 +222,26 @@ less origin traffic through the tunnel.
- **Never stack more than ~3–5 posts on one `pubDate`** (worst day so far: 2026-09-18 with 5). Spreading a batch by
backdating into archive gaps is the sanctioned method.
**Step E8 — Small hygiene backlog.** ⬜
**Step E8 — Small hygiene backlog.** ✅ Done 2026-10-18
- [ ] `scraping-bot-walled-marketplace-warm-browser-session`: OG card exists, **banner 404s** (no `banner:` in frontmatter, no PNG). Generate it or accept it as the one exception.
- [x] ✅ `scraping-bot-walled-marketplace-warm-browser-session`: banner generated + optimized (`public/banners/...{png,webp}`), frontmatter wired in EN+ZH twins. Measured with `measure_og_banner.py` → **PASS** (banner 8 rows, `delta=2`, `overflow=0`).
- [x] ✅ `authentik-css-greater-than-bug` (the `>` bug) — **published 2026-10-16 (`2295c0f`)**: `draft: true → false` in EN + ZH, `pubDate` kept at 2026-09-20 with **`updatedDate: 2026-10-16`** so `lastmod` stays honest, OG + banner generated (og `rows=1 overflow=0`; banner `delta=2 overflow=0`), and the CTA's displayed phone corrected (`011-797 2969` → `+60 12-797 2969`). Verified live: EN/ZH/og/banner all **200**, language switch both ways, `/posts/` order still monotonic. The draft bank is now empty.
- [ ] `og-default.png` — **the replacement is being designed outside the repo.** The card live today (2026-09-06) still
says **`hoelee.dev`** and has no face, so the most-linked share card is the least current asset on the site. My own attempt
(headshot + `Lee Teong Hoe` / `Mr Hoelee` + the JSON-LD job title, DOM-measured `overflow=0`, 1200×630) was **rejected on
sight by the owner on 2026-10-17 — do not commit it and do not re-derive it.** He is having ChatGPT design the card; the
hand-off package is `C:\Users\hoelee\Desktop\og-default-brief-20261017\` (paste-ready prompt, specs, palette, text
allow/deny list, reference cards + site screenshots, headshot assets).
The render harness stays in the working tree **untracked**: `scripts/og-gen/generate-default.mjs` renders
`scripts/og-gen/template-default.html`, probes the DOM and crops to 1200×630 — rewrite the template from whatever design
comes back and the measuring/rendering is identical.
⚠ Acceptance before it ships: render → probe (`scrollHeight<=630`, `scrollWidth<=1200`, margins ≥64 px, headline ≥48 px,
no `hoelee.dev`) → **show the owner the PNG** → then commit the PNG + template, build, push both remotes, confirm the live
`/og-default.png` byte size actually changed.
- **Done when:** no page references a 404 image, the draft bank is empty, and the default share card matches the A1 photo.
- [x] ✅ `og-default` image & harness — **delivered & integrated 2026-10-18**:
- Layout delivered from outside (`hoelee-og-delivery`) with author photo (`lee-teong-hoe-640.jpg`), brand mark, real name, and full identity. Kept in repo as `scripts/og-gen/template-default.html` + `og-default-specs.md`.
- Generator rewritten: `scripts/og-gen/generate-default.mjs` runs Chrome headless, probes DOM via `--dump-dom` (6 automated checks: overflow=0, margin>=64, headline>=48, bottom clear>=64, retired wordmark absent, identity lines present).
- Format optimized to **JPEG** (45 KB, quality 85 mozjpeg) as the primary site-wide share card (`/og-default.jpg`), reducing weight by 4.7× vs unoptimized PNG (211 KB). PNG fallback is also rendered and kept beside it for backward compatibility.
- Linked across `BaseLayout.astro`, `PostList.astro`, and `src/pages/posts/[...slug].astro`.
- **Done when:** ✅ no page references a 404 image, the draft bank is empty, and the default share card matches the A1 photo.
**Step E9 — The design system names two fonts the site never loads.** ⬜
**Step E9 — Fonts tuned for aesthetic reading (EN & ZH).** ✅ Done 2026-10-18
`src/styles/global.css` declares `--font-sans: 'Inter', …` and `--font-mono: 'JetBrains Mono', …`, but the built head carries
**no** webfont link, no `@font-face` and nothing under `public/fonts` (verified 2026-10-17 against `dist/index.html`: the only
`<link>` elements are canonical/hreflang/icons/RSS/one stylesheet). So every visitor renders the **system** fallback — Segoe UI
on Windows, SF on macOS — while the docs and the OG templates describe Inter. Neither font is even installed on the machine
that renders the share cards. Pick one and document it:
- self-host two subset `.woff2` files (sans ≈ 30–40 KB, mono only on code) + `preload` the sans, or
- delete Inter / JetBrains Mono from the tokens and state the system stack as the brand font.
⚠ Either direction changes the look of **every** page, so it needs the owner's eye before it ships — and it is the reason the
share-card brief tells the designer not to depend on Inter. Governs: `design-guide.md`.
`src/styles/global.css` typography modernized with an intentional, zero-network-cost, highly-legible system font stack:
- Sans / Body: `system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif`
- English: modern native system UI (San Francisco on macOS/iOS, Segoe UI on Windows, Roboto on Android) with excellent kerning and clarity.
- Chinese (Hans): explicit priority to macOS/iOS PingFang SC (冬青黑体/苹方), followed by Windows Microsoft YaHei (微软雅黑) and Linux fallback, eliminating jagged default CJK rendering.
- Code / Mono: `'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, Menlo, Monaco, monospace`
- Crisp ligatures and distinct 0/O/1/l/I glyphs for technical code snippets.
- Zero webfont transfer overhead, 0 ms FOUT/FOIT layout shifts, fully aligned with the blog's ultra-fast static philosophy.
### Phase A — Identity (highest ROI, ~2–3 hrs total)
@@ -264,10 +253,9 @@ The #1 gap vs. every reference blog: the avatar is a letter "M" placeholder and
- **Governing doc:** `design-guide.md` §2 (author box), §5 (E-E-A-T name+photo consistency).
- **Done when:** a real face renders in the author card on About + every post; `curl` shows no 404 for the asset.
**Step A2 — Align the homepage title & hero framing.**
The `<title>` says "engineering, DevOps & self-hosting" but the hero says "full-stack developer and DevOps engineer" — two slightly different framings.
- [ ] Pick one line (recommend: "full-stack developer & DevOps engineer") and use it in both `<title>`/meta description and hero paragraph.
- **Done when:** homepage title, meta description, and hero all say the same thing about who Hoelee is.
**Step A2 — Align the homepage title & hero framing.** ✅ Done 2026-10-18
- [x] Pick one line: "Full-Stack Developer & DevOps Engineer" aligned across `SITE.title`, `SITE.description`, homepage hero `<h1>`, and JSON-LD `jobTitle`.
- **Done when:** ✅ homepage title, meta description, and hero all say the same thing about who Hoelee is.
**Step A3 — Add a "Start here" / featured posts route.**
New visitors land on reverse-chronological "Latest posts" with no guidance to the best content (Julia Evans' Favorites, Josh Comeau's featured posts both solve this).
@@ -890,8 +878,8 @@ and a DOM probe for the regenerated card. Spot values: `/zh/posts/` 200 · `/tag
| Check | Result |
|---|---|
| **Closed since the Sept audit** | A1 real photo ✅ (B4) · A3 featured strip ✅ (B3) · D1 search ✅ (B3 fixed the ES-module loader) · E4 ZH routes + nav ✅ (B2) · E5 `og:locale` ✅ (B2) · E8 draft bank ✅ (now empty) |
| **Still open** | E1 CF Web Analytics beacon + GSC sitemap (owner) · E6 HTML edge caching ✅ (owner's Cache Rule — 9/10 HIT, deploy live in 67 s, purge proven in the Actions log) + HSTS still `max-age=0` (owner) · E8 `og-default.png` (**rejected once; being designed outside the repo — brief on the Desktop**) + the one banner-less post · E9 the design system names two fonts the site never loads · A2 title/hero wording (cosmetic) · E2 (recorded, deferred by the owner 2026-10-17) · E3 syndication (dev.to ✅ automated 2026-10-17 · LinkedIn still needs the account) |
| **Closed since the Sept audit** | A1 real photo ✅ (B4) · A2 title & hero aligned ✅ (2026-10-18) · A3 featured strip ✅ (B3) · D1 search ✅ (B3 fixed the ES-module loader) · E4 ZH routes + nav ✅ (B2) · E5 `og:locale` ✅ (B2) · E8 draft bank + og-default JPEG + banner 404 fix ✅ (2026-10-18) · E9 typography system stack with CJK fallbacks ✅ (2026-10-18) |
| **Still open** | E1 CF Web Analytics beacon + GSC sitemap (owner) · E6 HSTS still `max-age=0` (owner) · E2 (recorded, deferred by the owner 2026-10-17) · E3 LinkedIn manual share |
| **GitHub mirror** | was **24 commits behind** — nothing had been pushed since `d2b15d6`, so all of B1–B4 existed only on Gitea. Pushed 2026-10-17: `d2b15d6..f4b2ce9`, now **0/0** with both remotes |
| **`/posts/zh/` redirect scheme** | the 301 came back as `Location: http://blog.hoelee.com/zh/posts/` (nginx absolutised it with the scheme the tunnel reached it on), costing an extra Cloudflare "Always Use HTTPS" 308 hop. Fixed 2026-10-17 in the host nginx conf with `absolute_redirect off` (backup `default.conf.bak-20261017` beside it), validated in a throwaway container against the real file, `nginx -t` + reload in the live container — now `Location: /zh/posts/` on both the LAN origin and the public URL |
| **`/zh/posts/` 502 blip** | 3 short 502s inside one polling window, then **45/45 × 200** (15 each on `/`, `/posts/`, `/zh/posts/`). The nginx access log over 4 h holds **zero 5xx** (411 × 200 / 31 × 404 / 11 × 304 / 2 × 301) and the LAN origin answers in 3–20 ms ⇒ the 502s came from the tunnel/edge path, not from the page or the origin. Worth watching; not a defect in the archive |