skills/blog-to-wechat-pipeline/SKILL.md
End-to-end pipeline that takes a blog article and produces a complete 微信公众号 publishing package: WeChat-formatted content (copied to clipboard) + cover image. Optionally includes fetching from URLs, downloading embedded images, and translation for non-Chinese sources. Use this skill when the user wants multiple publishing steps handled together — formatting + cover, or translate + format + cover. Triggers on: '转公众号格式并配图', '公众号排版+封面', 'blog-to-wechat-pipeline', '翻译后发公众号', '做成公众号发布素材', '和上面一样的流程', '走一下公众号流程', '翻译成中文放进blog', '把这个链接翻译发公众号', or any bundled article-to-WeChat workflow. Also triggers when user shares a URL and mentions both translation and blog/公众号. If the user only needs one step, prefer the specific skill: wechat-md (formatting), baoyu-cover-image (cover), or baoyu-translate (translation).
npx skillsauth add tc9011/my-skills blog-to-wechat-pipelineInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Fetch source → download images → (optionally translate) → save as blog post → format for 微信公众号 → generate cover image → report.
The user wants two or more of these for a blog article:
If they only want one, use the specific skill directly:
wechat-mdbaoyu-cover-imagebaoyu-translate| Signal | Phases | |--------|--------| | User provides a URL | Fetch → rest of pipeline | | Source is in a foreign language | Fetch → Translate → Blog post → rest | | Source article is already a local Chinese markdown | Skip fetch/translate → Blog post (if needed) → rest | | User says "翻译" / "translate" | Include translation regardless | | User says "放进 blog" / "存到博客" | Include blog post creation | | User says "公众号排版" / "微信格式" | Include WeChat formatting | | User says "封面" / "配图" / "cover" | Include cover image generation |
When the user provides a URL instead of a local file, fetch the article content first.
https://r.jina.ai/<url> — returns clean markdowndefuddle skill — good for standard web pages, strips navigation/adsagent-reach skill — for platform-specific content (Twitter/X, 小红书, YouTube, etc.)webfetch — last resort, may include navigation clutter| Platform | Best method | Gotchas |
|----------|-------------|---------|
| Twitter/X long posts | Jina Reader (r.jina.ai) | Thread posts need full unrolling; xreach requires auth |
| Blog/article sites | Jina Reader or defuddle | Standard approach works well |
| WeChat articles | agent-reach (微信公众号 channel) | May need browser session |
| YouTube | agent-reach (transcript extraction) | Video → text transcription |
Save the fetched raw content to translate/<slug>.md as a working copy. This preserves the original for reference throughout the pipeline.
Source articles often contain images hosted on external CDNs. These must be downloaded before translation or blog post creation, because the blog needs local image paths.
 patterns)src/content/posts/_images/<post-title>/
.md)【译】 prefix in the folder namecurl or webfetch to the image directory
image-01-<brief-description>.jpg
Only run when translation is needed. Follow the baoyu-translate skill — check its EXTEND.md for the user's preferred translation mode (quick/normal/refined).
The baoyu-translate EXTEND.md typically specifies default_mode: refined for this user, which means a multi-pass workflow:
01-analysis.md02-prompt.md03-draft.md04-critique.md05-revision.mdSave translation artifacts to translate/<slug>-zh-CN/.
<!--more--> after the source attribution block (original URL, author, date)Save the translated (or original Chinese) article as a blog post.
The blog is an Astro project at /Users/tangcheng/Documents/Projects/blog/.
Posts directory: src/content/posts/<YYYY>/ (grouped by year)
Image directory: src/content/posts/_images/<post-title>/
.md_images/【译】Full Title Here/Content schema (from src/content.config.ts):
---
title: string # required
published: date # required (format: YYYY-MM-DD HH:mm:ss)
description: string # optional, defaults to ''
updated: date # optional
tags: string[] # optional, defaults to []
draft: boolean # optional, defaults to false
pin: number # optional (0-99), defaults to 0
toc: boolean # optional, defaults to theme setting
lang: string # optional ('zh', 'en', '', etc.)
abbrlink: string # optional
---
There is NO cover, image, or thumbnail field in the schema. Cover images live in the _images/ directory but are not referenced in frontmatter.
Examine existing translated posts (e.g., 【译】从原型到生产.md) for patterns:
【译】【译】翻译 plus topic-specific tags> 原文:[Original Title](https://original-url.com)
> 作者:Author Name
> 发布日期:YYYY 年 M 月 D 日
<!--more--> placed after the attribution blocklang: zh for Chinese translationstoc: true for long-form articlesAll image references use relative paths from the post file:

Before moving to the next phase:
title, published, tags, toc, langsrc/content/posts/<YYYY>/ directory_images/<!--more--> is present for excerpt controlpnpm build to verify the post renders without errorsFollow the wechat-md SKILL.md workflow. Key steps:
node <wechat-md-skill>/scripts/prepare-markdown.js <article> --strip-frontmatterpython3 <wechat-md-skill>/scripts/temp-http.py /tmp (background, capture SERVER_URL)https://md-wechat.vercel.app/focus() + selectAll + execCommand('insertText')
cmView.dispatch()) is not accessible on this site — use execCommand which works through CodeMirror's native input handlingCan run in parallel with Phase 3 — start the image generation while browser automation runs.
| Dimension | Value | |-----------|-------| | Type | conceptual | | Palette | cool | | Rendering | flat-vector | | Text | none (default: no text on cover) | | Mood | balanced | | Font | clean | | Aspect | 16:9 | | Watermark | disabled | | Language | zh |
Override only the dimensions the user explicitly mentions. If user says "带标题" → text: title-only.
The generation method depends on what tools are available. Check in this order:
nano-banana-pro skill (if available and user hasn't excluded it):
uv run <nano-banana-pro-skill>/scripts/generate_image.py \
--prompt "<detailed visual description>" \
--filename "<workspace>/cover-image/<topic-slug>/cover.png" \
--resolution 1K
Python/Pillow programmatic generation (always available as fallback): Create an SVG-style illustration using PIL/Pillow. This approach works for conceptual/flat-vector covers:
optimize=TrueOther image generation skills (if installed): Check for any available image generation MCP or skill
Regardless of generation method, the conceptual approach is the same:
Save the cover image to the blog's image directory:
src/content/posts/_images/<post-title>/cover.png
📋 公众号排版
- 源文件: <path>
- 状态: ✅ 已复制到剪贴板
🎨 封面图
- 位置: <path>
- 尺寸: <width>×<height>
- 生成方式: <method used>
- 风格: <type> / <palette> / <rendering> / <text> / <aspect>
If translation was included, add:
📝 翻译
- 源语言: <lang>
- 模式: <quick/normal/refined>
- 博客文章: <path>
- 图片目录: <path> (<N> images)
If source was fetched from URL, add:
🔗 源内容
- 来源: <url>
- 获取方式: <method used>
- 原文备份: <path>
Overlap work to minimize total time:
T0: Fetch source content (if URL)
T1: Download images + Start translation (can overlap if images finish fast)
T2: Create blog post (after translation + images ready)
T3: Start HTTP server (background) + Start cover image generation (background)
T4: Browser: navigate → style → reload → inject → verify → copy
T5: Kill HTTP server + Collect cover image
T6: Report all results
The CodeMirror view API (cmView.dispatch(), cmTile.view) is not exposed on md-wechat.vercel.app. Use the browser's editing API instead:
cmContent.focus() → document.execCommand('selectAll') → document.execCommand('insertText', false, text)
Relative image paths from the blog project won't render in md-wechat preview. This is expected and does NOT affect the clipboard output.
The success toast auto-dismisses in ~2 seconds. A successful click = content is in clipboard. Don't waste rounds trying to catch the toast.
Reuse the same tab/targetId across all browser calls within one formatting run.
Twitter/X images use pbs.twimg.com CDN URLs with format parameters (e.g., ?format=jpg&name=large). Download these directly with curl — no auth needed for public images. Rename to descriptive filenames rather than keeping CDN hashes.
The Retypeset theme's content schema (in src/content.config.ts) does NOT have a cover, image, or thumbnail frontmatter field. Don't try to add one — it will cause a build error. Cover images are stored in _images/ for manual use only.
When xreach or agent-reach isn't authenticated for Twitter/X, Jina Reader (r.jina.ai/<twitter-url>) reliably extracts thread content including image URLs.
Always run pnpm build after creating a blog post. The build takes ~60s and validates frontmatter schema, image processing (LQIP), and page generation. A 120s timeout may not be enough — use 300s.
When the user wants multiple articles processed:
tools
Three.js interaction - raycasting, controls, mouse/touch input, object selection. Use when handling user input, implementing click detection, adding camera controls, or creating interactive 3D experiences.
development
Three.js geometry creation - built-in shapes, BufferGeometry, custom geometry, instancing. Use when creating 3D shapes, working with vertices, building custom meshes, or optimizing with instanced rendering.
tools
Three.js scene setup, cameras, renderer, Object3D hierarchy, coordinate systems. Use when setting up 3D scenes, creating cameras, configuring renderers, managing object hierarchies, or working with transforms.
tools
Three.js animation - keyframe animation, skeletal animation, morph targets, animation mixing. Use when animating objects, playing GLTF animations, creating procedural motion, or blending animations.