Deploy / build (push) Successful in 16s
- Extract CSS into src/styles/global.css with design tokens (hoelee.com brand palette) - Self-hosted Inter + JetBrains Mono via @fontsource - Sticky nav + manual light/dark toggle + copy-button code blocks - Author card + Person JSON-LD (E-E-A-T), article meta, related posts, reading time - Full SEO: canonical, OG (with dims), twitter:card, favicon (all sizes), RSS + sitemap - New /categories/ and /categories/[category]/ pages - Add docs/ knowledge guides (content, design, seo, ops) + README index - Brand name: hoelee.dev -> Mr Hoelee
2.6 KiB
2.6 KiB
Ops & Deploy Runbook — blog.hoelee.com
How this blog is built, deployed, and kept alive. Read when debugging CI/CD, deployment, or hosting.
Pipeline
Markdown (src/content/posts) → Astro build (dist/) → Gitea Actions → act_runner on unRaid
→ nginx container → Cloudflare tunnel → Cloudflare CDN → blog.hoelee.com
- Repo:
git.hoelee.com/hoelee/hoelee-blog(push here first, then GitHub — standing convention). - Runner:
act_runneron unRaid (verified working: Gitea 1.27.3 + runner 3.3.2, PAT-secret pipeline).
Write & publish a post
- Create
src/content/posts/<slug>.mdwith frontmatter (seecontent-guide.md§6). - Push to
main. - CI builds
dist/and deploys to the nginx container automatically. - Verify live:
curl -I https://blog.hoelee.com/<slug>→ expect 200.
Build pitfalls (from prior Astro work — check these first)
- No JSX helper components in frontmatter — inline JSX directly in
.map()calls, or the build fails withExpected ">" but found "class". - Import depth —
src/pages/*.astrouse../layouts/…; subdirs use../../. Wrong level =Could not resolve. - Footer must render AFTER
<main>— a shared header+footer component renders footer above content otherwise. npm installscripts blocked can leave esbuild's binary missing → checknpm warn install-scriptsat install time.
Verify before shipping a layout change
Headless-Chrome screenshot + vision check on both 390px and 1280px:
CHROME="/c/Program Files/Google/Chrome/Application/chrome.exe"
"$CHROME" --headless --disable-gpu --window-size=1280,2400 \
--screenshot="$(cygpath -w $LOCALAPPDATA/Temp/blog.png)" \
--virtual-time-budget=4000 "http://localhost:4321/"
Overflow diagnosis (real numbers, not screenshot guessing): check scrollWidth > innerWidth via CDP Runtime.evaluate.
Hosting notes
- Static output = trivial to serve from any nginx/OpenLiteSpeed dir. Cloudflare in front gives CDN + HTTPS + DDoS.
- Cloudflare Pages git integration supports GitHub/GitLab only — not Gitea. Current setup (Gitea → self-hosted runner → nginx) sidesteps this entirely and is the reason the pipeline is the way it is.
- Full self-hosting also avoids Cloudflare Pages' 25MB/file, 20k-files limits — a decision already baked into this architecture.
Health checks
curl -I https://blog.hoelee.com/→ 200, correctcontent-type.curl https://blog.hoelee.com/sitemap.xml→ lists all published posts.curl https://blog.hoelee.com/rss.xml→ non-empty.- DNS:
blog.hoelee.comresolves through Cloudflare (proxy enabled).