9.5 KiB
Post-Writing & Publishing SOP (v2 Standard)
A single authoritative standard for creating, illustrating, validating, and deploying articles on blog.hoelee.com. Read this before writing, editing, or translating any post.
Guiding Strategy: Broader editorial philosophy (E-E-A-T, categories, topic selection) lives in
content-guide.md. This file governs the mechanics, persona, schema, and deployment pipeline.
1. File Structure & Bilingual Rule (Mandatory Sync)
| Language | File Path | Live URL |
|---|---|---|
| English (Primary) | src/content/posts/<slug>.md |
https://blog.hoelee.com/posts/<slug>/ |
| Chinese (Mirror) | src/content/posts/zh/<slug>.md |
https://blog.hoelee.com/posts/zh/<slug>/ |
- No
lang:field in Frontmatter — language is inferred strictly from the directory (zh/vs root). - 100% Bilingual Coverage: Every English post MUST have a corresponding Chinese twin with the exact same filename (
<slug>.md) inzh/. - Atomic Commits: English drafts, Chinese translations, and their visual assets must be updated and committed together. Never allow the two language twins to drift.
- English Title Case: English post titles MUST use Title Case (capitalize all major words). Chinese titles use natural phrasing.
2. Voice & Persona Guardrails (Enterprise Production First)
The blog establishes senior credibility for job recruitment and B2B client acquisition. Enthusiast hobbyist phrasing damages this positioning.
- ❌ Strictly Forbidden Terms:
homelab,home lab,家用,小主机,玩具,折腾. - ✅ Sanctioned Replacements:
the infrastructure I manage/self-hosted production node/dedicated server hardware- 中文:“我管理的私有基础设施”、“自托管生产节点”、“企业级自建网关”、“生产服务器”。
- First-Person Production Record:
- Open on what was measured or executed (
"When a container stopped unexpectedly on my production node, Docker reported exit 0..."), never an address to an imagined hiring manager. - No second-person (
you/your) in the technical body. Second-person belongs strictly in closing conversion hooks.
- Open on what was measured or executed (
- Honest Metrics:
- Quoted numbers must exist verbatim in the terminal logs, commit history, or benchmarks.
- Never invent incidents or exaggerate scale.
3. Frontmatter Specification (v2 Schema)
All posts (and their Chinese twins) must follow the updated Zod schema:
---
title: "How I Built the DigiKedai Telegram AI Bot"
description: "A customer-support AI bot that answers questions and provisions free-trial accounts over Telegram and WhatsApp — TypeScript, grammY, and a self-hosted LiteLLM gateway."
pubDate: 2026-09-06
category: case-studies
tags: ["telegram", "docker", "cloudflare", "litellm", "typescript", "ai"]
ogImage: /og/how-i-built-the-digikedai-telegram-bot.jpg
banner: /banners/how-i-built-the-digikedai-telegram-bot.jpg
draft: false
# [V2 Feature] Executive Summary Bento Card (Rendered automatically at top)
summary:
audience: "Business Owners & Product Leads" # 中文:“企业主与产品/运营负责人”
painPoint: "A solo digital goods business faces a non-stop stream of repetitive pre-sales questions, leading to missed midnight sales and high manual support overhead."
impact:
- metric: "24/7 Instant Reply"
detail: "Handles customer inquiries across Telegram and WhatsApp with zero human intervention for free-trial provisioning."
- metric: "Zero Price Hallucination"
detail: "3-tier deterministic SKU retrieval and state-machine purchase interception prevent hallucinated prices."
- metric: "~175 Unit Tests"
detail: "Runs reliably in a single container on a dedicated node with LiteLLM gateway failover."
stack: ["TypeScript", "grammY", "LiteLLM", "NocoDB", "Cloudflare Tunnel", "PostgreSQL"]
jumpLinks:
business: "#why-a-business-needs-a-bot-like-this"
architecture: "#the-architecture"
result: "#the-result"
# [V2 Feature] High-Conversion Dynamic CTA Matrix (Rendered automatically at bottom)
dynamicCta: true
# [V2 Feature] Homepage Stream Separation & Blueprint Mounting
stream: engineering # engineering (default for main list) | creative-lab (GPU/multimodal lab strip)
blueprint: ai-agent-automation # Optional: self-hosted-infrastructure | ai-agent-automation | sme-digital-suite
blueprintLayer: L1-deterministic-orchestration # Optional: L1..L4 layer slug
---
Supported Categories (Only 7 allowed)
case-studies · devops · engineering · ai · tutorials · web3 · notes
Key Frontmatter Rules:
ogImagefor English is/og/<slug>.jpg; for Chinese it is/og/zh-<slug>.jpg.banneris identical for both:/banners/<slug>.jpg.- When
dynamicCta: trueis set, DO NOT write a static contact/CTA section in markdown body —<DynamicCTA/>injects the contextual dual-track lead form automatically based on category and tags.
4. Body Content & Layout Blueprint
Every technical post follows the 5-phase "Hard Job → Post" narrative:
- The Business/Technical Context: Why this system was built, or what incident triggered the investigation.
- The Failure Mode & Evidence: What broke, how standard metrics/tools lied, and what raw evidence revealed the truth (e.g.,
dmesg, kernel logs, Wireshark). - The Fix / Architecture: The exact runnable configuration, patch, or state-machine code.
- Technical Deep Dive Accordions:
- For long code dumps, verbose config files, or raw logs (>20 lines), wrap them in native HTML
<details>: - Summary Specification:
<summary>MUST state the exact deliverable/artifact and line count/scope (e.g.🔍 View production docker-compose.yml (Traefik v3 + 2GB mem_limit, 42 lines)). Never use vague text likeView configurationor点击展开.
```<details class="tech-deep-dive"> <summary>🔍 查看完整的 Docker Compose 配置文件与网络策略 (Traefik v3 + 2GB 内存限制,42 行)</summary> ```yaml services: traefik: ... - For long code dumps, verbose config files, or raw logs (>20 lines), wrap them in native HTML
- Lessons & Judgment: What to do differently next time; architectural trade-offs.
- Quantified Result: One concrete metric (latency dropped by 42%, zero crashes in 30 days, 182 tests passing).
5. Visual Pipeline: Local ComfyUI "One Art, Four Targets"
Every new post requires dedicated, text-free conceptual artwork rendered on the local RTX 3060 GPU.
Steps to Generate Post Artwork:
# 1. Verify ComfyUI is listening on port 8188
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8188/system_stats # must return 200
# 2. Draft and render base frame (1360×768)
cd /c/AI/ideogram4
uv run --with rapidocr-onnxruntime --with pillow --with numpy --with scipy python post_art.py \
--slug <slug> \
--metaphor "<concrete physical object + action>" \
--evidence "$ <exact quote or metric from post body>"
Visual Quality & OCR Gates:
- No Text Rule: The metaphor must describe shapes and physics (e.g.,
"an illuminated optical prism deflecting laser beams"). Never include words like"badge","label","screen","numbers", which cause diffusion models to bake in gibberish text. - OCR Gate: Automatically discards seeds with text bounding boxes ≥ 12px.
- Output Artifacts Generated:
public/banners/<slug>.webp(1600×900, page hero)public/banners/<slug>.jpg(fallback)public/og/<slug>.jpg(1200×630, English share card with typography)public/og/zh-<slug>.jpg(1200×630, Chinese share card with typography)public/og/thumb/<slug>-800.webp&<slug>-400.webp(list thumbnails)
6. Pre-Flight Verification Gates
Before committing, run the automated verification suite from D:/dev/hoelee-blog:
# 1. Asset completeness check (fails if any banner or OG card is missing)
node scripts/check-assets.mjs
# 2. Production build & search index verification
npm run build
✅ Success Criteria:
assets: N published posts OK- Astro builds all HTML pages without errors (e.g., 311+ pages).
- Pagefind indexes all words without failing.
7. Dual-Remote Push & CI/CD Deployment
We maintain self-hosted Gitea as the primary repository with GitHub as an external mirror.
# 1. Push to Primary (Gitea git.hoelee.com)
git push origin main
# 2. Push to Mirror (GitHub with PAT helper fix)
TOK=$(grep github.com ~/.git-credentials | head -1 | sed -E 's#https://[^:]+:([^@]+)@.*#\1#' | tr -d '\r')
git -c credential.helper= push "https://hoelee:$TOK@github.com/hoelee/hoelee-blog.git" main
git fetch github main
Automated CI/CD Actions:
- Gitea Actions (
deploy.yml) is triggered automatically by the push toorigin main. - The
act_runneron unRaid clones over high-speed LAN HTTP (192.168.1.6:3000), executesnpm ci, runsnpm run build, and copies static assets to/mnt/user/docker/nginx-hoelee-blog/html/. - Cloudflare cache is automatically purged via API token.
8. Post-Deploy Health Check
Verify that the live site is serving the new build:
# 1. Check HTTP response and Last-Modified header
curl -s -I "https://blog.hoelee.com/posts/<slug>/" | grep -E "HTTP|cf-cache-status|last-modified"
# 2. Assert Executive Summary presence
curl -s "https://blog.hoelee.com/posts/<slug>/?v=$(date +%s)" | grep -o "exec-summary"
# 3. Assert Dynamic CTA presence
curl -s "https://blog.hoelee.com/posts/<slug>/?v=$(date +%s)" | grep -o "dynamic-cta"
Ensure both English and Chinese pages return HTTP/1.1 200 OK and contain the required components.