Files
hoelee-blog/docs/post-publishing-sop-v2.md
T

201 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`) in `zh/`.
- **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.
- **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:
```yaml
---
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:
1. `ogImage` for English is `/og/<slug>.jpg`; for Chinese it is `/og/zh-<slug>.jpg`.
2. `banner` is identical for both: `/banners/<slug>.jpg`.
3. When `dynamicCta: true` is 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:
1. **The Business/Technical Context**: Why this system was built, or what incident triggered the investigation.
2. **The Failure Mode & Evidence**: What broke, how standard metrics/tools lied, and what raw evidence revealed the truth (e.g., `dmesg`, kernel logs, Wireshark).
3. **The Fix / Architecture**: The exact runnable configuration, patch, or state-machine code.
4. **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 like `View configuration` or `点击展开`.
```html
<details class="tech-deep-dive">
<summary>🔍 查看完整的 Docker Compose 配置文件与网络策略 (Traefik v3 + 2GB 内存限制,42 行)</summary>
```yaml
services:
traefik:
...
```
</details>
```
5. **Lessons & Judgment**: What to do differently next time; architectural trade-offs.
6. **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:
```bash
# 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**:
1. `public/banners/<slug>.webp` (1600×900, page hero)
2. `public/banners/<slug>.jpg` (fallback)
3. `public/og/<slug>.jpg` (1200×630, English share card with typography)
4. `public/og/zh-<slug>.jpg` (1200×630, Chinese share card with typography)
5. `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`:
```bash
# 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.
```bash
# 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:[email protected]/hoelee/hoelee-blog.git" main
git fetch github main
```
### Automated CI/CD Actions:
1. Gitea Actions (`deploy.yml`) is triggered automatically by the push to `origin main`.
2. The `act_runner` on unRaid clones over high-speed LAN HTTP (`192.168.1.6:3000`), executes `npm ci`, runs `npm run build`, and copies static assets to `/mnt/user/docker/nginx-hoelee-blog/html/`.
3. Cloudflare cache is automatically purged via API token.
---
## 8. Post-Deploy Health Check
Verify that the live site is serving the new build:
```bash
# 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.