@1aboveio/skills 0.20.3 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +14 -9
  2. package/package.json +1 -1
  3. package/runtime/skills/distribution/generated/recipes.json +136 -24
  4. package/runtime/skills/distribution/scripts/bundles.mjs +152 -76
  5. package/runtime/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +1 -1
  6. package/skills/compliance/doc-authenticity/SKILL.md +2 -1
  7. package/skills/compliance/doc-authenticity/agents/openai.yaml +8 -0
  8. package/skills/content-creator/article-review/LICENSE +3 -0
  9. package/skills/content-creator/article-review/SKILL.md +65 -0
  10. package/skills/content-creator/article-review/references/report-format.md +68 -0
  11. package/skills/content-creator/article-review/references/template-guide.md +79 -0
  12. package/skills/content-creator/article-review/references/template-wechat-payments.md +125 -0
  13. package/skills/content-creator/article-to-image/LICENSE +3 -0
  14. package/skills/content-creator/article-to-image/SKILL.md +90 -0
  15. package/skills/content-creator/article-to-image/references/formats.md +53 -0
  16. package/skills/content-creator/wechat-article-writer/LICENSE +3 -0
  17. package/skills/content-creator/wechat-article-writer/SKILL.md +50 -0
  18. package/skills/content-creator/wechat-article-writer/references/style-comparison.md +64 -0
  19. package/skills/content-creator/wechat-article-writer/references/style-howto.md +64 -0
  20. package/skills/content-creator/wechat-article-writer/references/style-insight.md +63 -0
  21. package/skills/content-creator/wechat-article-writer/references/style-pitfall.md +60 -0
  22. package/skills/content-creator/wechat-article-writer/references/style-selector.md +133 -0
  23. package/skills/content-creator/wechat-article-writer/references/writing-rules.md +150 -0
  24. package/skills/content-creator/wechat-publisher/LICENSE +3 -0
  25. package/skills/content-creator/wechat-publisher/SKILL.md +170 -0
  26. package/skills/content-creator/wechat-publisher/references/api.md +105 -0
  27. package/skills/content-creator/wechat-publisher/references/layout-rules.md +57 -0
  28. package/skills/content-creator/wechat-publisher/references/wechat-safe-template.html +86 -0
  29. package/skills/content-creator/wechat-publisher/scripts/md_to_wechat_html.py +194 -0
  30. package/skills/content-creator/wechat-publisher/scripts/publish.py +239 -0
  31. package/skills/content-creator/wechat-search/LICENSE +3 -0
  32. package/skills/content-creator/wechat-search/SKILL.md +210 -0
  33. package/skills/content-creator/wechat-search/scripts/start-chrome.sh +83 -0
  34. package/skills/engineering/engineering-runtime/coherence/workflow.json +13 -13
  35. package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +1 -1
@@ -0,0 +1,133 @@
1
+ # 风格选择指南
2
+
3
+ ## 为什么风格选择很重要
4
+
5
+ 不同风格适配不同的内容目标和传播场景。选错风格会导致:
6
+ - 内容失去传播动力(该踩坑的却写成了行业观察)
7
+ - 读者流失(该给步骤的却只讲道理)
8
+ - 品牌调性不一致(该严肃权威的却过于口语化)
9
+
10
+ ---
11
+
12
+ ## 四种风格的适用背景
13
+
14
+ ### 踩坑型(「真人踩坑 + 工具化输出」)
15
+
16
+ **核心机制:** 我的痛苦 → 你的解决方案
17
+
18
+ **最适合的场景:**
19
+ - 你或你的团队/客户**真实踩过这个坑**,有一手经验
20
+ - 目标读者在**同一个痛点上普遍焦虑**(封号、踩坑、选错方案)
21
+ - 问题有**可操作的解决路径**(不是无解的行业困境)
22
+ - 你想**快速建立权威感**(「踩了3次才搞懂」比「专家告诉你」更有说服力)
23
+
24
+ **不适合的场景:**
25
+ - 没有真实案例支撑,纯观点输出
26
+ - 问题太宏观,无法给出具体步骤
27
+ - 读者已经很了解这个坑,不需要被教育
28
+
29
+ **在 B2B 场景的变体:**
30
+ - 「我/我们」可以替换为「客户案例」:「某跨境商家踩了这个坑,我们帮他排查了48小时」
31
+ - 情绪可以比 C 端克制:「非常头疼」代替「心态崩了」
32
+ - 工具化输出必须更精确:步骤/CheckList/决策树,不能只是建议
33
+
34
+ **典型标题信号词:** 踩坑、教训、终于搞懂了、血泪总结、才发现
35
+
36
+ ---
37
+
38
+ ### 实操型(「步骤教程 + 保姆级指南」)
39
+
40
+ **核心机制:** 照着做就行
41
+
42
+ **最适合的场景:**
43
+ - 读者有**明确的执行意图**(想做某件事,但不知道怎么做)
44
+ - 操作过程有**标准流程可遵循**(不是因情况而异的判断题)
45
+ - 受众是**执行层**(需要操作手册,不需要战略判断)
46
+ - 内容更新频率低,**不容易过时**(避免下个月就失效的教程)
47
+
48
+ **不适合的场景:**
49
+ - 问题没有统一答案,高度依赖具体情况
50
+ - 读者是决策层,他们不需要自己操作
51
+ - 内容更新太快,步骤容易过时
52
+
53
+ **在 B2B 场景的变体:**
54
+ - 读者可能是技术人员(接入文档)或业务人员(配置后台)
55
+ - 技术读者:代码/命令行步骤要精确
56
+ - 业务读者:截图 + 标注 + 常见问题 FAQ
57
+
58
+ **典型标题信号词:** 手把手、保姆级、完整指南、从0到1、附教程
59
+
60
+ ---
61
+
62
+ ### 对比型(「概念澄清 + 选型决策」)
63
+
64
+ **核心机制:** 帮读者做决定,省去自己研究的时间
65
+
66
+ **最适合的场景:**
67
+ - 读者对**两个容易混淆的概念/方案**感到困惑
68
+ - 行业内**存在普遍的认知误区**需要纠正
69
+ - 读者正处于**选型决策阶段**,需要判断框架
70
+ - 你有**比较维度的第一手数据**(不是泛泛而谈的优缺点)
71
+
72
+ **不适合的场景:**
73
+ - 只有一个合理选择,没有真正的对比价值
74
+ - 比较维度太多,读者看完更迷糊
75
+ - 属于个人偏好,无法给出客观判断
76
+
77
+ **在 B2B 场景的变体:**
78
+ - 对比要有明确的「适用条件」:什么规模/场景/预算下选 A,什么条件下选 B
79
+ - 可以做成「决策矩阵」或「判断树」,比简单对比更有价值
80
+ - 引用真实数据支撑(成本差异、性能数据、故障率等)
81
+
82
+ **典型标题信号词:** vs、区别、哪个好、分不清、对比、选型
83
+
84
+ ---
85
+
86
+ ### 观察型(「行业洞察 + 深度观点」)
87
+
88
+ **核心机制:** 我看到了一个别人没注意到的趋势/问题
89
+
90
+ **最适合的场景:**
91
+ - 行业**正在发生结构性变化**,读者需要提前感知
92
+ - 你有**独特的数据来源或视角**(非公开的行业洞察)
93
+ - 目标是**建立行业权威感**,培养高质量长期读者
94
+ - 内容**有长尾价值**,不是蹭热点
95
+
96
+ **不适合的场景:**
97
+ - 只是整合公开信息,没有新的判断
98
+ - 没有明确立场,全篇「可能」「也许」
99
+ - 读者需要即时操作指导,观察型无法满足
100
+
101
+ **在 B2B 场景的变体:**
102
+ - 可以稍长(1200-1500字),B2B 读者接受深度内容
103
+ - 必须有明确观点,不能只做信息汇总
104
+ - 适合搭配数据图表,增强说服力
105
+
106
+ **典型标题信号词:** 趋势、观察、为什么、背后、意味着什么、正在发生
107
+
108
+ ---
109
+
110
+ ## 快速选型决策树
111
+
112
+ ```
113
+ 有真实案例/一手踩坑经验?
114
+ ├── 是 → 有可操作的解决步骤?
115
+ │ ├── 是 → 踩坑型 ✅
116
+ │ └── 否 → 观察型(案例作为佐证)
117
+ └── 否 → 读者有执行意图(想做某件事)?
118
+ ├── 是 → 实操型 ✅
119
+ └── 否 → 两个概念/方案需要厘清?
120
+ ├── 是 → 对比型 ✅
121
+ └── 否 → 观察型 ✅
122
+ ```
123
+
124
+ ---
125
+
126
+ ## 混搭原则
127
+
128
+ 单篇文章可以以一种风格为主,融合另一种风格的元素:
129
+ - **踩坑型 + 实操** — 最常见组合:踩坑开场 → 步骤化解决方案
130
+ - **对比型 + 观察** — 概念澄清之后,加一节「行业趋势判断」
131
+ - **观察型 + 实操** — 趋势分析之后,给读者「现在可以做的3件事」
132
+
133
+ 避免:踩坑型 + 观察型混搭(叙事钩子和宏观视角会互相稀释)
@@ -0,0 +1,150 @@
1
+ # 公众号写作通用规则
2
+
3
+ ## 目录
4
+ - [目标读者定位](#目标读者定位)
5
+ - [标题公式](#标题公式)
6
+ - [语言规范](#语言规范)
7
+ - [金句设计](#金句设计)
8
+ - [视觉设计适配](#视觉设计适配)
9
+ - [C 端 → B2B 改写参考](#改写参考)
10
+ - [结构共性](#结构共性)
11
+ - [发布前自查清单](#发布前自查清单)
12
+
13
+ ---
14
+
15
+ ## 目标读者定位
16
+
17
+ 根据品牌受众调整。以 **B2B 专业服务行业(如金融科技、支付、SaaS)** 为例:
18
+ - 有业务背景,但不一定是技术开发者
19
+ - 关心「怎么选」「会不会踩坑」「行业在发生什么」
20
+ - 阅读场景:碎片时间刷手机、午休;核心诉求:**省时间、少踩坑、用得上**
21
+ - B2B 读者更在意**权威性和数据背书**,比 C 端用户情绪更克制
22
+
23
+ 如果是 C 端品牌(消费、生活方式、教育),情绪表达可以更活泼,CTA 可以是「立即体验」「关注账号」。
24
+
25
+ ---
26
+
27
+ ## 标题公式
28
+
29
+ ### 公式 A:踩坑-数字-顿悟
30
+ ```
31
+ [情绪事件] + [数字] + [顿悟感]
32
+ ```
33
+ 示例:「被封了3次之后,我终于搞懂了 Claude 的封号逻辑」
34
+ B2B 改写版:「踩了50个支付坑后,我们终于搞懂了网关选型的逻辑」
35
+
36
+ ### 公式 B:问题-解决方案
37
+ ```
38
+ [问题定位] + [权威背书] + [用户画像]
39
+ ```
40
+ 示例:「Claude 封号避坑指南:十几个真实案例总结的国内用户生存法则」
41
+ B2B 改写版:「支付网关怎么选?我们拆了50个真实案例,给出一套可落地的标准」
42
+
43
+ ### 公式 C:数字-痛点
44
+ ```
45
+ [数字冲击] + [痛点/悬念]
46
+ ```
47
+ 示例:「99%的电商都在这三个地方翻车」
48
+ B2B 改写版:「90%的企业在配置风控规则时犯的同一个错误」
49
+
50
+ ### 公式 D:概念对比
51
+ ```
52
+ [概念A] vs [概念B]:[X%] 的人分不清
53
+ ```
54
+ 示例:「支付失败 vs 交易拒付:90%的人都分不清这两个概念」
55
+
56
+ ---
57
+
58
+ ## 语言规范
59
+
60
+ ### 人称使用
61
+ - 叙事/经历 → 「我」:「我们遇到过这样一个案例」
62
+ - 指导/建议 → 「你」:「你应该先检查这一项」
63
+ - 客观分析 → 「我们」:「我们发现,这类问题有三个共性」
64
+ - 不要全篇只用一种人称,保持「我们讲 → 你学」的节奏
65
+
66
+ ### 句子节奏
67
+ - 平均句子长度:12–20字(手机阅读友好)
68
+ - 每段 2–4 句,不超过4句
69
+ - 每 300–500 字安排一个金句
70
+
71
+ ### 禁止表达
72
+ - ❌ 首先、其次、最后(太正式)
73
+ - ❌ 由此可见、综上所述(太书面)
74
+ - ❌ 必须、绝对、一定(语气过硬)
75
+ - ❌ 纯技术术语堆砌不解释
76
+ - ❌ AI 腔:「当然」「值得注意的是」「不难看出」
77
+
78
+ ---
79
+
80
+ ## 金句设计
81
+
82
+ 好金句的三个条件:
83
+ 1. 不需要上下文就能理解(截图传播)
84
+ 2. 有情绪或观点,不是陈述事实
85
+ 3. 50字以内,3秒读完
86
+
87
+ ### 四种金句类型
88
+ **类比型**:「这相当于你一边戴着假发,一边却把身份证递给官方看」
89
+ **反常识型**:「你以为最安全的做法,恰恰是最容易被风控识别的」
90
+ **数字冲击型**:「我们审查过的50个失败案例,有37个栽在同一个地方」
91
+ **自嘲/幽默型**(慎用于 B2B 场景):「申诉基本无用,但我还是让 AI 写了封言辞恳切的英文信」
92
+
93
+ ### 金句位置
94
+ - 放在段首或段尾,不要埋在段落中间
95
+ - 文章结尾必须以金句收尾
96
+ - 副标题本身也可以是金句
97
+
98
+ ---
99
+
100
+ ## 视觉设计适配
101
+
102
+ ### 文字层面
103
+ - **小标题 ≤10 字** — 一眼扫过能理解
104
+ - **加粗关键词** — 每段 1–2 个,不要整段加粗
105
+ - **数字突出** — 「3次」「7个问题」「90%」这类数字本身是视觉锚点
106
+
107
+ ### 金句卡片(朋友圈截图友好)
108
+ - 金句单独成卡,背景色与正文区隔
109
+ - 留白充足(不是越满越好)
110
+ - 品牌名要够大(缩略图里要看得见)
111
+
112
+ ---
113
+
114
+ ## 改写参考
115
+
116
+ **原版(C 端风格):**
117
+ > 「选错支付网关?99%的人都踩过这3个坑,心态崩了!」
118
+
119
+ **B2B 改写版:**
120
+ > 「选错支付网关?90%的企业都在这三个地方翻车。我们拆了50个真实案例,找到了根本原因。」
121
+
122
+ 改写要点:
123
+ - 去掉情绪夸张(「心态崩了」→ 去掉)
124
+ - 加数据背书(「我们拆了50个真实案例」)
125
+ - 语气平实、有说服力
126
+
127
+ **如果是 C 端品牌,反向操作:** 加情绪词、减数据堆砌、CTA 更直接。
128
+
129
+ ---
130
+
131
+ ## 结构共性
132
+
133
+ 所有风格文章共同要求:
134
+ 1. **开头 200 字**:建立情感连接或紧迫感,不要直接进正文
135
+ 2. **每节有「怎么做」**:不只讲「是什么」,给读者行动路径
136
+ 3. **CheckList 或步骤**:至少一个可收藏的结构化内容
137
+ 4. **结尾 CTA**:根据品牌类型选择合适的行动召唤
138
+
139
+ ---
140
+
141
+ ## 发布前自查清单
142
+
143
+ - [ ] 标题有数字或情绪钩子吗?
144
+ - [ ] 开头 200 字有代入感吗?
145
+ - [ ] 每节有「怎么做」而不是只有「是什么」吗?
146
+ - [ ] 有金句吗?放在显眼位置了吗?
147
+ - [ ] 文章结尾有明确行动召唤吗?
148
+ - [ ] 有没有超过 4 句没分段的长段落?
149
+ - [ ] 有没有生硬的技术术语没解释?
150
+ - [ ] 截图发朋友圈,3 秒内能看懂核心观点吗?
@@ -0,0 +1,3 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 1AboveIO
@@ -0,0 +1,170 @@
1
+ ---
2
+ name: wechat-publisher
3
+ description: "Publish articles to a WeChat Official Account (公众号) via API: push Markdown to the draft box (or auto-publish with --publish), convert Markdown to WeChat HTML, upload images to the media library. Requires AppID + AppSecret + whitelisted server IP on a 认证订阅号/服务号. Consumes wechat-article-writer's Markdown."
4
+ ---
5
+
6
+ # WeChat Publisher (公众号发布)
7
+
8
+ Publish articles to WeChat Official Account via the official API.
9
+
10
+ **Full API reference:** `references/api.md` — read when debugging errors or needing endpoint details.
11
+
12
+ **WeChat-safe layout reference:** `references/wechat-safe-template.html` — read when drafting or fixing article HTML that must survive WeChat rendering.
13
+
14
+ ## Prerequisites (check before starting)
15
+
16
+ 1. **AppID + AppSecret** — from WeChat MP Admin → 开发 → 基本配置
17
+ 2. **IP Whitelist** — server's IPv4 must be added in the same page
18
+ 3. **Account type** — must be 认证订阅号 or 认证服务号 (personal accounts lost API access in 2025-07)
19
+ 4. **Cover image** — JPEG/PNG, ≤64KB (WeChat `thumb` type limit)
20
+
21
+ Get AppID/AppSecret from `~/.openclaw/openclaw.json` → `channels.weixin` if already configured.
22
+
23
+ ## Standard Workflow
24
+
25
+ ## WeChat-safe HTML rules (important)
26
+
27
+ When generating or polishing article HTML for WeChat, treat WeChat as a constrained renderer, not a normal browser.
28
+
29
+ Use these rules for layout-sensitive areas:
30
+
31
+ - Prefer a **small tag set**: `div`, `img`, `h1/h2/h3`, `pre/code`, and a small amount of `br`
32
+ - Avoid relying on native paragraph and list rendering for precise spacing
33
+ - Do **not** use `ul/li` when spacing matters, WeChat often reflows list items with extra gap
34
+ - Do **not** use multiple `p` blocks inside styled cards for step lists, WeChat often re-renders them as loose paragraphs
35
+ - For **steps**, prefer one `div` with manual line breaks:
36
+ - `第一步...<br>第二步...`
37
+ - For **bullet lists**, prefer manual bullets in a plain block:
38
+ - `• 要点 A<br>• 要点 B`
39
+ - For **screenshots**, do not place white screenshots directly on page background
40
+ - Wrap screenshots in an outer container with white background, padding, light gray border, and rounded corners
41
+ - Example wrapper pattern:
42
+
43
+ ```html
44
+ <div style="margin:10px 0;padding:6px;background:#fff;border:1px solid #e5e7eb;border-radius:12px;line-height:0;">
45
+ <img src="..." style="width:100%;height:auto;border-radius:8px;display:block;">
46
+ </div>
47
+ ```
48
+
49
+ - For WeChat article body HTML, omit the visible in-body title if the WeChat draft title is already set separately
50
+ - Keep structure shallow, avoid unnecessary nested wrappers
51
+ - After push, if spacing still looks too loose in the WeChat editor, the final fallback is:
52
+ - select all
53
+ - set **段后距 = 0** inside WeChat editor
54
+
55
+ These rules are more reliable than micro-tuning margin values like `margin-bottom: 6px -> 4px`.
56
+
57
+
58
+ ### Step 1 — Convert Markdown to HTML (if input is .md)
59
+
60
+ ```bash
61
+ python3 {skillDir}/scripts/md_to_wechat_html.py article.md --output article.html
62
+ ```
63
+
64
+ If the article already contains inline-styled HTML, skip this step.
65
+
66
+ ### Step 1.5 — Normalize HTML for WeChat editor behavior
67
+
68
+ When the issue is not visual spacing but a **caret-only blank line in the WeChat editor**, treat it as a **block-boundary problem**, not a copywriting problem.
69
+
70
+ Default rule:
71
+
72
+ - Use **flat `<div>` blocks for body paragraphs**.
73
+ - Treat `<p>` as an **anti-pattern** for WeChat publishing in this skill.
74
+
75
+ Why this rule exists:
76
+
77
+ - In real Agentier testing, multiple versions with `p` still produced a phantom blank editable block before an emphasized sentence.
78
+ - Switching the whole article body to **pure `div` blocks** fixed the issue immediately.
79
+ - Practical conclusion: WeChat may treat `p` boundaries as separate editable paragraph units even when CSS spacing looks correct.
80
+
81
+ Operating principle:
82
+
83
+ - Default to **editor stability over semantic HTML richness**.
84
+ - If WeChat editor behavior and semantic markup conflict, prefer the structure that renders and edits reliably in WeChat.
85
+
86
+ Use these rules:
87
+
88
+ - Keep the body **one level deep**. Do not nest block elements inside other block elements.
89
+ - Use one natural paragraph per `<div>`.
90
+ - For emphasis, use `<div><strong>...</strong></div>`.
91
+ - Remove empty nodes between blocks: no empty `<p>`, no placeholder `&nbsp;`, no repeated `<br>`, no zero-width filler characters.
92
+ - Minify inter-block whitespace before publish when debugging editor quirks.
93
+
94
+ Recommended safe structure:
95
+
96
+ ```html
97
+ <div>正文段 1</div><div>正文段 2</div><div><strong>强调句</strong></div><div>正文段 3</div>
98
+ ```
99
+
100
+ Anti-patterns to avoid:
101
+
102
+ - `<p>` for body paragraphs
103
+ - `blockquote`
104
+ - `ul` / `li`
105
+ - nested `div` / `section` wrappers
106
+ - empty paragraph tags
107
+ - mixed paragraph systems (`p` + `div` in the same article body)
108
+
109
+ ### Step 2 — Publish to Draft Box
110
+
111
+ ```bash
112
+ python3 {skillDir}/scripts/publish.py \
113
+ --appid <APPID> \
114
+ --appsecret <APPSECRET> \
115
+ --title "文章标题" \
116
+ --html article.html \
117
+ --thumb-image cover.jpg \
118
+ --author "作者名" \
119
+ --digest "摘要(最多120字)"
120
+ ```
121
+
122
+ Output: `{ "ok": true, "draft_media_id": "xxx" }`
123
+
124
+ The article now appears in the draft box. Open **微信公众号助手 App** on mobile → 草稿箱 → review → publish.
125
+
126
+ ### Step 3 (optional) — Auto-publish Live
127
+
128
+ Add `--publish` flag to push live immediately (skips manual review):
129
+
130
+ ```bash
131
+ python3 {skillDir}/scripts/publish.py ... --publish
132
+ ```
133
+
134
+ Output: `{ "ok": true, "draft_media_id": "xxx", "publish_id": "yyy", "publish_status": {"status": "success"} }`
135
+
136
+ ⚠️ Only use `--publish` when Jonas explicitly approves skipping manual review.
137
+
138
+ ## Inline Image Handling
139
+
140
+ If the article HTML contains local image paths (`<img src="./images/foo.png">`), upload them first:
141
+
142
+ ```python
143
+ # Quick one-liner to get the WeChat CDN URL for an image
144
+ import subprocess, json
145
+ result = subprocess.run([
146
+ "python3", "-c",
147
+ """
148
+ import requests, sys
149
+ token = sys.argv[1]
150
+ with open(sys.argv[2], 'rb') as f:
151
+ r = requests.post(f'https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token={token}', files={'media': f})
152
+ print(r.json()['url'])
153
+ """,
154
+ "<token>", "image.jpg"
155
+ ], capture_output=True, text=True)
156
+ print(result.stdout.strip())
157
+ ```
158
+
159
+ Then replace `src="./images/foo.png"` with the returned CDN URL in the HTML.
160
+
161
+ ## Error Quick-Reference
162
+
163
+ | Error | Fix |
164
+ |-------|-----|
165
+ | `40164` IP not in whitelist | Add server IP in WeChat MP Admin |
166
+ | `48001` API not authorized | Account not certified or permission missing |
167
+ | `40007` invalid media_id | Cover image upload failed — retry upload |
168
+ | `45009` rate limit | Wait for next day or reset quota in MP Admin |
169
+
170
+ Full error codes: `references/api.md`
@@ -0,0 +1,105 @@
1
+ # WeChat Official Account API Reference
2
+
3
+ ## Authentication
4
+
5
+ **Get access_token** (valid 2 hours; cached in `/tmp/wechat_access_token.json`)
6
+ ```
7
+ GET https://api.weixin.qq.com/cgi-bin/token
8
+ ?grant_type=client_credential&appid=APPID&secret=APPSECRET
9
+ → { "access_token": "...", "expires_in": 7200 }
10
+ ```
11
+ Daily limit: 2000 calls. Always cache; never call per-request.
12
+
13
+ **IP Whitelist** — The calling server's IP must be added in:
14
+ WeChat MP Admin → 开发 → 基本配置 → IP白名单
15
+
16
+ ---
17
+
18
+ ## Content Publishing Flow
19
+
20
+ ### Step 1: Upload cover image (permanent material)
21
+ ```
22
+ POST https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=TOKEN&type=thumb
23
+ multipart/form-data: media=<file>
24
+ → { "media_id": "...", "url": "..." }
25
+ ```
26
+ - Cover image: JPEG/PNG, **≤64 KB** for `thumb` type
27
+ - Returns `media_id` for use in draft creation
28
+
29
+ ### Step 2: Upload inline images (article body)
30
+ ```
31
+ POST https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=TOKEN
32
+ multipart/form-data: media=<file>
33
+ → { "url": "https://mmbiz.qpic.cn/..." }
34
+ ```
35
+ - Any images in the article HTML body must be replaced with these CDN URLs
36
+ - External image URLs will NOT render inside WeChat
37
+
38
+ ### Step 3: Create draft
39
+ ```
40
+ POST https://api.weixin.qq.com/cgi-bin/draft/add?access_token=TOKEN
41
+ {
42
+ "articles": [{
43
+ "title": "文章标题",
44
+ "author": "作者名",
45
+ "digest": "摘要(≤120字)",
46
+ "content": "<p>HTML正文</p>",
47
+ "thumb_media_id": "<from step 1>",
48
+ "need_open_comment": 0,
49
+ "only_fans_can_comment": 0
50
+ }]
51
+ }
52
+ → { "media_id": "draft_media_id" }
53
+ ```
54
+ Daily limit: 1000 drafts
55
+
56
+ ### Step 4 (optional): Publish draft live
57
+ ```
58
+ POST https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token=TOKEN
59
+ { "media_id": "draft_media_id" }
60
+ → { "errcode": 0, "publish_id": "123456" }
61
+ ```
62
+ Daily limit: 100 publishes
63
+
64
+ ### Step 5 (optional): Poll publish status
65
+ ```
66
+ POST https://api.weixin.qq.com/cgi-bin/freepublish/get?access_token=TOKEN
67
+ { "publish_id": "123456" }
68
+ → { "publish_status": 0, "article_id": "..." }
69
+ ```
70
+ `publish_status`: 0=成功, 1=发布中, 2=失败, 4=已删除
71
+
72
+ ---
73
+
74
+ ## Account Type Requirements
75
+
76
+ | Feature | 个人未认证订阅号 | 认证订阅号 | 认证服务号 |
77
+ |---------|--------------|----------|----------|
78
+ | 草稿箱/发布 API | ❌ (2025-07 回收) | ✅ | ✅ |
79
+ | 群发接口 | ❌ | ✅ | ✅ |
80
+ | 模板消息 | ❌ | ❌ | ✅ |
81
+ | 网页授权/支付 | ❌ | ❌ | ✅ |
82
+
83
+ **Minimum requirement: 认证订阅号 (企业/组织主体)**
84
+
85
+ ---
86
+
87
+ ## HTML Content Requirements
88
+
89
+ - All CSS must be **inline** — no `<style>` tags, no external CSS
90
+ - No `<html>`, `<head>`, `<body>` wrapper (WeChat provides it)
91
+ - Images: must be WeChat CDN URLs (upload first via `uploadimg`)
92
+ - Font size: 14–16px recommended for mobile
93
+ - Line height: 1.6–1.8 for readability
94
+
95
+ ---
96
+
97
+ ## Common Error Codes
98
+
99
+ | errcode | Meaning | Fix |
100
+ |---------|---------|-----|
101
+ | 40001 | invalid access_token | Refresh token |
102
+ | 40164 | IP not in whitelist | Add server IP to whitelist |
103
+ | 45009 | API rate limit exceeded | Wait or reset quota |
104
+ | 48001 | API not authorized | Account not certified or lacks permission |
105
+ | 40007 | invalid media_id | Re-upload the media |
@@ -0,0 +1,57 @@
1
+ # WeChat-safe layout rules
2
+
3
+ Use this reference when article HTML must survive WeChat draft/editor rendering.
4
+
5
+ ## Core rule
6
+
7
+ Treat WeChat as a constrained renderer, not a normal browser.
8
+
9
+ ## Team rules
10
+
11
+ 1. Prefer a small tag set
12
+ - `div`
13
+ - `img`
14
+ - `h1/h2/h3`
15
+ - `pre/code`
16
+ - a small amount of `br`
17
+
18
+ 2. Do not rely on native list or paragraph spacing when layout matters
19
+ - avoid `ul/li`
20
+ - avoid multiple `p` blocks inside styled cards
21
+
22
+ 3. Build steps as one block
23
+ - use one `div`
24
+ - separate lines with `<br>`
25
+
26
+ 4. Build bullets manually
27
+ - use `•` in a plain `div`
28
+ - do not use native list markup for spacing-sensitive sections
29
+
30
+ 5. Always wrap white screenshots
31
+ - white background
32
+ - padding
33
+ - light gray border
34
+ - rounded corners
35
+
36
+ 6. Keep body HTML title-free
37
+ - the WeChat draft title is configured separately
38
+ - do not repeat the article title inside body HTML
39
+
40
+ 7. Keep section hierarchy readable
41
+ - section headings need visible top spacing
42
+ - subsection headings also need top spacing, but less than sections
43
+
44
+ 8. Use WeChat editor as final fallback
45
+ - if the draft still looks too loose, select all and set `段后距 = 0`
46
+
47
+ ## Most common failure patterns
48
+
49
+ - margin micro-tweaks that do not survive WeChat rendering
50
+ - `ul/li` producing unexpected extra space
51
+ - card blocks made of many child paragraphs/divs becoming loose after push
52
+ - white screenshots visually disappearing into page background
53
+
54
+ ## Recommended reference files
55
+
56
+ - `wechat-safe-template.html` for reusable HTML skeleton
57
+ - `api.md` for publishing/debugging details