hoelee f364084284
Deploy / build (push) Successful in 56s
perf(images): WebP banners, text-only related cards, resized list thumbnails
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-blog

My personal technical blog — where I write about what I build and learn.

Built with Astro 5 + Markdown, deployed via self-hosted Gitea CI/CD to an nginx container on my unRaid server, served through Cloudflare tunnel + CDN. Live at blog.hoelee.com.

Purpose (read this first)

This blog exists so that when a recruiter, hiring manager, or freelance client Googles "Lee Teong Hoe", they land on a stream of concrete technical work that proves I can build things — plus a clear, trustworthy picture of who I am. It backs the job hunt and the freelance funnel (Upwork / Fiverr / Codeable).

  • 67% of hiring managers check a candidate's online presence before deciding (Stack Overflow 2025).
  • SEO is a long game — while posts rank, the blog doubles as a portfolio and inbound-lead magnet.

Every decision below optimizes for credibility + discoverability + speed of shipping, not monetization or vanity traffic.

Stack

  • Framework: Astro 5 (static output, zero runtime JS by default)
  • Content: Markdown + MDX, versioned in git
  • i18n: English (default) + Chinese (zh) — English-first
  • CI/CD: Gitea Actions → act_runner on unRaid → nginx container
  • Host: nginx on unRaid → Cloudflare tunnel → Cloudflare CDN

Structure

src/
  content/
    posts/          # English posts (flat)
      zh/           # Chinese posts (subfolder -> /posts/zh/<slug>/)
  pages/
    index.astro     # homepage
    posts/[...slug].astro   # post template
    about.astro
  layouts/
    BaseLayout.astro
  lib/
    lang.ts         # derives en/zh from folder path
docs/
  content-guide.md  # what to write, what to avoid (READ before writing a post)
  post-guideline.md # HOW to write it: title case, locale, frontmatter, publish flow
  design-guide.md   # what the design must have, what to avoid (READ before touching UI)
  seo-reference.md  # E-E-A-T / name identity, SEO + GEO checklist, syndication
  ops-runbook.md    # pipeline, publish steps, build pitfalls, health checks
  project-state.md  # enhancement backlog (Tier 1/2/3) — work through one by one

Knowledge guides (my rules of thumb)

Doc When to read
docs/content-guide.md Before writing/planning any blog post — categories, post types, the "hard job → post" template, and the anti-patterns.
docs/post-guideline.md Before writing/editing a post — title case, locale folder structure, frontmatter, publish flow.
docs/design-guide.md Before changing theme, layout, typography, color, or SEO markup.
docs/seo-reference.md Before adding posts/<head> markup or debugging search visibility.
docs/ops-runbook.md Before debugging CI/CD, deployment, or hosting.
docs/project-state.md To see what's next — the prioritized enhancement backlog.

Write a post

  1. Create src/content/posts/<slug>.md (English) or src/content/posts/zh/<slug>.md (Chinese) with frontmatter (see content guide — no lang: field, it's derived from the folder).
  2. Push to main.
  3. CI builds and deploys automatically.

Categories

engineering · devops · ai · web3 · tutorials · case-studies · notes

Conventions

  • Repo publishing order: push to git.hoelee.com (Gitea) first, then GitHub. (My standing convention.)
  • Language: English posts flat in posts/; Chinese posts in posts/zh/; no Malay.
  • Theme: defaults to dark mode (light is opt-in via the toggle).
  • No overclaiming — especially Web3 (learning projects, not production DeFi).
  • Name identity is consistent everywhere: "Lee Teong Hoe" / "Mr Hoelee" + same photo + same sameAs handles across blog, LinkedIn, GitHub, git.hoelee.com.
S
Description
Personal technical blog of Lee Teong Hoe (Mr Hoelee) - full-stack engineering, DevOps & self-hosting, AI automation, and Web3. Built with Astro 5 + Markdown, deployed via self-hosted Gitea Actions CI/CD. English-first, Chinese under /posts/zh/.
https://blog.hoelee.com Readme
86 MiB
0 Stars 1 Watchers 0 Forks
v1.0.0
Latest
2026-09-05 22:46:23 +00:00
Languages
JavaScript 35%
Astro 27.4%
Python 13.1%
CSS 8.6%
TypeScript 8.6%
Other 7.3%