Compare commits

..

27 Commits

Author SHA1 Message Date
Jim Liu 宝玉 4821508c34 chore: release v1.95.0 2026-04-08 22:10:03 -05:00
Jim Liu 宝玉 f1042c8a6c feat(baoyu-slide-deck): add hand-drawn-edu preset and macaron mood 2026-04-08 22:06:54 -05:00
Jim Liu 宝玉 fa0fe441f5 feat(baoyu-infographic): add hand-drawn-edu style with macaron palette 2026-04-08 22:06:50 -05:00
Jim Liu 宝玉 90b2205914 chore: release v1.94.0 2026-04-08 17:58:33 -05:00
Jim Liu 宝玉 8e111c17b3 feat(baoyu-cover-image): add macaron palette and hand-drawn-edu style preset 2026-04-08 17:58:29 -05:00
Jim Liu 宝玉 80d7675355 chore: release v1.93.0 2026-04-08 15:49:00 -05:00
Jim Liu 宝玉 538ede2b32 feat(baoyu-article-illustrator): add hand-drawn-edu preset with sketch-notes + macaron 2026-04-08 15:48:20 -05:00
Jim Liu 宝玉 038e67fd9b refactor(baoyu-article-illustrator): extract palette as independent third dimension
- Create palettes/ directory with macaron, warm, neon palette files
- Move macaron from styles/ to palettes/ (color scheme, not rendering style)
- Extract warm palette variant from vector-illustration into shared palette
- Add neon palette extracted from retro style colors
- Update architecture from Type × Style to Type × Style × Palette
- Add Palette Gallery and override rules to styles.md
- Add Palette Override section to prompt-construction.md
- Update presets table with Palette column
- Add palette selection step to workflow
- Add preferred_palette to EXTEND.md schema
2026-04-08 14:35:51 -05:00
Jim Liu 宝玉 049462d6dd fix(baoyu-article-illustrator): add explicit style file loading step in workflow 2026-04-08 12:52:13 -05:00
Jim Liu 宝玉 c8042cef0d chore: release v1.92.0 2026-04-08 11:51:23 -05:00
Jim Liu 宝玉 15508eae43 feat(baoyu-article-illustrator): add macaron style with soft pastel color blocks 2026-04-08 11:49:49 -05:00
Jim Liu 宝玉 94eab2de63 chore: release v1.91.0 2026-04-07 01:32:21 -05:00
Jim Liu 宝玉 126b72ed36 feat: add pdf-lib dependency for PDF generation 2026-04-07 01:31:35 -05:00
Jim Liu 宝玉 38f4f253df feat(baoyu-comic): add four-panel preset, minimalist art style, and flexible image workflow
- Add minimalist art style (clean line art, limited spot color, stick-figure characters)
- Add four-panel layout with 起承转合 structure
- Add four-panel preset combining minimalist + neutral + four-panel layout
- Make character sheet conditional (skip for simple presets like four-panel)
- Add --ref failure recovery: compress → retry → fall back to prompt-only
2026-04-07 01:31:32 -05:00
Jim Liu 宝玉 8bc01debac Add concept-story preset to baoyu-comic 2026-04-07 01:09:05 -05:00
Jim Liu 宝玉 c5c54e26da chore: release v1.90.1 2026-04-05 13:55:58 -05:00
Jim Liu 宝玉 2a0bba6161 fix(baoyu-post-to-wechat): detect actual image format from buffer magic bytes
CDNs may serve WebP for URLs with .png extension. Detect real format
from magic bytes and correct content-type/extension before upload.
Also treat .webp as PNG-preferred for transparency handling.
2026-04-05 13:36:51 -05:00
Jim Liu 宝玉 c44a524fa6 chore: release v1.90.0 2026-04-03 23:45:44 -05:00
Jim Liu 宝玉 826535abe4 feat(baoyu-xhs-images): add --yes non-interactive mode for automation 2026-04-03 23:45:10 -05:00
Jim Liu 宝玉 fc50f31694 chore: release v1.89.2 2026-04-03 23:35:58 -05:00
Jim Liu 宝玉 204765a137 feat(baoyu-youtube-transcript): auto-retry with yt-dlp on empty InnerTube transcript 2026-04-03 23:35:42 -05:00
Jim Liu 宝玉 4874cd2dae feat(baoyu-post-to-wechat): use fallback chain for article summary field 2026-04-03 23:35:34 -05:00
Jim Liu 宝玉 b791ee5dc7 chore: release v1.89.1 2026-04-01 02:12:07 -05:00
Jim Liu 宝玉 450c76d955 chore(baoyu-url-to-markdown): sync vendor baoyu-fetch with login auto-detect 2026-04-01 02:12:04 -05:00
Jim Liu 宝玉 db33da26e7 feat(baoyu-fetch): auto-detect login state before extraction in interaction mode 2026-04-01 02:12:00 -05:00
Jim Liu 宝玉 c7c98ba034 chore: sync vendor baoyu-chrome-cdp across CDP skills 2026-04-01 02:11:56 -05:00
Jim Liu 宝玉 60ab574559 feat(baoyu-chrome-cdp): add gracefulKillChrome and fix killChrome process state check 2026-04-01 02:11:51 -05:00
54 changed files with 1532 additions and 211 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
},
"metadata": {
"description": "Skills shared by Baoyu for improving daily work efficiency",
"version": "1.89.0"
"version": "1.95.0"
},
"plugins": [
{
+42
View File
@@ -2,6 +2,48 @@
English | [中文](./CHANGELOG.zh.md)
## 1.95.0 - 2026-04-08
### Features
- `baoyu-infographic`: add `hand-drawn-edu` style — macaron pastels, hand-drawn wobble, stick figures
- `baoyu-slide-deck`: add `hand-drawn-edu` preset and `macaron` mood dimension with pastel color palette
## 1.94.0 - 2026-04-08
### Features
- `baoyu-cover-image`: add macaron palette and hand-drawn-edu style preset
## 1.93.0 - 2026-04-08
### Features
- `baoyu-article-illustrator`: add `hand-drawn-edu` preset — flowchart + sketch-notes + macaron combination for hand-drawn educational diagrams
### Refactor
- `baoyu-article-illustrator`: extract palette as independent third dimension in Type × Style × Palette system
### Fixes
- `baoyu-article-illustrator`: add explicit style file loading step in workflow
## 1.92.0 - 2026-04-08
### Features
- `baoyu-article-illustrator`: add `macaron` style — soft macaron pastel color blocks (blue, mint, lavender, peach) on warm cream background with optional hand-drawn mode; add `edu-visual` preset
## 1.90.1 - 2026-04-05
### Fixes
- `baoyu-post-to-wechat`: detect actual image format from buffer magic bytes to fix CDN content-type mismatches (e.g. WebP served for .png URLs); treat WebP as PNG-preferred for transparency handling
## 1.89.1 - 2026-04-01
### Features
- `baoyu-chrome-cdp`: add `gracefulKillChrome` that waits for Chrome to exit and release its port; fix `killChrome` to use `exitCode`/`signalCode` instead of `.killed` for reliable process state detection
- `baoyu-fetch`: auto-detect login state before extraction in interaction wait mode
### Maintenance
- Sync vendor baoyu-chrome-cdp across CDP skills
- `baoyu-url-to-markdown`: sync vendor baoyu-fetch with login auto-detect
## 1.89.0 - 2026-03-31
### Features
+42
View File
@@ -2,6 +2,48 @@
[English](./CHANGELOG.md) | 中文
## 1.95.0 - 2026-04-08
### 新功能
- `baoyu-infographic`:新增 `hand-drawn-edu` 风格 — 马卡龙柔和色块、手绘线条、火柴人角色
- `baoyu-slide-deck`:新增 `hand-drawn-edu` 预设和 `macaron` 色调维度,含柔和马卡龙色板
## 1.94.0 - 2026-04-08
### 新功能
- `baoyu-cover-image`:新增马卡龙色板和 hand-drawn-edu 风格预设
## 1.93.0 - 2026-04-08
### 新功能
- `baoyu-article-illustrator`:新增 `hand-drawn-edu` 预设 — flowchart + sketch-notes + macaron 组合,用于手绘教育图解
### 重构
- `baoyu-article-illustrator`:将色板(Palette)提取为独立的第三维度,形成 Type × Style × Palette 三维系统
### 修复
- `baoyu-article-illustrator`:在工作流中添加显式的风格文件加载步骤
## 1.92.0 - 2026-04-08
### 新功能
- `baoyu-article-illustrator`:新增 `macaron` 风格 — 马卡龙柔和色块(浅蓝、浅绿、浅紫、浅橙)配暖白底色,可选手绘模式;新增 `edu-visual` 预设
## 1.90.1 - 2026-04-05
### 修复
- `baoyu-post-to-wechat`:通过 magic bytes 检测实际图片格式,修复 CDN 返回与 URL 扩展名不一致的 content-type 问题(如 .png URL 实际返回 WebP);WebP 格式按 PNG 策略处理以保留透明度
## 1.89.1 - 2026-04-01
### 新功能
- `baoyu-chrome-cdp`:新增 `gracefulKillChrome`,等待 Chrome 进程退出并释放端口;修复 `killChrome` 使用 `exitCode`/`signalCode` 替代 `.killed` 以更可靠地检测进程状态
- `baoyu-fetch`:在交互等待模式下自动检测登录状态,未登录时提示用户先登录再提取内容
### 维护
- 同步 vendor baoyu-chrome-cdp 至所有 CDP 技能
- `baoyu-url-to-markdown`:同步 vendor baoyu-fetch 的登录自动检测功能
## 1.89.0 - 2026-03-31
### 新功能
+1 -1
View File
@@ -1,6 +1,6 @@
# CLAUDE.md
Claude Code marketplace plugin providing AI-powered content generation skills. Version: **1.89.0**.
Claude Code marketplace plugin providing AI-powered content generation skills. Version: **1.95.0**.
## Architecture
+22 -13
View File
@@ -116,6 +116,10 @@ Xiaohongshu (RedNote) infographic series generator. Breaks down content into 1-1
# Direct content input
/baoyu-xhs-images 今日星座运势
# Non-interactive (skip all confirmations, for scheduled tasks)
/baoyu-xhs-images posts/ai-future/article.md --yes
/baoyu-xhs-images posts/ai-future/article.md --yes --preset knowledge-card
```
**Styles** (visual aesthetics): `cute` (default), `fresh`, `warm`, `bold`, `minimal`, `retro`, `pop`, `notion`, `chalkboard`
@@ -152,7 +156,7 @@ Xiaohongshu (RedNote) infographic series generator. Breaks down content into 1-1
#### baoyu-infographic
Generate professional infographics with 20 layout types and 17 visual styles. Analyzes content, recommends layout×style combinations, and generates publication-ready infographics.
Generate professional infographics with 21 layout types and 21 visual styles. Analyzes content, recommends layout×style combinations, and generates publication-ready infographics.
```bash
# Auto-recommend combinations based on content
@@ -265,7 +269,7 @@ Generate professional infographics with 20 layout types and 17 visual styles. An
#### baoyu-cover-image
Generate cover images for articles with 5 dimensions: Type × Palette × Rendering × Text × Mood. Combines 9 color palettes with 6 rendering styles for 54 unique combinations.
Generate cover images for articles with 5 dimensions: Type × Palette × Rendering × Text × Mood. Combines 11 color palettes with 7 rendering styles for 77 unique combinations.
```bash
# Auto-select all dimensions based on content
@@ -290,8 +294,8 @@ Generate cover images for articles with 5 dimensions: Type × Palette × Renderi
**Five Dimensions**:
- **Type**: `hero`, `conceptual`, `typography`, `metaphor`, `scene`, `minimal`
- **Palette**: `warm`, `elegant`, `cool`, `dark`, `earth`, `vivid`, `pastel`, `mono`, `retro`
- **Rendering**: `flat-vector`, `hand-drawn`, `painterly`, `digital`, `pixel`, `chalk`
- **Palette**: `warm`, `elegant`, `cool`, `dark`, `earth`, `vivid`, `pastel`, `mono`, `retro`, `duotone`, `macaron`
- **Rendering**: `flat-vector`, `hand-drawn`, `painterly`, `digital`, `pixel`, `chalk`, `screen-print`
- **Text**: `none`, `title-only` (default), `title-subtitle`, `text-rich`
- **Mood**: `subtle`, `balanced` (default), `bold`
@@ -469,20 +473,17 @@ Knowledge comic creator with flexible art style × tone combinations. Creates or
#### baoyu-article-illustrator
Smart article illustration skill with Type × Style two-dimension approach. Analyzes article structure, identifies positions requiring visual aids, and generates illustrations.
Smart article illustration skill with Type × Style × Palette three-dimension approach. Analyzes article structure, identifies positions requiring visual aids, and generates illustrations.
```bash
# Auto-select type and style based on content
/baoyu-article-illustrator path/to/article.md
# Specify type
/baoyu-article-illustrator path/to/article.md --type infographic
# Specify style
/baoyu-article-illustrator path/to/article.md --style blueprint
# Combine type and style
# Specify type and style
/baoyu-article-illustrator path/to/article.md --type flowchart --style notion
# With palette override
/baoyu-article-illustrator path/to/article.md --style vector-illustration --palette macaron
```
**Types** (information structure):
@@ -496,7 +497,7 @@ Smart article illustration skill with Type × Style two-dimension approach. Anal
| `framework` | Concept maps, relationship diagrams | Methodologies, architecture |
| `timeline` | Chronological progression | History, project progress |
**Styles** (visual aesthetics):
**Styles** (rendering approach):
| Style | Description | Best For |
|-------|-------------|----------|
@@ -509,6 +510,14 @@ Smart article illustration skill with Type × Style two-dimension approach. Anal
| `editorial` | Magazine-style infographic | Tech explainers, journalism |
| `scientific` | Academic precise diagrams | Biology, chemistry, technical |
**Palettes** (optional color override):
| Palette | Description | Best For |
|---------|-------------|----------|
| `macaron` | Soft pastel blocks (blue, mint, lavender, peach) on warm cream | Educational, knowledge, tutorials |
| `warm` | Warm earth tones on soft peach, no cool colors | Brand, product, lifestyle |
| `neon` | Vibrant neon on dark purple | Gaming, retro, pop culture |
**Style Previews**:
| | | |
+21 -12
View File
@@ -116,6 +116,10 @@ clawhub install baoyu-markdown-to-html
# 直接输入内容
/baoyu-xhs-images 今日星座运势
# 非交互模式(跳过所有确认,适用于定时任务)
/baoyu-xhs-images posts/ai-future/article.md --yes
/baoyu-xhs-images posts/ai-future/article.md --yes --preset knowledge-card
```
**风格**(视觉美学):`cute`(默认)、`fresh``warm``bold``minimal``retro``pop``notion``chalkboard`
@@ -152,7 +156,7 @@ clawhub install baoyu-markdown-to-html
#### baoyu-infographic
专业信息图生成器,支持 20 种布局和 17 种视觉风格。分析内容后推荐布局×风格组合,生成可发布的信息图。
专业信息图生成器,支持 21 种布局和 21 种视觉风格。分析内容后推荐布局×风格组合,生成可发布的信息图。
```bash
# 根据内容自动推荐组合
@@ -265,7 +269,7 @@ clawhub install baoyu-markdown-to-html
#### baoyu-cover-image
为文章生成封面图,支持五维定制系统:类型 × 配色 × 渲染 × 文字 × 氛围。9 种配色方案与 6 种渲染风格组合,提供 54 种独特效果。
为文章生成封面图,支持五维定制系统:类型 × 配色 × 渲染 × 文字 × 氛围。11 种配色方案与 7 种渲染风格组合,提供 77 种独特效果。
```bash
# 根据内容自动选择所有维度
@@ -290,8 +294,8 @@ clawhub install baoyu-markdown-to-html
**五个维度**
- **类型 (Type)**`hero``conceptual``typography``metaphor``scene``minimal`
- **配色 (Palette)**`warm``elegant``cool``dark``earth``vivid``pastel``mono``retro`
- **渲染 (Rendering)**`flat-vector``hand-drawn``painterly``digital``pixel``chalk`
- **配色 (Palette)**`warm``elegant``cool``dark``earth``vivid``pastel``mono``retro``duotone``macaron`
- **渲染 (Rendering)**`flat-vector``hand-drawn``painterly``digital``pixel``chalk``screen-print`
- **文字 (Text)**`none``title-only`(默认)、`title-subtitle``text-rich`
- **氛围 (Mood)**`subtle``balanced`(默认)、`bold`
@@ -469,20 +473,17 @@ clawhub install baoyu-markdown-to-html
#### baoyu-article-illustrator
智能文章插图技能,采用类型 × 风格维系统。分析文章结构,识别需要视觉辅助的位置,生成插图。
智能文章插图技能,采用类型 × 风格 × 色板三维系统。分析文章结构,识别需要视觉辅助的位置,生成插图。
```bash
# 根据内容自动选择类型和风格
/baoyu-article-illustrator path/to/article.md
# 指定类型
/baoyu-article-illustrator path/to/article.md --type infographic
# 指定风格
/baoyu-article-illustrator path/to/article.md --style blueprint
# 组合类型和风格
/baoyu-article-illustrator path/to/article.md --type flowchart --style notion
# 使用色板覆盖
/baoyu-article-illustrator path/to/article.md --style vector-illustration --palette macaron
```
**类型**(信息结构):
@@ -496,7 +497,7 @@ clawhub install baoyu-markdown-to-html
| `framework` | 概念图、关系图 | 方法论、架构 |
| `timeline` | 时间线进展 | 历史、项目进度 |
**风格**视觉美学):
**风格**渲染手法):
| 风格 | 描述 | 适用场景 |
|------|------|----------|
@@ -509,6 +510,14 @@ clawhub install baoyu-markdown-to-html
| `editorial` | 杂志风格信息图 | 科技解说、新闻 |
| `scientific` | 学术精确图表 | 生物、化学、技术 |
**色板**(可选配色覆盖):
| 色板 | 描述 | 适用场景 |
|------|------|----------|
| `macaron` | 马卡龙柔和色块(浅蓝、浅绿、浅紫、浅橙)暖白底 | 教育、知识分享、教程 |
| `warm` | 暖色系(橙、赭石、金)无冷色 | 品牌、产品、生活方式 |
| `neon` | 霓虹色(粉、青、黄)深色底 | 游戏、复古、潮流 |
**风格预览**
| | | |
BIN
View File
Binary file not shown.
+3
View File
@@ -15,5 +15,8 @@
"turndown": "^7.2.2",
"turndown-plugin-gfm": "^1.0.2",
"tsx": "^4.20.5"
},
"dependencies": {
"pdf-lib": "^1.17.1"
}
}
@@ -11,6 +11,7 @@ import {
discoverRunningChromeDebugPort,
findChromeExecutable,
findExistingChromeDebugPort,
gracefulKillChrome,
getFreePort,
openPageSession,
resolveSharedChromeProfileDir,
@@ -110,6 +111,44 @@ async function stopProcess(child: ChildProcess | null): Promise<void> {
await new Promise((resolve) => child.once("exit", resolve));
}
async function startPortHoldingProcess(port: number): Promise<ChildProcess> {
const child = spawn(
process.execPath,
[
"-e",
`
const http = require("node:http");
const port = Number(process.argv[1]);
const server = http.createServer((_req, res) => res.end("ok"));
server.listen(port, "127.0.0.1", () => process.stdout.write("ready\\n"));
setInterval(() => {}, 1000);
`,
String(port),
],
{
stdio: ["ignore", "pipe", "ignore"],
},
);
await new Promise<void>((resolve, reject) => {
const timer = setTimeout(() => reject(new Error("Timed out waiting for child server to start.")), 3_000);
child.once("error", (error) => {
clearTimeout(timer);
reject(error);
});
child.stdout?.once("data", () => {
clearTimeout(timer);
resolve();
});
child.once("exit", () => {
clearTimeout(timer);
reject(new Error("Child server exited before becoming ready."));
});
});
return child;
}
test("getFreePort honors a fixed environment override and otherwise allocates a TCP port", async (t) => {
useEnv(t, { TEST_FIXED_PORT: "45678" });
assert.equal(await getFreePort("TEST_FIXED_PORT"), 45678);
@@ -305,3 +344,19 @@ test("waitForChromeDebugPort retries until the debug endpoint becomes available"
assert.equal(websocketUrl, `ws://127.0.0.1:${port}/devtools/browser/demo`);
});
test("gracefulKillChrome waits for the Chrome process to exit and release its port", async (t) => {
const port = await getFreePort();
const child = await startPortHoldingProcess(port);
t.after(async () => { await stopProcess(child); });
assert.equal(await waitForChromeDebugPort(port, 1_000).catch(() => null), null);
await gracefulKillChrome(child, port, 4_000);
assert.ok(child.exitCode !== null || child.signalCode !== null);
assert.equal(
await fetch(`http://127.0.0.1:${port}`).then(() => true).catch(() => false),
false,
);
});
+32 -1
View File
@@ -478,7 +478,7 @@ export function killChrome(chrome: ChildProcess): void {
chrome.kill("SIGTERM");
} catch {}
setTimeout(() => {
if (!chrome.killed) {
if (chrome.exitCode === null && chrome.signalCode === null) {
try {
chrome.kill("SIGKILL");
} catch {}
@@ -486,6 +486,37 @@ export function killChrome(chrome: ChildProcess): void {
}, 2_000).unref?.();
}
export async function gracefulKillChrome(
chrome: ChildProcess,
port?: number,
timeoutMs = 6_000,
): Promise<void> {
if (chrome.exitCode !== null || chrome.signalCode !== null) return;
const exitPromise = new Promise<void>((resolve) => {
chrome.once("exit", () => resolve());
});
killChrome(chrome);
const start = Date.now();
while (Date.now() - start < timeoutMs) {
if (chrome.exitCode !== null || chrome.signalCode !== null) return;
if (port !== undefined && !await isPortListening(port, 250)) return;
const exited = await Promise.race([
exitPromise.then(() => true),
sleep(100).then(() => false),
]);
if (exited) return;
}
await Promise.race([
exitPromise,
sleep(250),
]);
}
export async function openPageSession(options: OpenPageSessionOptions): Promise<PageSession> {
let targetId: string;
let createdTarget = false;
@@ -399,6 +399,22 @@ export async function runConvertCommand(options: ConvertCommandOptions): Promise
if (restored) logger.info(`Restored ${adapter.name} session cookies from sidecar.`);
}
if (options.waitMode === "interaction" && adapter.checkLogin) {
await context.browser.goto(url.toString(), options.timeoutMs).catch(() => {});
const preLogin = await adapter.checkLogin(context);
if (preLogin.state !== "logged_in") {
didLogin = true;
await waitForInteraction(adapter, context, {
type: "wait_for_interaction",
kind: "login",
provider: preLogin.provider ?? adapter.name,
prompt: `Please sign in to ${adapter.name === "x" ? "X" : adapter.name} in the opened Chrome window. Extraction will continue automatically once login is detected.`,
reason: preLogin.reason ?? `Not logged in to ${adapter.name}`,
requiresVisibleBrowser: true,
}, options);
}
}
if (options.waitMode === "force") {
await context.browser.goto(url.toString(), options.timeoutMs).catch(() => {});
await waitForForceResume(adapter, context, options);
+13 -11
View File
@@ -1,6 +1,6 @@
---
name: baoyu-article-illustrator
description: Analyzes article structure, identifies positions requiring visual aids, generates illustrations with Type × Style two-dimension approach. Use when user asks to "illustrate article", "add images", "generate images for article", or "为文章配图".
description: Analyzes article structure, identifies positions requiring visual aids, generates illustrations with Type × Style × Palette three-dimension approach. Use when user asks to "illustrate article", "add images", "generate images for article", or "为文章配图".
version: 1.57.0
metadata:
openclaw:
@@ -9,18 +9,19 @@ metadata:
# Article Illustrator
Analyze articles, identify illustration positions, generate images with Type × Style consistency.
Analyze articles, identify illustration positions, generate images with Type × Style × Palette consistency.
## Two Dimensions
## Three Dimensions
| Dimension | Controls | Examples |
|-----------|----------|----------|
| **Type** | Information structure | infographic, scene, flowchart, comparison, framework, timeline |
| **Style** | Visual aesthetics | notion, warm, minimal, blueprint, watercolor, elegant |
| **Style** | Rendering approach | notion, warm, minimal, blueprint, watercolor, elegant |
| **Palette** | Color scheme (optional) | macaron, warm, neon — overrides style's default colors |
Combine freely: `--type infographic --style blueprint`
Combine freely: `--type infographic --style vector-illustration --palette macaron`
Or use presets: `--preset tech-explainer` → type + style in one flag. See [Style Presets](references/style-presets.md).
Or use presets: `--preset edu-visual` → type + style + palette in one flag. See [Style Presets](references/style-presets.md).
## Types
@@ -96,13 +97,14 @@ Full procedures: [references/workflow.md](references/workflow.md#step-2-setup--a
| **Q1: Preset or Type** | [Recommended preset], [alt preset], or manual: infographic, scene, flowchart, comparison, framework, timeline, mixed |
| **Q2: Density** | minimal (1-2), balanced (3-5), per-section (Recommended), rich (6+) |
| **Q3: Style** | [Recommended], minimal-flat, sci-fi, hand-drawn, editorial, scene, poster, Other — **skip if preset chosen** |
| Q4: Language | When article language ≠ EXTEND.md setting |
| Q4: Palette | Default (style colors), macaron, warm, neon — **skip if preset includes palette or preferred_palette set** |
| Q5: Language | When article language ≠ EXTEND.md setting |
Full procedures: [references/workflow.md](references/workflow.md#step-3-confirm-settings-)
### Step 4: Generate Outline
Save `outline.md` with frontmatter (type, density, style, image_count) and entries:
Save `outline.md` with frontmatter (type, density, style, palette, image_count) and entries:
```yaml
## Illustration 1
@@ -137,7 +139,7 @@ Insert `![description]({relative-path}/NN-{type}-{slug}.png)` after paragraphs.
```
Article Illustration Complete!
Article: [path] | Type: [type] | Density: [level] | Style: [style]
Article: [path] | Type: [type] | Density: [level] | Style: [style] | Palette: [palette or default]
Images: X/N generated
```
@@ -180,7 +182,7 @@ When input is **pasted content** (no file path), always uses `illustrations/{top
|------|---------|
| [references/workflow.md](references/workflow.md) | Detailed procedures |
| [references/usage.md](references/usage.md) | Command syntax |
| [references/styles.md](references/styles.md) | Style gallery |
| [references/style-presets.md](references/style-presets.md) | Preset shortcuts (type + style) |
| [references/styles.md](references/styles.md) | Style gallery + Palette gallery |
| [references/style-presets.md](references/style-presets.md) | Preset shortcuts (type + style + palette) |
| [references/prompt-construction.md](references/prompt-construction.md) | Prompt templates |
| [references/config/first-time-setup.md](references/config/first-time-setup.md) | First-time setup |
@@ -20,6 +20,8 @@ preferred_style:
name: null # Built-in or custom style name
description: "" # Override/notes
preferred_palette: null # Built-in palette name (macaron|warm|neon) or null
language: null # zh|en|ja|ko|auto
default_output_dir: null # same-dir|illustrations-subdir|independent
@@ -47,6 +49,7 @@ custom_styles:
| `watermark.position` | enum | bottom-right | Position on image |
| `preferred_style.name` | string | null | Style name or null |
| `preferred_style.description` | string | "" | Custom notes/override |
| `preferred_palette` | string | null | Palette override (macaron, warm, neon, or null) |
| `language` | string | null | Output language (null = auto-detect) |
| `default_output_dir` | enum | null | Output directory preference (null = ask each time) |
| `custom_styles` | array | [] | User-defined styles |
@@ -0,0 +1,29 @@
# macaron
Soft macaron pastel color blocks on warm cream
## Background
- Color: Warm Cream (#F5F0E8)
- Texture: Subtle warm paper grain
## Colors
| Role | Color | Hex | Usage |
|------|-------|-----|-------|
| Background | Warm Cream | #F5F0E8 | Primary background |
| Primary Text | Deep Charcoal | #2D2D2D | Headlines, main text, outlines |
| Macaron Blue | Sky Blue | #A8D8EA | Info block fill, cool-toned zones |
| Macaron Mint | Mint Green | #B5E5CF | Info block fill, growth/positive zones |
| Macaron Lavender | Lavender | #D5C6E0 | Info block fill, abstract/concept zones |
| Macaron Peach | Peach | #FFD5C2 | Info block fill, warm-toned zones |
| Accent | Coral Red | #E8655A | Key data, warnings, emphasis |
| Muted Text | Warm Gray | #6B6B6B | Secondary annotations, small labels |
## Accent
Coral Red (#E8655A) for key data, warnings, and emphasis highlights. Use sparingly — one or two elements per illustration.
## Best For
Educational content, knowledge sharing, concept explainers, tutorials, tech summaries, onboarding materials
@@ -0,0 +1,29 @@
# neon
Vibrant neon colors on dark backgrounds
## Background
- Color: Deep Purple (#2D1B4E)
- Texture: Subtle grid pattern or solid dark
## Colors
| Role | Color | Hex | Usage |
|------|-------|-----|-------|
| Background | Deep Purple | #2D1B4E | Primary background |
| Alt Background | Dark Teal | #0F4C5C | Alternative sections |
| Primary | Hot Pink | #FF1493 | Main accent |
| Secondary | Electric Cyan | #00FFFF | Supporting elements |
| Tertiary | Neon Yellow | #FFFF00 | Highlights |
| Accent 1 | Lime Green | #32CD32 | Energy, success |
| Accent 2 | Orange | #FF6B35 | Warmth |
| Text | White | #FFFFFF | Text elements |
## Accent
Hot Pink (#FF1493) for primary emphasis. High contrast neon-on-dark creates immediate visual impact.
## Best For
Gaming, retro tech, 80s/90s nostalgic content, bold editorial, trend and pop culture
@@ -0,0 +1,28 @@
# warm
Warm earth tones on soft peach, no cool colors
## Background
- Color: Soft Peach (#FFECD2)
- Texture: Warm paper texture
## Colors
| Role | Color | Hex | Usage |
|------|-------|-----|-------|
| Background | Soft Peach | #FFECD2 | Primary background |
| Outlines | Deep Charcoal | #2D2D2D | All element outlines |
| Primary | Warm Orange | #ED8936 | Main accent color |
| Secondary | Terracotta | #C05621 | Warm depth |
| Tertiary | Golden Yellow | #F6AD55 | Highlights, energy |
| Accent | Deep Brown | #744210 | Grounding, anchoring |
| Text | Warm Charcoal | #4A4A4A | Text elements |
## Accent
Warm Orange (#ED8936) for primary emphasis. Warm-only palette — no cool colors (no green, blue, purple). Modern-retro feel.
## Best For
Product showcases, team introductions, feature grids, brand content, personal growth, lifestyle
@@ -135,10 +135,10 @@ COLORS: Cream background (#F5F0E6), Coral Red (#E07A5F), Mint Green (#81B29A), M
ELEMENTS: Geometric simplified icons, no gradients, playful decorative elements (dots, stars)
```
**Infographic + vector-illustration (warm palette)**:
**Infographic + vector-illustration + warm palette**:
```
Flat vector illustration infographic. Clean black outlines on all elements.
Warm-only color palette, no cool colors.
PALETTE OVERRIDE (warm): Warm-only color palette, no cool colors.
COLORS: Soft Peach background (#FFECD2), Warm Orange (#ED8936),
Terracotta (#C05621), Golden Yellow (#F6AD55), Deep Brown (#744210)
ELEMENTS: Geometric simplified icons, no gradients, rounded corners,
@@ -182,6 +182,17 @@ COLORS: Cream background (#F5F0E6), steps in Coral/Mint/Mustard, black outlines
ELEMENTS: Rounded rectangles, thick arrows, simple icons per step
```
**Flowchart + sketch-notes + macaron palette**:
```
Hand-drawn educational flowchart on warm cream paper. Slight wobble on all lines.
PALETTE: macaron — soft pastel color blocks
COLORS: Warm Cream background (#F5F0E8), zone fills in Macaron Blue (#A8D8EA),
Lavender (#D5C6E0), Mint (#B5E5CF), Coral Red (#E8655A) for emphasis
ELEMENTS: Rounded cards with dashed/solid borders, wavy hand-drawn arrows with labels,
simple stick-figure characters, doodle decorations (stars, underlines)
STYLE: Color fills don't completely fill outlines, hand-drawn lettering, generous white space
```
### Comparison
```
@@ -207,10 +218,10 @@ COLORS: Left side Coral (#E07A5F), Right side Mint (#81B29A), cream background
ELEMENTS: Bold icons, black outlines, centered divider line
```
**Comparison + vector-illustration (warm palette)**:
**Comparison + vector-illustration + warm palette**:
```
Flat vector comparison with split layout. Clear visual separation.
Warm-only color palette, no cool colors.
PALETTE OVERRIDE (warm): Warm-only color palette, no cool colors.
COLORS: Left side Warm Orange (#ED8936), Right side Terracotta (#C05621),
Soft Peach background (#FFECD2), Deep Brown (#744210) accents
ELEMENTS: Bold icons, black outlines, centered divider line
@@ -239,10 +250,10 @@ COLORS: Cream background (#F5F0E6), nodes in Coral/Mint/Mustard/Blue, black outl
ELEMENTS: Rounded rectangles or circles for nodes, thick connecting lines
```
**Framework + vector-illustration (warm palette)**:
**Framework + vector-illustration + warm palette**:
```
Flat vector framework diagram with geometric nodes and bold connectors.
Warm-only color palette, no cool colors.
PALETTE OVERRIDE (warm): Warm-only color palette, no cool colors.
COLORS: Soft Peach background (#FFECD2), nodes in Warm Orange (#ED8936),
Terracotta (#C05621), Golden Yellow (#F6AD55), black outlines
ELEMENTS: Rounded rectangles or circles for nodes, thick connecting lines
@@ -296,6 +307,39 @@ TEXTURE: Halftone transitions between sides
---
## Palette Override
When a palette is specified (via `--palette` or preset), it overrides the style's default colors:
1. Read style file → get rendering rules (Visual Elements, Style Rules, line treatment)
2. Read palette file (`palettes/<palette>.md`) → get Colors + Background
3. Palette Colors **replace** style's default Color Palette in prompt
4. Palette Background **replaces** style's Background color (keep style's texture description)
5. Build prompt: style rendering instructions + palette colors
**Prompt frontmatter** includes palette when specified:
```yaml
---
illustration_id: 01
type: infographic
style: vector-illustration
palette: macaron
---
```
**Example**: `vector-illustration` + `macaron` palette:
```
Flat vector illustration infographic. Clean black outlines on all elements.
PALETTE: macaron — soft pastel color blocks
COLORS: Warm Cream background (#F5F0E8), Macaron Blue (#A8D8EA), Mint (#B5E5CF),
Lavender (#D5C6E0), Peach (#FFD5C2), Coral Red (#E8655A) for emphasis
ELEMENTS: Geometric simplified icons, no gradients, playful decorative elements
```
When no palette is specified, use the style's built-in Color Palette as before.
---
## What to Avoid
- Vague descriptions ("a nice image")
@@ -1,52 +1,54 @@
# Style Presets
`--preset X` expands to a type + style combination. Users can override either dimension.
`--preset X` expands to a type + style + optional palette combination. Users can override any dimension.
## By Category
### Technical & Engineering
| --preset | Type | Style | Best For |
|----------|------|-------|----------|
| `tech-explainer` | `infographic` | `blueprint` | API docs, system metrics, technical deep-dives |
| `system-design` | `framework` | `blueprint` | Architecture diagrams, system design |
| `architecture` | `framework` | `vector-illustration` | Component relationships, module structure |
| `science-paper` | `infographic` | `scientific` | Research findings, lab results, academic |
| --preset | Type | Style | Palette | Best For |
|----------|------|-------|---------|----------|
| `tech-explainer` | `infographic` | `blueprint` | — | API docs, system metrics, technical deep-dives |
| `system-design` | `framework` | `blueprint` | — | Architecture diagrams, system design |
| `architecture` | `framework` | `vector-illustration` | — | Component relationships, module structure |
| `science-paper` | `infographic` | `scientific` | — | Research findings, lab results, academic |
### Knowledge & Education
| --preset | Type | Style | Best For |
|----------|------|-------|----------|
| `knowledge-base` | `infographic` | `vector-illustration` | Concept explainers, tutorials, how-to |
| `saas-guide` | `infographic` | `notion` | Product guides, SaaS docs, tool walkthroughs |
| `tutorial` | `flowchart` | `vector-illustration` | Step-by-step tutorials, setup guides |
| `process-flow` | `flowchart` | `notion` | Workflow documentation, onboarding flows |
| `warm-knowledge` | `infographic` | `vector-illustration` (warm palette) | Product showcases, team intros, feature cards, brand content |
| --preset | Type | Style | Palette | Best For |
|----------|------|-------|---------|----------|
| `knowledge-base` | `infographic` | `vector-illustration` | — | Concept explainers, tutorials, how-to |
| `saas-guide` | `infographic` | `notion` | — | Product guides, SaaS docs, tool walkthroughs |
| `tutorial` | `flowchart` | `vector-illustration` | — | Step-by-step tutorials, setup guides |
| `process-flow` | `flowchart` | `notion` | — | Workflow documentation, onboarding flows |
| `warm-knowledge` | `infographic` | `vector-illustration` | `warm` | Product showcases, team intros, feature cards, brand content |
| `edu-visual` | `infographic` | `vector-illustration` | `macaron` | Knowledge summaries, concept explainers, educational articles |
| `hand-drawn-edu` | `flowchart` | `sketch-notes` | `macaron` | Hand-drawn educational diagrams, process explainers, onboarding visuals |
### Data & Analysis
| --preset | Type | Style | Best For |
|----------|------|-------|----------|
| `data-report` | `infographic` | `editorial` | Data journalism, metrics reports, dashboards |
| `versus` | `comparison` | `vector-illustration` | Tech comparisons, framework shootouts |
| `business-compare` | `comparison` | `elegant` | Product evaluations, strategy options |
| --preset | Type | Style | Palette | Best For |
|----------|------|-------|---------|----------|
| `data-report` | `infographic` | `editorial` | — | Data journalism, metrics reports, dashboards |
| `versus` | `comparison` | `vector-illustration` | — | Tech comparisons, framework shootouts |
| `business-compare` | `comparison` | `elegant` | — | Product evaluations, strategy options |
### Narrative & Creative
| --preset | Type | Style | Best For |
|----------|------|-------|----------|
| `storytelling` | `scene` | `warm` | Personal essays, reflections, growth stories |
| `lifestyle` | `scene` | `watercolor` | Travel, wellness, lifestyle, creative |
| `history` | `timeline` | `elegant` | Historical overviews, milestones |
| `evolution` | `timeline` | `warm` | Progress narratives, growth journeys |
| --preset | Type | Style | Palette | Best For |
|----------|------|-------|---------|----------|
| `storytelling` | `scene` | `warm` | — | Personal essays, reflections, growth stories |
| `lifestyle` | `scene` | `watercolor` | — | Travel, wellness, lifestyle, creative |
| `history` | `timeline` | `elegant` | — | Historical overviews, milestones |
| `evolution` | `timeline` | `warm` | — | Progress narratives, growth journeys |
### Editorial & Opinion
| --preset | Type | Style | Best For |
|----------|------|-------|----------|
| `opinion-piece` | `scene` | `screen-print` | Op-eds, commentary, critical essays |
| `editorial-poster` | `comparison` | `screen-print` | Debate, contrasting viewpoints |
| `cinematic` | `scene` | `screen-print` | Dramatic narratives, cultural essays |
| --preset | Type | Style | Palette | Best For |
|----------|------|-------|---------|----------|
| `opinion-piece` | `scene` | `screen-print` | — | Op-eds, commentary, critical essays |
| `editorial-poster` | `comparison` | `screen-print` | — | Debate, contrasting viewpoints |
| `cinematic` | `scene` | `screen-print` | — | Dramatic narratives, cultural essays |
## Content Type → Preset Recommendations
@@ -55,7 +57,7 @@ Use this table during Step 3 to recommend presets based on Step 2 content analys
| Content Type (Step 2) | Primary Preset | Alternatives |
|------------------------|----------------|--------------|
| Technical | `tech-explainer` | `system-design`, `architecture` |
| Tutorial | `tutorial` | `process-flow`, `knowledge-base` |
| Tutorial | `tutorial` | `process-flow`, `knowledge-base`, `edu-visual` |
| Methodology / Framework | `system-design` | `architecture`, `process-flow` |
| Data / Metrics | `data-report` | `versus`, `tech-explainer` |
| Comparison / Review | `versus` | `business-compare`, `editorial-poster` |
@@ -64,6 +66,7 @@ Use this table during Step 3 to recommend presets based on Step 2 content analys
| Historical / Timeline | `history` | `evolution` |
| Academic / Research | `science-paper` | `tech-explainer`, `data-report` |
| SaaS / Product | `saas-guide` | `knowledge-base`, `process-flow`, `warm-knowledge` |
| Education / Knowledge | `edu-visual` | `knowledge-base`, `tutorial`, `hand-drawn-edu` |
## Override Examples
@@ -98,12 +98,6 @@ Full specifications: `references/styles/<style>.md`
- Modern, professional, highly readable
- Perfect for knowledge articles and tutorials
### infographic + vector-illustration (warm palette)
- Same rendering: flat vector, black outlines, geometric simplification
- Warm-only palette: terracotta, gold, brown tones on soft peach
- Modern-retro feel, approachable and brand-friendly
- Best for product showcases, team intros, feature grids, brand content
### flowchart + vector-illustration
- Bold arrows and connectors
- Distinct step containers with icons
@@ -200,3 +194,28 @@ Full specifications: `references/styles/<style>.md`
- Limited color coding (one color per concept level)
- Clean silhouette-based iconography
- Poster-style hierarchy with bold typography
---
## Palette Gallery
Palettes override a style's default colors. Combine any style with any palette: `--style vector-illustration --palette macaron`.
| Palette | Description | Best For |
|---------|-------------|----------|
| `macaron` | Soft pastel blocks (blue, mint, lavender, peach) on warm cream | Educational, knowledge, tutorials |
| `warm` | Warm earth tones (orange, terracotta, gold) on soft peach, no cool colors | Brand, product, lifestyle |
| `neon` | Vibrant neon (pink, cyan, yellow) on dark purple | Gaming, retro, pop culture |
Full specifications: `references/palettes/<palette>.md`
When no palette is specified, the style's built-in Color Palette is used.
## Palette Override Rules
1. Read style file → rendering rules (Visual Elements, Style Rules)
2. Read palette file → Colors + Background
3. Palette colors **replace** style's default Color Palette
4. Palette Background **replaces** style's default Background color
5. Style's texture description is preserved
@@ -24,26 +24,6 @@ Flat vector illustration with no gradients or 3D effects. Clear, uniform-thickne
| Accent 2 | Rock Blue | #577590 | Cool balance |
| Text | Black | #1A1A1A | Text elements |
## Palette Variants
### Warm Palette
Use with `--preset warm-knowledge` or specify in prompt. For product showcases, team introductions, feature grids, brand content.
| Role | Color | Hex | Usage |
|------|-------|-----|-------|
| Background | Soft Peach | #FFECD2 | Primary background |
| Outlines | Deep Charcoal | #2D2D2D | All element outlines |
| Primary | Warm Orange | #ED8936 | Main accent color |
| Secondary | Terracotta | #C05621 | Warm depth |
| Tertiary | Golden Yellow | #F6AD55 | Highlights, energy |
| Accent | Deep Brown | #744210 | Grounding, anchoring |
| Text | Warm Charcoal | #4A4A4A | Text elements |
Warm-only palette, no cool colors (no green, blue, purple). Modern-retro feel.
Default palette includes Mint Green (#81B29A) and Rock Blue (#577590) for colorful educational content. Warm palette uses exclusively warm tones for brand/product/team content.
## Visual Elements
- All objects have closed black outlines (coloring book style)
@@ -211,9 +211,22 @@ If no `preferred_style` (present Core Styles first):
| `poster` | screen-print | Opinion, editorial, cultural, cinematic |
Style selection based on Type × Style compatibility matrix (styles.md).
Full specs: `styles/<style>.md`
**In Step 5.1**, read `styles/<style>.md` for visual elements and rendering rules.
### Q4: Image Text Language ⚠️ REQUIRED when article language ≠ EXTEND.md `language`
### Q4: Palette (optional)
If preset did not specify a palette, and the user may benefit from a palette override, offer available palettes:
- Default (use style's built-in colors) (Recommended)
- `macaron` — soft pastel blocks on warm cream
- `warm` — warm earth tones, no cool colors
- `neon` — vibrant neon on dark backgrounds
**Skip if**: preset already resolved palette, or `preferred_palette` set in EXTEND.md.
See Palette Gallery in [styles.md](styles.md#palette-gallery) and full specs in `palettes/<palette>.md`.
### Q5: Image Text Language ⚠️ REQUIRED when article language ≠ EXTEND.md `language`
Detect article language from content. If different from EXTEND.md `language` setting, MUST ask:
- Article language (match article content) (Recommended)
@@ -294,16 +307,18 @@ For each illustration in the outline:
style: custom-flat-vector
---
```
3. **Follow type-specific template** from [prompt-construction.md](prompt-construction.md)
4. **Prompt quality requirements** (all REQUIRED):
3. **Load style specs**: Read `styles/<style>.md` for visual elements, style rules, and rendering instructions
4. **Load palette specs** (if palette specified): Read `palettes/<palette>.md` for colors and background. Palette colors **replace** the style's default Color Palette. If no palette specified, use the style's built-in colors.
5. **Follow type-specific template** from [prompt-construction.md](prompt-construction.md), using rendering from style + colors from palette (or style default)
6. **Prompt quality requirements** (all REQUIRED):
- `Layout`: Describe overall composition (grid / radial / hierarchical / left-right / top-down)
- `ZONES`: Describe each visual area with specific content, not vague descriptions
- `LABELS`: Use **actual numbers, terms, metrics, quotes from the article** — NOT generic placeholders
- `COLORS`: Specify hex codes with semantic meaning (e.g., `Coral (#E07A5F) for emphasis`)
- `STYLE`: Describe line treatment, texture, mood, character rendering
- `COLORS`: Specify hex codes from palette (or style default) with semantic meaning
- `STYLE`: Describe line treatment, texture, mood, character rendering per style rules
- `ASPECT`: Specify ratio (e.g., `16:9`)
5. **Apply defaults**: composition requirements, character rendering, text guidelines, watermark
6. **Backup rule**: If prompt file exists, rename to `prompts/NN-{type}-{slug}-backup-YYYYMMDD-HHMMSS.md`
7. **Apply defaults**: composition requirements, character rendering, text guidelines, watermark
8. **Backup rule**: If prompt file exists, rename to `prompts/NN-{type}-{slug}-backup-YYYYMMDD-HHMMSS.md`
**Verification** ⛔: Before proceeding to 5.2, confirm ALL prompt files exist:
```
+47 -26
View File
@@ -29,9 +29,9 @@ Create original knowledge comics with flexible art style × tone combinations.
| Option | Values | Description |
|--------|--------|-------------|
| `--art` | ligne-claire (default), manga, realistic, ink-brush, chalk | Art style / rendering technique |
| `--art` | ligne-claire (default), manga, realistic, ink-brush, chalk, minimalist | Art style / rendering technique |
| `--tone` | neutral (default), warm, dramatic, romantic, energetic, vintage, action | Mood / atmosphere |
| `--layout` | standard (default), cinematic, dense, splash, mixed, webtoon | Panel arrangement |
| `--layout` | standard (default), cinematic, dense, splash, mixed, webtoon, four-panel | Panel arrangement |
| `--aspect` | 3:4 (default, portrait), 4:3 (landscape), 16:9 (widescreen) | Page aspect ratio |
| `--lang` | auto (default), zh, en, ja, etc. | Output language |
@@ -55,6 +55,7 @@ Details: [references/partial-workflows.md](references/partial-workflows.md)
| `realistic` | 写实 | Digital painting, realistic proportions, sophisticated |
| `ink-brush` | 水墨 | Chinese brush strokes, ink wash effects |
| `chalk` | 粉笔 | Chalkboard aesthetic, hand-drawn warmth |
| `minimalist` | 极简 | Clean black line art, limited spot color, stick-figure characters |
### Tones (基调)
@@ -77,6 +78,8 @@ Presets with special rules beyond art+tone:
| `--style ohmsha` | `--art manga --tone neutral` | Visual metaphors, NO talking heads, gadget reveals |
| `--style wuxia` | `--art ink-brush --tone action` | Qi effects, combat visuals, atmospheric elements |
| `--style shoujo` | `--art manga --tone romantic` | Decorative elements, eye details, romantic beats |
| `--style concept-story` | `--art manga --tone warm` | Visual symbol system, growth arc, dialogue+action balance |
| `--style four-panel` | `--art minimalist --tone neutral --layout four-panel` | 起承转合 4-panel structure, B&W + spot color, stick-figure characters |
### Compatibility Matrix
@@ -87,6 +90,7 @@ Presets with special rules beyond art+tone:
| realistic | neutral, warm, dramatic, vintage | action | romantic, energetic |
| ink-brush | neutral, dramatic, action, vintage | warm | romantic, energetic |
| chalk | neutral, warm, energetic | vintage | dramatic, action, romantic |
| minimalist | neutral | warm, energetic | dramatic, vintage, romantic, action |
Details: [references/auto-selection.md](references/auto-selection.md)
@@ -101,6 +105,8 @@ Content signals determine default art + tone + layout (or preset):
| Personal story, mentor | ligne-claire + warm |
| Martial arts, wuxia | **wuxia** preset |
| Romance, school life | **shoujo** preset |
| Psychology, motivation, business narrative | **concept-story** preset |
| Business allegory, fable, parable, short insight, 四格 | **four-panel** preset |
| Biography, balanced | ligne-claire + neutral |
**When preset is recommended**: Load `references/presets/{preset}.md` and apply all special rules.
@@ -172,9 +178,9 @@ Comic Progress:
- [ ] Step 4: Review outline (conditional)
- [ ] Step 5: Generate prompts
- [ ] Step 6: Review prompts (conditional)
- [ ] Step 7: Generate images ⚠️ CHARACTER REF REQUIRED
- [ ] 7.1 Generate character sheet FIRST → characters/characters.png
- [ ] 7.2 Generate pages WITH --ref characters/characters.png
- [ ] Step 7: Generate images
- [ ] 7.1 Generate character sheet (if needed) → characters/characters.png
- [ ] 7.2 Generate pages (with --ref if character sheet exists)
- [ ] Step 8: Merge to PDF
- [ ] Step 9: Completion report
```
@@ -205,16 +211,24 @@ Analyze → [Check Existing?] → [Confirm: Style + Reviews] → Storyboard →
| 4 | Review outline (if requested) | User approval |
| 5 | Generate prompts | `prompts/*.md` |
| 6 | Review prompts (if requested) | User approval |
| **7.1** | **Generate character sheet FIRST** | `characters/characters.png` |
| **7.2** | Generate pages **with character ref** | `*.png` files |
| 7.1 | Generate character sheet (if needed) | `characters/characters.png` |
| 7.2 | Generate pages (with character ref if available) | `*.png` files |
| 8 | Merge to PDF | `{slug}.pdf` |
| 9 | Completion report | Summary |
### Step 7: Image Generation ⚠️ CRITICAL
### Step 7: Image Generation
**Character reference is MANDATORY for visual consistency.**
**7.1 Generate character sheet (conditional)**:
**7.1 Generate character sheet first**:
Character sheet is recommended for multi-page comics with recurring characters, but **NOT required** for all presets:
| Condition | Action |
|-----------|--------|
| Multi-page comic with detailed characters | Generate character sheet (recommended) |
| Preset with simplified characters (e.g., four-panel minimalist) | Skip — prompt descriptions are sufficient |
| Single-page comic | Skip unless characters are complex |
**When generating character sheet**:
- **Backup rule**: If `characters/characters.png` exists, rename to `characters/characters-backup-YYYYMMDD-HHMMSS.png`
- Invoke an installed image generation skill such as `baoyu-imagine`
- Read that skill's `SKILL.md` and follow its documented interface rather than calling its scripts directly
@@ -222,18 +236,25 @@ Analyze → [Check Existing?] → [Confirm: Style + Reviews] → Storyboard →
- Save output to `characters/characters.png`
- Use aspect ratio `4:3`
**Compress character sheet** (recommended):
Compress to reduce token usage when used as reference image:
**Compress character sheet** (recommended when using as `--ref`):
- Use available image compression skill (if any)
- Or system tools: `pngquant`, `optipng`, `sips` (macOS)
- **Keep PNG format**, lossless compression preferred
- Or system tools: `sips -s format jpeg -s formatOptions 80 input.png --out output.jpg` (macOS)
- Or: `pngquant --quality=65-80 input.png -o output.png`
- Compression reduces API payload size and avoids `--ref` failures
**7.2 Generate each page WITH character reference**:
**7.2 Generate each page**:
| Skill Capability | Strategy |
|------------------|----------|
| Supports `--ref` | Pass `characters/characters.png` with EVERY page |
| No `--ref` support | Prepend character descriptions to EVERY prompt file |
| Character Sheet | Skill Capability | Strategy |
|-----------------|------------------|----------|
| Exists | Supports `--ref` | Pass `characters/characters.png` with EVERY page |
| Exists | No `--ref` support | Prepend character descriptions to EVERY prompt file |
| Skipped | — | Prompt file contains all character descriptions inline |
**`--ref` failure recovery**: If generation fails with `--ref`:
1. **Compress**: Convert reference image to JPEG with reduced quality:
`sips -s format jpeg -s formatOptions 70 characters.png --out characters-compressed.jpg`
2. **Retry** with compressed image as `--ref`
3. **If still fails**: Fall back to generating WITHOUT `--ref` (prompt-only, character descriptions embedded in prompt text)
**Backup rules for page generation**:
- If prompt file exists: rename to `prompts/NN-{cover|page}-[slug]-backup-YYYYMMDD-HHMMSS.md`
@@ -241,8 +262,8 @@ Compress to reduce token usage when used as reference image:
- Invoke the installed image generation skill for each page
- Use `prompts/01-page-xxx.md` as the prompt-file input
- Save output to `01-page-xxx.png`
- Use aspect ratio `3:4`
- If the chosen skill supports reference images, pass `characters/characters.png` as `--ref`
- Use aspect ratio from storyboard (default `3:4`, preset may override)
- If character sheet exists and skill supports reference images, pass as `--ref`
**Full workflow details**: [references/workflow.md](references/workflow.md)
@@ -273,10 +294,10 @@ Schema: [references/config/preferences-schema.md](references/config/preferences-
- [ohmsha-guide.md](references/ohmsha-guide.md) - Ohmsha manga specifics
**Style Definitions**:
- `references/art-styles/` - Art styles (ligne-claire, manga, realistic, ink-brush, chalk)
- `references/art-styles/` - Art styles (ligne-claire, manga, realistic, ink-brush, chalk, minimalist)
- `references/tones/` - Tones (neutral, warm, dramatic, romantic, energetic, vintage, action)
- `references/presets/` - Presets with special rules (ohmsha, wuxia, shoujo)
- `references/layouts/` - Layouts (standard, cinematic, dense, splash, mixed, webtoon)
- `references/presets/` - Presets with special rules (ohmsha, wuxia, shoujo, concept-story, four-panel)
- `references/layouts/` - Layouts (standard, cinematic, dense, splash, mixed, webtoon, four-panel)
**Workflow**:
- [workflow.md](references/workflow.md) - Full workflow details
@@ -306,6 +327,6 @@ Schema: [references/config/preferences-schema.md](references/config/preferences-
- Maintain style consistency via session ID
- **Step 2 confirmation required** - do not skip
- **Steps 4/6 conditional** - only if user requested in Step 2
- **Step 7.1 character sheet MUST be generated before pages** - ensures consistency
- **Step 7.2 EVERY page MUST reference characters** - use `--ref` or embed descriptions
- **Step 7.1 character sheet** - recommended for multi-page comics, optional for simple presets
- **Step 7.2 character reference** - use `--ref` if sheet exists; compress/convert on failure; fall back to prompt-only
- Watermark/language configured once in EXTEND.md
@@ -0,0 +1,84 @@
# minimalist
极简画风 - Clean black line art, limited spot color, simplified stick-figure characters
## Overview
Minimalist cartoon illustration characterized by clean black line art on white background with very limited spot color for emphasis. Characters are simplified to near-stick-figure abstraction, focusing on gesture and concept rather than anatomical detail. Designed for business allegory, quick-read educational content, and concept illustration.
## Line Work
- Clean, uniform black lines (1.5-2px)
- No hatching, cross-hatching, or shading techniques
- Minimal detail — every line serves a purpose
- Bold outlines for characters, thinner lines for props/labels
- No decorative flourishes or ornamental lines
## Character Design
- Highly simplified, stick-figure-like business characters
- Circle or oval heads with minimal facial features (dot eyes, simple line mouth)
- Body as simple geometric shapes or line constructions
- Distinguishing features through props only (tie, hat, briefcase, glasses)
- No anatomical detail — expressive through posture and gesture
- 4-5 head height proportions (squat, iconic)
## Background Treatment
- Mostly blank/white — negative space is a design element
- Minimal environmental cues (a line for ground, simple desk outline)
- Concept labels and text annotations replace detailed environments
- Icons and symbols over realistic rendering
- No perspective or spatial depth
## Color Approach
- Primarily black and white (90%+ of the image)
- 1-2 spot accent colors for emphasis on key concepts
- Accent color used sparingly: highlighting key objects, text labels, concept indicators
- No gradients, no shading, no color fills on backgrounds
- Color draws the eye to the most important element in each panel
## Default Color Palette
| Role | Color | Hex |
|------|-------|-----|
| Primary | Black ink | `#1A1A1A` |
| Background | Clean white | `#FFFFFF` |
| Accent 1 | Spot orange | `#FF6B35` |
| Accent 2 | Spot blue (optional) | `#3182CE` |
| Text labels | Dark gray | `#4A4A4A` |
| Panel border | Medium gray | `#666666` |
## Visual Elements
- Text labels with accent-color backgrounds or underlines for key terms
- Simple icons: arrows, circles, checkmarks, crosses
- Concept highlight boxes with spot color
- Minimal speech bubbles (simple oval or rectangle, thin black outline)
- No sound effects, no motion lines, no screen tones
## Quality Markers
- ✓ Clean, purposeful line work with no unnecessary detail
- ✓ 90%+ black-and-white with strategic spot color
- ✓ Simplified characters readable at small sizes
- ✓ Text labels integrated naturally into panels
- ✓ Strong negative space usage
- ✓ Every element serves the narrative point
## Compatibility
| Tone | Fit | Notes |
|------|-----|-------|
| neutral | ✓✓ | Ideal for business/educational content |
| warm | ✓ | Works for gentle stories, slight warmth in accent |
| energetic | ✓ | Works for punchy, high-energy content |
| dramatic | ✗ | Style too stripped down for dramatic intensity |
| vintage | ✗ | Minimalist aesthetic conflicts with aged/textured look |
| romantic | ✗ | No capacity for decorative/soft elements |
| action | ✗ | No dynamic line capability for speed/impact |
## Best For
Business allegory, management fables, short concept illustration, four-panel comic strips, quick-insight education, social media content
@@ -11,10 +11,13 @@ Content signals determine default art + tone + layout (or preset).
| Technical explanation, educational | manga | neutral | webtoon | **ohmsha** |
| Pre-1950, classical, ancient | realistic | vintage | cinematic | - |
| Personal story, mentor | ligne-claire | warm | standard | - |
| Psychology, motivation, self-help, coaching | manga | warm | standard | **concept-story** |
| Business narrative, management, leadership | manga | warm | standard | **concept-story** |
| Conflict, breakthrough | (inherit) | dramatic | splash | - |
| Wine, food, business, lifestyle | realistic | neutral | cinematic | - |
| Wine, food, lifestyle | realistic | neutral | cinematic | - |
| Martial arts, wuxia, xianxia | ink-brush | action | splash | **wuxia** |
| Romance, love, school life | manga | romantic | standard | **shoujo** |
| Business allegory, fable, parable, short insight, 四格 | minimalist | neutral | four-panel | **four-panel** |
| Biography, balanced | ligne-claire | neutral | mixed | - |
## Preset Recommendation Rules
@@ -36,6 +39,16 @@ Content signals determine default art + tone + layout (or preset).
- **Special rules**: Decorative elements, eye details, romantic beats
- **Base**: manga + romantic + standard
### concept-story
- **Triggers**: Psychology, motivation, self-help, business narrative, management, leadership, personal growth, coaching, soft skills, abstract concept through story
- **Special rules**: Visual symbol system, growth arc, dialogue+action balance, original characters
- **Base**: manga + warm + standard
### four-panel
- **Triggers**: Business allegory, fable, parable, short insight, four-panel, 四格, 四格漫画, single-page comic, minimalist comic strip
- **Special rules**: Strict 起承转合 4-panel structure, B&W + spot color, simplified stick-figure characters, single-page story
- **Base**: minimalist + neutral + four-panel
## Compatibility Matrix
Art Style × Tone combinations work best when matched appropriately:
@@ -47,6 +60,7 @@ Art Style × Tone combinations work best when matched appropriately:
| realistic | neutral, warm, dramatic, vintage | action | romantic, energetic |
| ink-brush | neutral, dramatic, action, vintage | warm | romantic, energetic |
| chalk | neutral, warm, energetic | vintage | dramatic, action, romantic |
| minimalist | neutral | warm, energetic | dramatic, vintage, romantic, action |
**Note**: Art Style × Tone × Layout can be freely combined. Incompatible combinations work but may produce unexpected results.
@@ -16,9 +16,9 @@ watermark:
content: ""
position: bottom-right # bottom-right|bottom-left|bottom-center|top-right
preferred_art: null # ligne-claire|manga|realistic|ink-brush|chalk
preferred_art: null # ligne-claire|manga|realistic|ink-brush|chalk|minimalist
preferred_tone: null # neutral|warm|dramatic|romantic|energetic|vintage|action
preferred_layout: null # standard|cinematic|dense|splash|mixed|webtoon
preferred_layout: null # standard|cinematic|dense|splash|mixed|webtoon|four-panel
preferred_aspect: null # 3:4|4:3|16:9
language: null # zh|en|ja|ko|auto
@@ -41,7 +41,7 @@ character_presets:
| `watermark.enabled` | bool | false | Enable watermark |
| `watermark.content` | string | "" | Watermark text (@username or custom) |
| `watermark.position` | enum | bottom-right | Position on image |
| `preferred_art` | string | null | Art style (ligne-claire, manga, realistic, ink-brush, chalk) |
| `preferred_art` | string | null | Art style (ligne-claire, manga, realistic, ink-brush, chalk, minimalist) |
| `preferred_tone` | string | null | Tone (neutral, warm, dramatic, romantic, energetic, vintage, action) |
| `preferred_layout` | string | null | Layout preference or null |
| `preferred_aspect` | string | null | Aspect ratio (3:4, 4:3, 16:9) |
@@ -57,6 +57,7 @@ character_presets:
| `realistic` | 写实 | Digital painting, realistic proportions |
| `ink-brush` | 水墨 | Chinese brush strokes, ink wash effects |
| `chalk` | 粉笔 | Chalkboard aesthetic, hand-drawn warmth |
| `minimalist` | 极简 | Clean black line art, limited spot color, stick-figure characters |
## Tone Options
@@ -0,0 +1,40 @@
# four-panel
四格漫画 - Strict 2×2 grid, single-page story
## Panel Structure
- **Panels per page**: 4 (exactly, no variation)
- **Structure**: Strict 2×2 equal grid
- **Gutters**: Consistent white space (8-10px), uniform on all sides
## Grid Configuration
- 2 columns × 2 rows, all panels identical size
- Panel sizes: Exactly equal (each panel = 25% of content area)
- Reading flow: Z-pattern — Panel 1 (top-left) → Panel 2 (top-right) → Panel 3 (bottom-left) → Panel 4 (bottom-right)
## Narrative Structure
Each panel serves a specific narrative role (起承转合 / kishōtenketsu):
| Panel | Position | Role | Purpose |
|-------|----------|------|---------|
| 1 | Top-left | 起 Setup | Establish situation, introduce characters/problem |
| 2 | Top-right | 承 Development | Build on setup, add complication or attempt |
| 3 | Bottom-left | 转 Turn | Twist, key insight, or reversal — the pivotal moment |
| 4 | Bottom-right | 合 Conclusion | Resolution, punchline, or takeaway |
## Aspect Ratio
- Recommended page aspect: **4:3** (landscape)
- Landscape gives each panel a comfortable wide rectangle
- Portrait (3:4) makes panels tall and narrow — avoid for this layout
## Best For
Business allegory, quick-insight education, social media comics, fables, parables, single-concept explanation
## Best Style Pairings
minimalist, ligne-claire, chalk
@@ -0,0 +1,121 @@
# concept-story
概念故事预设 - Narrative comics that visualize abstract concepts through character-driven stories
## Base Configuration
| Dimension | Value |
|-----------|-------|
| Art Style | manga |
| Tone | warm |
| Layout | standard (default) |
Equivalent to: `--art manga --tone warm`
## Unique Rules
This preset includes special rules beyond the art+tone combination. When `--style concept-story` is used, ALL rules below must be applied.
### Concept Visualization System (CRITICAL)
Each major abstract concept SHOULD have a recurring visual symbol/metaphor:
| Concept Type | Visualization Approach |
|-------------|----------------------|
| Psychological need | Tangible object character holds or discovers (e.g., glowing energy ball = competence) |
| Management principle | Environmental metaphor character navigates (e.g., ship wheel = autonomy) |
| Growth/development | Living organic symbol that transforms (e.g., seed → flowering plant = relatedness) |
| Abstract framework | Spatial structure characters can enter or observe |
| Emotional state | Color/lighting shift in the scene atmosphere |
**Unlike ohmsha**: Dialogue panels are allowed and expected. The goal is to COMBINE visual metaphors WITH dialogue, not replace dialogue entirely.
**Pattern**: "Dialogue introduces idea" → "Visual metaphor illustrates it" → "Character reacts/applies it"
### Visual Symbol Continuity
Symbols must persist across the story:
| Stage | Treatment |
|-------|-----------|
| Introduction | Symbol appears with soft glow effect when concept is first mentioned |
| Recurrence | Same symbol reappears in background or character interaction when concept is referenced |
| Resolution | ALL symbols gather in the final composition, showing integration of learned concepts |
**Storyboard requirement**: Include a Symbol Mapping Table defining concept → visual symbol before panel breakdown.
### Character Archetypes (Flexible)
Create original characters based on content domain. No fixed defaults:
| Role | Archetype | Visual Cues |
|------|-----------|------------|
| Protagonist | Learner/worker facing a challenge | Modern professional or student, relatable, starts with constrained posture |
| Mentor | Experienced guide who teaches through experience | Slightly older, calm demeanor, warm color accents |
| Catalyst | Person or event that triggers transformation | Can be a colleague, situation, challenge, or opportunity |
**IMPORTANT**: Characters are created fresh each time based on the source content's domain (business, psychology, education, etc.). No default character set.
### Narrative Arc Structure
Enforce a five-stage growth arc:
| Act | Structure | Visual Tone |
|-----|-----------|------------|
| Opening | Protagonist stuck in routine, faces frustration | Muted warm tones, tight framing, constrained compositions |
| Inciting moment | Mentor appears or opportunity arrives | Brightness increases, panels open up |
| Learning | Concepts introduced through visual metaphors | Rich warm palette, symbols introduced one by one |
| Turning point | Protagonist applies knowledge, faces test | Contrast increases, dynamic compositions |
| Transformation | Growth demonstrated, new understanding visible | Full warm palette, expansive composition, all symbols present |
### Dialogue + Action Balance
- Dialogue is encouraged and expected (unlike ohmsha's NO talking heads rule)
- Every page should combine at least one dialogue panel with at least one visual/action panel
- Avoid pure "lecture" pages where a character explains for 4+ panels straight
- When a character explains a concept verbally, the NEXT panel should visualize it
**Wrong approach**: Four consecutive panels of mentor lecturing at protagonist
**Right approach**: Mentor introduces concept → visual metaphor panel → protagonist reacts → applies understanding
### Scene Atmosphere Rules
| Scene Type | Atmosphere |
|------------|-----------|
| Problem/frustration | Cool muted tones over warm base, tight framing, cluttered environment |
| Mentoring moment | Golden hour lighting, open composition, warm indoor glow |
| Concept visualization | Soft glow effects, clean simplified backgrounds, symbol spotlight |
| Growth/transformation | Warm light expanding outward, character posture opening up |
| Resolution | Full warm palette, spacious composition, all visual symbols visible |
### Ending Requirements
Final page MUST include:
1. Protagonist demonstrating transformed understanding (not just being told)
2. Visual callback showing contrast with opening state (e.g., wilted plant → thriving plant)
3. All concept symbols visible together in the composition
4. A forward-looking element suggesting ongoing growth (not a closed ending)
### Page Title Convention
Every page MUST have a narrative title:
**Wrong**: "Chapter 3: Self-Determination Theory"
**Right**: "The Day Xiao Ming Found His Own Engine"
## Quality Markers
- ✓ Each major concept has a recurring visual symbol
- ✓ Dialogue and visual metaphors work together (not one replacing the other)
- ✓ Clear growth arc from problem to transformation
- ✓ Original characters suited to the content domain
- ✓ Warm, professional atmosphere throughout
- ✓ Visual symbols recur and accumulate through the story
- ✓ Final page integrates all concept symbols with transformation callback
## Best For
Psychology concepts, business/management principles, motivation theory, personal development,
self-help content, leadership frameworks, coaching narratives, soft skill education,
abstract concept explanation through character-driven stories
@@ -0,0 +1,107 @@
# four-panel
四格漫画预设 - Minimalist four-panel business allegory comics
## Base Configuration
| Dimension | Value |
|-----------|-------|
| Art Style | minimalist |
| Tone | neutral |
| Layout | four-panel (default) |
| Aspect | 4:3 (landscape) |
Equivalent to: `--art minimalist --tone neutral --layout four-panel --aspect 4:3`
## Unique Rules
This preset includes special rules beyond the art+tone combination. When `--style four-panel` is used, ALL rules below must be applied.
### 起承转合 Narrative Structure (CRITICAL)
Every comic MUST follow the four-panel 起承转合 structure:
| Panel | Role | Requirements |
|-------|------|-------------|
| 1 (起 Setup) | Introduce the situation | Show character(s) in a recognizable context. Establish the "normal" state or problem |
| 2 (承 Development) | Build on the setup | Add complication, show an attempt, or introduce the concept. Stakes become clearer |
| 3 (转 Turn) | The twist or key insight | **Most important panel.** Show the unexpected reversal, contrast, or "aha" moment that makes the allegory work |
| 4 (合 Conclusion) | Resolution and takeaway | Show the result, consequence, or lesson learned. Can be a visual punchline or summary |
**CRITICAL**: Do NOT deviate from exactly 4 panels. No 5th panel, no title panel, no footer panel within the image.
### Single-Page Story Rule (CRITICAL)
- The entire story is told in ONE page with exactly 4 panels
- Page count: always 1 (plus optional cover)
- No multi-page four-panel stories — if content requires more, create multiple separate four-panel comics
- Storyboard structure: Cover (optional) + 1 page
### Accent Color System
- The image is primarily black-and-white line art
- Use exactly 1-2 spot colors per strip (default: orange `#FF6B35`)
- Rules:
- Key concept label or object: filled with accent color or outlined in accent
- Panel 3 (转 Turn) should have the strongest color emphasis
- Characters remain B&W — color is for concepts/objects/labels only
- Consistent accent color across all 4 panels (do not switch colors between panels)
### Character Design Rules
- Simplified stick-figure-like characters
- Distinguish characters through simple props: ties, glasses, hats, briefcases, aprons
- No detailed faces — dot eyes, line mouth at most
- Characters should be generic enough to represent archetypes (the manager, the employee, the customer)
- Maximum 2-3 characters per strip
### Text in Panels
- Chinese text for dialogue and labels (or match source language)
- Keep text minimal — 1-2 short lines per panel maximum
- Key concept terms can be highlighted with accent color background
- No narrator boxes — dialogue and labels only
- Speech bubbles: simple rectangles or ovals, thin black outline
### Optional Title & Caption
- A brief descriptive title above the 4 panels
- An optional one-line caption/moral below the panels
- These are part of the page composition, not separate panels
### Character Archetypes (Flexible)
Create simple stick-figure characters based on content. No fixed defaults:
| Role | Archetype | Visual Cues |
|------|-----------|------------|
| Protagonist | Worker/employee facing a situation | Simple figure, minimal distinguishing feature (glasses, tie) |
| Authority | Boss/manager/expert | Slightly larger figure, or prop like pointer/clipboard |
| Object | The concept itself | Labeled object, icon, or highlighted text with accent color |
### Prompt Template
When generating image prompts for four-panel comics, include these keywords:
> A minimalist, clean line art digital comic strip in a four-panel grid layout (2×2). The style is simplified cartoon illustration with clear black outlines and a minimal color palette of black, white, and specific spot [accent color] for key concepts.
Each panel description should specify:
- Panel position (Top Left / Top Right / Bottom Left / Bottom Right)
- Character poses and gestures (simple, stick-figure style)
- Dialogue text in Chinese (hand-drawn style)
- Any accent-colored elements (concept labels, key objects)
## Quality Markers
- ✓ Exactly 4 panels in strict 2×2 grid
- ✓ 起承转合 narrative arc clearly present
- ✓ 90%+ black-and-white with strategic spot color
- ✓ Simplified stick-figure characters
- ✓ Key concept visually highlighted with accent color
- ✓ Text is minimal and in Chinese (or source language)
- ✓ Single complete story in one page
- ✓ Panel 3 delivers a clear "turn" or insight
## Best For
Business allegory, management fables, short insights, workplace parables, concept contrasts, social media educational content, quick-read comics
+44 -14
View File
@@ -18,6 +18,8 @@ Comic Progress:
- [ ] Step 5: Generate prompts
- [ ] Step 6: Review prompts (conditional)
- [ ] Step 7: Generate images
- [ ] 7.1 Character sheet (if needed)
- [ ] 7.2 Generate pages
- [ ] Step 8: Merge to PDF
- [ ] Step 9: Completion report
```
@@ -410,28 +412,41 @@ options:
With confirmed prompts from Step 5/6:
### 7.1 Generate Character Reference Sheet (first)
### 7.1 Generate Character Reference Sheet (conditional)
Character sheet is recommended for multi-page comics with recurring characters, but **NOT required** for all presets.
**When to generate**:
| Condition | Action |
|-----------|--------|
| Multi-page comic with detailed/recurring characters | Generate character sheet (recommended) |
| Preset with simplified characters (e.g., four-panel minimalist) | Skip — prompt descriptions are sufficient |
| Single-page comic | Skip unless characters are complex |
**When generating**:
1. Use Reference Sheet Prompt from `characters/characters.md`
2. **Backup rule**: If `characters/characters.png` exists, rename to `characters/characters-backup-YYYYMMDD-HHMMSS.png`
3. Generate → `characters/characters.png`
4. This ensures visual consistency for all subsequent pages
4. **Compress** to reduce API payload size when used as `--ref`:
- `sips -s format jpeg -s formatOptions 80 characters.png --out characters-compressed.jpg` (macOS)
- Or: `pngquant --quality=65-80 characters.png -o characters-compressed.png`
### 7.2 Generate Comic Pages
**CRITICAL: Character Reference is MANDATORY** for visual consistency across all pages.
**Before generating any page**:
1. Read the image generation skill's SKILL.md
2. Check if it supports reference image input (`--ref`, `--reference`, etc.)
3. Choose the appropriate strategy below
3. Determine if character sheet exists
4. Choose the appropriate strategy below
**Character Reference Strategy**:
**Page Generation Strategy**:
| Skill Capability | Strategy | Action |
|------------------|----------|--------|
| Supports `--ref` | **Strategy A** | Pass `characters/characters.png` with EVERY page |
| Does NOT support `--ref` | **Strategy B** | Prepend character descriptions to EVERY prompt |
| Character Sheet | Skill Capability | Strategy |
|-----------------|------------------|----------|
| Exists | Supports `--ref` | **A**: Pass character sheet as `--ref` with every page |
| Exists | No `--ref` support | **B**: Embed character descriptions in every prompt |
| Skipped | — | **C**: Prompt file contains all descriptions inline |
**Strategy A: Using `--ref` parameter** (e.g., baoyu-imagine)
@@ -439,8 +454,16 @@ With confirmed prompts from Step 5/6:
- Invoke that installed skill via its documented interface, not by calling its scripts directly
- For every page, use `prompts/01-page-xxx.md` as the prompt-file input
- Save output to `01-page-xxx.png`
- Use aspect ratio `3:4`
- Pass `characters/characters.png` as `--ref` on every page generation
- Use aspect ratio from storyboard (default `3:4`, preset may override)
- Pass `characters/characters.png` (or compressed version) as `--ref`
**`--ref` failure recovery**:
If generation fails when using `--ref`:
1. **Compress/convert** reference image:
- `sips -s format jpeg -s formatOptions 70 characters.png --out characters-compressed.jpg`
- Or reduce resolution: `sips -Z 1024 characters.png --out characters-small.png`
2. **Retry** with compressed/converted image as `--ref`
3. **If still fails**: Fall back to **Strategy C** — generate WITHOUT `--ref`, with character descriptions embedded in prompt text
**Strategy B: Embedding character descriptions in prompt**
@@ -458,10 +481,17 @@ When skill does NOT support reference images, create combined prompt files:
[Original page prompt here]
```
**Strategy C: Prompt-only (no character sheet)**
When character sheet was skipped or `--ref` failed:
- Prompt file already contains all character descriptions inline
- No `--ref` parameter needed
- Rely on detailed text descriptions for character consistency
**For each page (cover + pages)**:
1. Read prompt from `prompts/NN-{cover|page}-[slug].md`
2. **Backup rule**: If image file exists, rename to `NN-{cover|page}-[slug]-backup-YYYYMMDD-HHMMSS.png`
3. Generate image using Strategy A or B (based on skill capability)
3. Generate image using Strategy A, B, or C
4. Save to `NN-{cover|page}-[slug].png`
5. Report progress after each generation: "Generated X/N: [page title]"
@@ -493,7 +523,7 @@ Title: [title] | Art: [art] | Tone: [tone] | Pages: [count] | Aspect: [ratio] |
Watermark: [enabled/disabled]
Location: [path]
✓ analysis.md
✓ characters.png
✓ characters.png (if generated)
✓ 00-cover-[slug].png ... NN-page-[slug].png
✓ {topic-slug}.pdf
```
+4 -4
View File
@@ -1,6 +1,6 @@
---
name: baoyu-cover-image
description: Generates article cover images with 5 dimensions (type, palette, rendering, text, mood) combining 10 color palettes and 7 rendering styles. Supports cinematic (2.35:1), widescreen (16:9), and square (1:1) aspects. Use when user asks to "generate cover image", "create article cover", or "make cover".
description: Generates article cover images with 5 dimensions (type, palette, rendering, text, mood) combining 11 color palettes and 7 rendering styles. Supports cinematic (2.35:1), widescreen (16:9), and square (1:1) aspects. Use when user asks to "generate cover image", "create article cover", or "make cover".
version: 1.56.1
metadata:
openclaw:
@@ -39,7 +39,7 @@ Generate elegant cover images for articles with 5-dimensional customization.
| Option | Description |
|--------|-------------|
| `--type <name>` | hero, conceptual, typography, metaphor, scene, minimal |
| `--palette <name>` | warm, elegant, cool, dark, earth, vivid, pastel, mono, retro, duotone |
| `--palette <name>` | warm, elegant, cool, dark, earth, vivid, pastel, mono, retro, duotone, macaron |
| `--rendering <name>` | flat-vector, hand-drawn, painterly, digital, pixel, chalk, screen-print |
| `--style <name>` | Preset shorthand (see [Style Presets](references/style-presets.md)) |
| `--text <level>` | none, title-only, title-subtitle, text-rich |
@@ -56,7 +56,7 @@ Generate elegant cover images for articles with 5-dimensional customization.
| Dimension | Values | Default |
|-----------|--------|---------|
| **Type** | hero, conceptual, typography, metaphor, scene, minimal | auto |
| **Palette** | warm, elegant, cool, dark, earth, vivid, pastel, mono, retro, duotone | auto |
| **Palette** | warm, elegant, cool, dark, earth, vivid, pastel, mono, retro, duotone, macaron | auto |
| **Rendering** | flat-vector, hand-drawn, painterly, digital, pixel, chalk, screen-print | auto |
| **Text** | none, title-only, title-subtitle, text-rich | title-only |
| **Mood** | subtle, balanced, bold | balanced |
@@ -69,7 +69,7 @@ Auto-selection rules: [references/auto-selection.md](references/auto-selection.m
**Types**: hero, conceptual, typography, metaphor, scene, minimal
→ Details: [references/types.md](references/types.md)
**Palettes**: warm, elegant, cool, dark, earth, vivid, pastel, mono, retro, duotone
**Palettes**: warm, elegant, cool, dark, earth, vivid, pastel, mono, retro, duotone, macaron
→ Details: [references/palettes/](references/palettes/)
**Renderings**: flat-vector, hand-drawn, painterly, digital, pixel, chalk, screen-print
@@ -27,6 +27,7 @@ When a dimension is omitted, select based on content signals.
| Zen, focus, essential, pure, simple | `mono` |
| History, vintage, retro, classic, exploration | `retro` |
| Movie poster, album cover, concert, cinematic, dramatic, two-color | `duotone` |
| Education, tutorial, knowledge, onboarding, concept explainer | `macaron` |
## Auto Rendering Selection
@@ -18,7 +18,7 @@ watermark:
preferred_type: null # hero|conceptual|typography|metaphor|scene|minimal or null for auto-select
preferred_palette: null # warm|elegant|cool|dark|earth|vivid|pastel|mono|retro or null for auto-select
preferred_palette: null # warm|elegant|cool|dark|earth|vivid|pastel|mono|retro|duotone|macaron or null for auto-select
preferred_rendering: null # flat-vector|hand-drawn|painterly|digital|pixel|chalk or null for auto-select
@@ -0,0 +1,26 @@
# macaron
Soft macaron pastel color blocks on warm cream
## Color Palette
| Role | Color | Hex |
|------|-------|-----|
| Primary 1 | Sky Blue | #A8D8EA |
| Primary 2 | Mint Green | #B5E5CF |
| Primary 3 | Lavender | #D5C6E0 |
| Background | Warm Cream | #F5F0E8 |
| Background Alt | Peach | #FFD5C2 |
| Accent 1 | Coral Red | #E8655A |
| Accent 2 | Deep Charcoal | #2D2D2D |
## Decorative Hints
- Rounded pastel color blocks
- Subtle warm paper grain texture
- Soft shadows, no hard edges
- Gentle gradient transitions between zones
## Best For
Educational content, knowledge sharing, concept explainers, tutorials, tech summaries, onboarding materials
@@ -23,6 +23,7 @@
| `vintage` | `retro` | `hand-drawn` |
| `warm` | `warm` | `hand-drawn` |
| `warm-flat` | `warm` | `flat-vector` |
| `hand-drawn-edu` | `macaron` | `hand-drawn` |
| `watercolor` | `earth` | `painterly` |
| `poster-art` | `retro` | `screen-print` |
| `mondo` | `mono` | `screen-print` |
@@ -478,7 +478,7 @@ export function killChrome(chrome: ChildProcess): void {
chrome.kill("SIGTERM");
} catch {}
setTimeout(() => {
if (!chrome.killed) {
if (chrome.exitCode === null && chrome.signalCode === null) {
try {
chrome.kill("SIGKILL");
} catch {}
@@ -486,6 +486,37 @@ export function killChrome(chrome: ChildProcess): void {
}, 2_000).unref?.();
}
export async function gracefulKillChrome(
chrome: ChildProcess,
port?: number,
timeoutMs = 6_000,
): Promise<void> {
if (chrome.exitCode !== null || chrome.signalCode !== null) return;
const exitPromise = new Promise<void>((resolve) => {
chrome.once("exit", () => resolve());
});
killChrome(chrome);
const start = Date.now();
while (Date.now() - start < timeoutMs) {
if (chrome.exitCode !== null || chrome.signalCode !== null) return;
if (port !== undefined && !await isPortListening(port, 250)) return;
const exited = await Promise.race([
exitPromise.then(() => true),
sleep(100).then(() => false),
]);
if (exited) return;
}
await Promise.race([
exitPromise,
sleep(250),
]);
}
export async function openPageSession(options: OpenPageSessionOptions): Promise<PageSession> {
let targetId: string;
let createdTarget = false;
@@ -478,7 +478,7 @@ export function killChrome(chrome: ChildProcess): void {
chrome.kill("SIGTERM");
} catch {}
setTimeout(() => {
if (!chrome.killed) {
if (chrome.exitCode === null && chrome.signalCode === null) {
try {
chrome.kill("SIGKILL");
} catch {}
@@ -486,6 +486,37 @@ export function killChrome(chrome: ChildProcess): void {
}, 2_000).unref?.();
}
export async function gracefulKillChrome(
chrome: ChildProcess,
port?: number,
timeoutMs = 6_000,
): Promise<void> {
if (chrome.exitCode !== null || chrome.signalCode !== null) return;
const exitPromise = new Promise<void>((resolve) => {
chrome.once("exit", () => resolve());
});
killChrome(chrome);
const start = Date.now();
while (Date.now() - start < timeoutMs) {
if (chrome.exitCode !== null || chrome.signalCode !== null) return;
if (port !== undefined && !await isPortListening(port, 250)) return;
const exited = await Promise.race([
exitPromise.then(() => true),
sleep(100).then(() => false),
]);
if (exited) return;
}
await Promise.race([
exitPromise,
sleep(250),
]);
}
export async function openPageSession(options: OpenPageSessionOptions): Promise<PageSession> {
let targetId: string;
let createdTarget = false;
+6 -3
View File
@@ -1,6 +1,6 @@
---
name: baoyu-infographic
description: Generates professional infographics with 21 layout types and 20 visual styles. Analyzes content, recommends layout×style combinations, and generates publication-ready infographics. Use when user asks to create "infographic", "信息图", "visual summary", "可视化", or "高密度信息大图".
description: Generates professional infographics with 21 layout types and 21 visual styles. Analyzes content, recommends layout×style combinations, and generates publication-ready infographics. Use when user asks to create "infographic", "信息图", "visual summary", "可视化", or "高密度信息大图".
version: 1.56.1
metadata:
openclaw:
@@ -26,7 +26,7 @@ Two dimensions: **layout** (information structure) × **style** (visual aestheti
| Option | Values |
|--------|--------|
| `--layout` | 21 options (see Layout Gallery), default: bento-grid |
| `--style` | 20 options (see Style Gallery), default: craft-handmade |
| `--style` | 21 options (see Style Gallery), default: craft-handmade |
| `--aspect` | Named: landscape (16:9), portrait (9:16), square (1:1). Custom: any W:H ratio (e.g., 3:4, 4:3, 2.35:1) |
| `--lang` | en, zh, ja, etc. |
@@ -82,6 +82,7 @@ Full definitions: `references/layouts/<layout>.md`
| `pop-laboratory` | Blueprint grid, coordinate markers, lab precision |
| `morandi-journal` | Hand-drawn doodle, warm Morandi tones |
| `retro-pop-grid` | 1970s retro pop art, Swiss grid, thick outlines |
| `hand-drawn-edu` | Macaron pastels, hand-drawn wobble, stick figures |
Full definitions: `references/styles/<style>.md`
@@ -104,6 +105,8 @@ Full definitions: `references/styles/<style>.md`
| Product Guide | `dense-modules` + `morandi-journal` |
| Technical Guide | `dense-modules` + `pop-laboratory` |
| Trendy Guide | `dense-modules` + `retro-pop-grid` |
| Educational Diagram | `hub-spoke` + `hand-drawn-edu` |
| Process Tutorial | `linear-progression` + `hand-drawn-edu` |
Default: `bento-grid` + `craft-handmade`
@@ -259,7 +262,7 @@ Report: topic, layout, style, aspect, language, output path, files created.
- `references/structured-content-template.md` - Content format
- `references/base-prompt.md` - Prompt template
- `references/layouts/<layout>.md` - 21 layout definitions
- `references/styles/<style>.md` - 20 style definitions
- `references/styles/<style>.md` - 21 style definitions
## Extension Support
@@ -0,0 +1,63 @@
# hand-drawn-edu
Hand-drawn educational infographic with macaron pastel color blocks on warm cream paper texture.
## Color Palette
- Background: Warm cream (#F5F0E8) with subtle paper grain texture
- Primary text: Deep charcoal (#2D2D2D) for headlines, outlines
- Macaron Blue: #A8D8EA for cool-toned information zones
- Macaron Mint: #B5E5CF for growth/positive zones
- Macaron Lavender: #D5C6E0 for abstract/concept zones
- Macaron Peach: #FFD5C2 for warm-toned zones
- Accent: Coral Red (#E8655A) for key data, warnings, emphasis
- Muted annotations: Warm gray (#6B6B6B) for secondary labels
## Visual Elements
- Macaron pastel rounded cards as distinct information zones
- Hand-drawn wavy connection lines and arrows with small text labels
- Simple stick-figure characters and cartoon icons to humanize concepts
- Doodle decorations: small stars, underlines, spirals, sparkles
- Color fills don't completely fill outlines — preserve casual hand-drawn feel
- Dashed borders for secondary or contained zones
- Small icon doodles (clipboard, lock, checkmark, lightbulb) to reinforce concepts
- Bold centered quote or takeaway at the bottom
- Slight hand-drawn wobble on all lines and shapes
## Variants
| Variant | Focus | Visual Emphasis |
|---------|-------|-----------------|
| **Sketch-notes** | Concept mapping | More stick figures, thought bubbles, connecting arrows |
| **Pastel cards** | Structured info | Cleaner macaron blocks, less doodle, more white space |
## Typography
- Main title: Bold hand-drawn lettering with organic strokes, large confident letterforms with slight wobble
- Section headers: Hand-lettered text on or inside macaron color blocks
- Body text: Clear handwritten print style, legible but not mechanical
- Annotations: Warm gray (#6B6B6B), smaller, neat handwritten labels
- Keywords: Bold emphasis within body text
## Style Enforcement
- All lines must have slight hand-drawn wobble — no perfect geometry
- Each information zone uses a distinct macaron color block
- Maintain consistent wobble quality across all shapes and lines
- Include at least one simple cartoon character or stick figure
- Generous white space between zones — each zone should breathe
- Maximum 4 macaron colors per infographic
## Avoid
- Perfect geometric shapes or straight lines
- Photorealistic elements or stock illustration style
- Pure white backgrounds
- Flat vector icons or digital-precision graphics
- Overcrowded layouts — let zones breathe
- Corporate or clinical aesthetic
## Best For
Educational diagrams, process explainers, concept maps, knowledge summaries, tutorial walkthroughs, onboarding visuals
+1 -1
View File
@@ -352,7 +352,7 @@ WECHAT_APP_SECRET=<user_input>
| Field | If Missing |
|-------|------------|
| Title | Prompt: "Enter title, or press Enter to auto-generate from content" |
| Summary | Prompt: "Enter summary, or press Enter to auto-generate (recommended for SEO)" |
| Summary | Use fallback chain: frontmatter `description` → frontmatter `summary` → prompt user or auto-generate |
| Author | Use fallback chain: CLI `--author` → frontmatter `author` → EXTEND.md `default_author` |
**Auto-Generation Logic**:
@@ -478,7 +478,7 @@ export function killChrome(chrome: ChildProcess): void {
chrome.kill("SIGTERM");
} catch {}
setTimeout(() => {
if (!chrome.killed) {
if (chrome.exitCode === null && chrome.signalCode === null) {
try {
chrome.kill("SIGKILL");
} catch {}
@@ -486,6 +486,37 @@ export function killChrome(chrome: ChildProcess): void {
}, 2_000).unref?.();
}
export async function gracefulKillChrome(
chrome: ChildProcess,
port?: number,
timeoutMs = 6_000,
): Promise<void> {
if (chrome.exitCode !== null || chrome.signalCode !== null) return;
const exitPromise = new Promise<void>((resolve) => {
chrome.once("exit", () => resolve());
});
killChrome(chrome);
const start = Date.now();
while (Date.now() - start < timeoutMs) {
if (chrome.exitCode !== null || chrome.signalCode !== null) return;
if (port !== undefined && !await isPortListening(port, 250)) return;
const exited = await Promise.race([
exitPromise.then(() => true),
sleep(100).then(() => false),
]);
if (exited) return;
}
await Promise.race([
exitPromise,
sleep(250),
]);
}
export async function openPageSession(options: OpenPageSessionOptions): Promise<PageSession> {
let targetId: string;
let createdTarget = false;
@@ -7,6 +7,7 @@ import {
type WechatUploadAsset,
prepareWechatBodyImageUpload,
needsWechatBodyImageProcessing,
detectImageFormatFromBuffer,
} from "./wechat-image-processor.ts";
interface AccessTokenResponse {
@@ -138,6 +139,16 @@ async function loadUploadAsset(
contentType = mimeTypes[fileExt] || "image/jpeg";
}
// Detect actual format from magic bytes to fix extension/content-type mismatches
// (e.g. CDNs serving WebP for URLs with .png extension)
const detected = detectImageFormatFromBuffer(fileBuffer);
if (detected && detected.contentType !== contentType) {
console.error(`[wechat-api] Format mismatch: ${filename} declared as ${contentType}, actual ${detected.contentType}`);
contentType = detected.contentType;
fileExt = detected.fileExt;
filename = `${path.basename(filename, path.extname(filename))}${detected.fileExt}`;
}
return {
buffer: fileBuffer,
filename,
@@ -52,6 +52,39 @@ const MIME_TO_EXT: Record<string, string> = {
const JPEG_QUALITY_STEPS = [82, 74, 66, 58, 50, 42, 34];
const MAX_WIDTH_STEPS = [2560, 2048, 1600, 1280, 1024, 800, 640, 480];
/**
* Detect actual image format from buffer magic bytes.
* Returns corrected { contentType, fileExt } or null if unknown.
*/
export function detectImageFormatFromBuffer(buffer: Buffer): { contentType: string; fileExt: string } | null {
if (buffer.length < 12) return null;
// WebP: RIFF....WEBP
if (
buffer[0] === 0x52 && buffer[1] === 0x49 && buffer[2] === 0x46 && buffer[3] === 0x46 &&
buffer[8] === 0x57 && buffer[9] === 0x45 && buffer[10] === 0x42 && buffer[11] === 0x50
) {
return { contentType: "image/webp", fileExt: ".webp" };
}
// PNG: 89 50 4E 47
if (buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4e && buffer[3] === 0x47) {
return { contentType: "image/png", fileExt: ".png" };
}
// JPEG: FF D8 FF
if (buffer[0] === 0xff && buffer[1] === 0xd8 && buffer[2] === 0xff) {
return { contentType: "image/jpeg", fileExt: ".jpg" };
}
// GIF: GIF8
if (buffer[0] === 0x47 && buffer[1] === 0x49 && buffer[2] === 0x46 && buffer[3] === 0x38) {
return { contentType: "image/gif", fileExt: ".gif" };
}
// BMP: BM
if (buffer[0] === 0x42 && buffer[1] === 0x4d) {
return { contentType: "image/bmp", fileExt: ".bmp" };
}
return null;
}
let webpDecoderReady: Promise<void> | undefined;
type JimpImage = Awaited<ReturnType<typeof Jimp.read>>;
@@ -209,7 +242,8 @@ export async function prepareWechatBodyImageUpload(
const image = await loadImageForProcessing(asset);
const widths = buildCandidateWidths(image.bitmap.width);
const preferPng = imageHasTransparency(image) || ensureFileExt(asset) === ".png";
const ext = ensureFileExt(asset);
const preferPng = imageHasTransparency(image) || ext === ".png" || ext === ".webp";
const processingNotes = buildProcessingNotes(asset);
for (const width of widths) {
@@ -478,7 +478,7 @@ export function killChrome(chrome: ChildProcess): void {
chrome.kill("SIGTERM");
} catch {}
setTimeout(() => {
if (!chrome.killed) {
if (chrome.exitCode === null && chrome.signalCode === null) {
try {
chrome.kill("SIGKILL");
} catch {}
@@ -486,6 +486,37 @@ export function killChrome(chrome: ChildProcess): void {
}, 2_000).unref?.();
}
export async function gracefulKillChrome(
chrome: ChildProcess,
port?: number,
timeoutMs = 6_000,
): Promise<void> {
if (chrome.exitCode !== null || chrome.signalCode !== null) return;
const exitPromise = new Promise<void>((resolve) => {
chrome.once("exit", () => resolve());
});
killChrome(chrome);
const start = Date.now();
while (Date.now() - start < timeoutMs) {
if (chrome.exitCode !== null || chrome.signalCode !== null) return;
if (port !== undefined && !await isPortListening(port, 250)) return;
const exited = await Promise.race([
exitPromise.then(() => true),
sleep(100).then(() => false),
]);
if (exited) return;
}
await Promise.race([
exitPromise,
sleep(250),
]);
}
export async function openPageSession(options: OpenPageSessionOptions): Promise<PageSession> {
let targetId: string;
let createdTarget = false;
@@ -478,7 +478,7 @@ export function killChrome(chrome: ChildProcess): void {
chrome.kill("SIGTERM");
} catch {}
setTimeout(() => {
if (!chrome.killed) {
if (chrome.exitCode === null && chrome.signalCode === null) {
try {
chrome.kill("SIGKILL");
} catch {}
@@ -486,6 +486,37 @@ export function killChrome(chrome: ChildProcess): void {
}, 2_000).unref?.();
}
export async function gracefulKillChrome(
chrome: ChildProcess,
port?: number,
timeoutMs = 6_000,
): Promise<void> {
if (chrome.exitCode !== null || chrome.signalCode !== null) return;
const exitPromise = new Promise<void>((resolve) => {
chrome.once("exit", () => resolve());
});
killChrome(chrome);
const start = Date.now();
while (Date.now() - start < timeoutMs) {
if (chrome.exitCode !== null || chrome.signalCode !== null) return;
if (port !== undefined && !await isPortListening(port, 250)) return;
const exited = await Promise.race([
exitPromise.then(() => true),
sleep(100).then(() => false),
]);
if (exited) return;
}
await Promise.race([
exitPromise,
sleep(250),
]);
}
export async function openPageSession(options: OpenPageSessionOptions): Promise<PageSession> {
let targetId: string;
let createdTarget = false;
+5 -1
View File
@@ -71,6 +71,7 @@ Transform content into professional slide deck images.
| `corporate` | clean + professional + geometric + balanced | Investor decks, proposals |
| `minimal` | clean + neutral + geometric + minimal | Executive briefings |
| `sketch-notes` | organic + warm + handwritten + balanced | Educational, tutorials |
| `hand-drawn-edu` | organic + macaron + handwritten + balanced | Educational diagrams, process explainers |
| `watercolor` | organic + warm + humanist + minimal | Lifestyle, wellness |
| `dark-atmospheric` | clean + dark + editorial + balanced | Entertainment, gaming |
| `notion` | clean + neutral + geometric + dense | Product demos, SaaS |
@@ -88,7 +89,7 @@ Transform content into professional slide deck images.
| Dimension | Options | Description |
|-----------|---------|-------------|
| **Texture** | clean, grid, organic, pixel, paper | Visual texture and background treatment |
| **Mood** | professional, warm, cool, vibrant, dark, neutral | Color temperature and palette style |
| **Mood** | professional, warm, cool, vibrant, dark, neutral, macaron | Color temperature and palette style |
| **Typography** | geometric, humanist, handwritten, editorial, technical | Headline and body text styling |
| **Density** | minimal, balanced, dense | Information density per slide |
@@ -99,6 +100,7 @@ Full specs: `references/dimensions/*.md`
| Content Signals | Preset |
|-----------------|--------|
| tutorial, learn, education, guide, beginner | `sketch-notes` |
| hand-drawn, infographic, diagram, process, onboarding | `hand-drawn-edu` |
| classroom, teaching, school, chalkboard | `chalkboard` |
| architecture, system, data, analysis, technical | `blueprint` |
| creative, children, kids, cute | `vector-illustration` |
@@ -393,6 +395,8 @@ options:
description: "Blues, grays, analytical"
- label: "vibrant"
description: "High saturation, bold"
- label: "macaron"
description: "Pastel blocks (blue, mint, lavender, peach) on cream"
```
(Note: "dark", "neutral" available via Other)
@@ -8,6 +8,7 @@ Color temperature and palette style.
|--------|-------------------|---------------|----------|
| `professional` | Cool-neutral | Navy, gold, structured grays | Business, investor, corporate |
| `warm` | Warm | Earth tones, oranges, natural colors | Education, friendly, approachable |
| `macaron` | Warm | Pastel blocks (blue, mint, lavender, peach) on cream | Educational diagrams, knowledge sharing |
| `cool` | Cool | Blues, grays, cyan, teal | Technical, data, analytical |
| `vibrant` | Varied | High saturation, bold colors | Marketing, creative, attention-grabbing |
| `dark` | Dark | Deep backgrounds with bright accents | Entertainment, gaming, atmospheric |
@@ -36,6 +37,19 @@ Accent 2: #E9C46A (Mustard Yellow)
Accent 3: #87A96B (Sage Green)
```
### macaron
```
Background: #F5F0E8 (Warm Cream)
Primary Text: #2D2D2D (Deep Charcoal)
Muted Text: #6B6B6B (Warm Gray)
Macaron Blue: #A8D8EA (Sky Blue)
Macaron Mint: #B5E5CF (Mint Green)
Macaron Lavender: #D5C6E0 (Lavender)
Macaron Peach: #FFD5C2 (Peach)
Accent: #E8655A (Coral Red)
```
### cool
```
@@ -95,6 +109,13 @@ Accent 2: #A1A1AA (Light Gray)
- Soft transitions between colors
- Welcoming atmosphere
### macaron
- Soft pastel color blocks as distinct information zones
- Each zone uses one macaron color (blue, mint, lavender, peach)
- Coral Red accent used sparingly for emphasis
- Warm cream background maintains friendly, approachable feel
### cool
- Blue-dominant palette
@@ -129,6 +150,7 @@ Accent 2: #A1A1AA (Light Gray)
|------|-----------------|------------|
| professional | clean texture, geometric typography | organic texture, handwritten |
| warm | organic texture, humanist typography | pixel texture, minimal density |
| macaron | organic texture, handwritten typography | pixel texture, dark mood |
| cool | grid texture, technical typography | paper texture, handwritten |
| vibrant | pixel/organic texture, editorial typography | neutral mood overlaps |
| dark | clean/pixel texture, technical typography | paper texture |
@@ -11,6 +11,7 @@ Maps 16 preset styles to their dimension combinations.
| corporate | clean | professional | geometric | balanced |
| minimal | clean | neutral | geometric | minimal |
| sketch-notes | organic | warm | handwritten | balanced |
| hand-drawn-edu | organic | macaron | handwritten | balanced |
| watercolor | organic | warm | humanist | minimal |
| dark-atmospheric | clean | dark | editorial | balanced |
| notion | clean | neutral | geometric | dense |
@@ -50,6 +51,11 @@ Maps 16 preset styles to their dimension combinations.
- **Feel**: Friendly learning, approachable education
- **Auto-select**: tutorial, learn, education, guide, beginner
### hand-drawn-edu
- **Dimensions**: organic + macaron + handwritten + balanced
- **Feel**: Hand-drawn educational infographic, macaron pastel zones
- **Auto-select**: hand-drawn, infographic, diagram, process, onboarding
### watercolor
- **Dimensions**: organic + warm + humanist + minimal
- **Feel**: Artistic, natural, lifestyle
@@ -114,7 +120,7 @@ When user selects "Custom dimensions", combine any:
- **Typography** (5): geometric, humanist, handwritten, editorial, technical
- **Density** (3): minimal, balanced, dense
Total possible combinations: 5 × 6 × 5 × 3 = **450 unique styles**
Total possible combinations: 5 × 7 × 5 × 3 = **525 unique styles**
## Recommended Combinations (Beyond Presets)
@@ -55,6 +55,6 @@ Visual texture and background treatment.
|---------|-----------------|------------|
| clean | professional, neutral moods | handwritten typography |
| grid | cool, professional moods | handwritten, vibrant moods |
| organic | warm, vibrant moods | technical typography |
| organic | warm, macaron, vibrant moods | technical typography |
| pixel | vibrant, dark moods | editorial typography |
| paper | warm moods | geometric typography, minimal density |
@@ -0,0 +1,69 @@
# hand-drawn-edu
Hand-drawn educational infographic with macaron pastel color blocks on warm cream paper
## Design Aesthetic
Hand-drawn educational infographic feel with slight wobble on all lines and shapes, like a high-quality presentation visual summary. Warm cream paper background with macaron pastel color blocks creating distinct information zones. Simple cartoon characters and doodle decorations bring concepts to life while maintaining clean composition and generous white space.
## Background
- Color: Warm Cream (#F5F0E8)
- Texture: Subtle warm paper grain, hand-drawn feel with slight organic imperfection
## Typography
### Primary Font (Headlines)
Bold hand-drawn lettering with organic strokes. Large, confident letterforms with slight wobble. Thick marker-style strokes. Render as hand-drawn letters, not typed text.
### Secondary Font (Body)
Clear handwritten style for body text and labels. Warm gray (#6B6B6B) for annotations and small labels. Bold keywords within body text for emphasis. Legible but not mechanical.
## Color Palette
| Role | Color | Hex | Usage |
|------|-------|-----|-------|
| Background | Warm Cream | #F5F0E8 | Primary background |
| Primary Text | Deep Charcoal | #2D2D2D | Headlines, main text, outlines |
| Macaron Blue | Sky Blue | #A8D8EA | Info block fill, cool-toned zones |
| Macaron Mint | Mint Green | #B5E5CF | Info block fill, growth/positive zones |
| Macaron Lavender | Lavender | #D5C6E0 | Info block fill, abstract/concept zones |
| Macaron Peach | Peach | #FFD5C2 | Info block fill, warm-toned zones |
| Accent | Coral Red | #E8655A | Key data, warnings, emphasis |
| Muted Text | Warm Gray | #6B6B6B | Secondary annotations, small labels |
## Visual Elements
- Macaron pastel rounded cards as distinct information zones
- Hand-drawn wavy connection lines and arrows between zones
- Simple stick-figure characters and cartoon icons
- Doodle decorations: small stars, underlines, spirals
- Color fills don't completely fill outlines — preserve hand-drawn casual feel
- Dashed borders for secondary or contained zones
- Small icon doodles (clipboard, lock, checkmark) to reinforce concepts
## Style Rules
### Do
- Use distinct macaron color blocks for each information zone
- Keep hand-drawn wobble consistent across all lines and shapes
- Include simple cartoon characters to humanize concepts
- Add small label annotations on connecting arrows
- Include a bold centered quote or takeaway at the bottom
- Maintain generous white space between zones
### Don't
- Use perfect geometric shapes or straight lines
- Create photorealistic elements
- Mix more than 4 macaron colors per slide
- Use pure white backgrounds
- Add slide numbers, footers, or logos
- Overcrowd — each zone should breathe
## Best For
Educational diagrams, process explainers, concept maps, onboarding visuals, knowledge summaries, tutorial walkthroughs
@@ -399,6 +399,22 @@ export async function runConvertCommand(options: ConvertCommandOptions): Promise
if (restored) logger.info(`Restored ${adapter.name} session cookies from sidecar.`);
}
if (options.waitMode === "interaction" && adapter.checkLogin) {
await context.browser.goto(url.toString(), options.timeoutMs).catch(() => {});
const preLogin = await adapter.checkLogin(context);
if (preLogin.state !== "logged_in") {
didLogin = true;
await waitForInteraction(adapter, context, {
type: "wait_for_interaction",
kind: "login",
provider: preLogin.provider ?? adapter.name,
prompt: `Please sign in to ${adapter.name === "x" ? "X" : adapter.name} in the opened Chrome window. Extraction will continue automatically once login is detected.`,
reason: preLogin.reason ?? `Not logged in to ${adapter.name}`,
requiresVisibleBrowser: true,
}, options);
}
}
if (options.waitMode === "force") {
await context.browser.goto(url.toString(), options.timeoutMs).catch(() => {});
await waitForForceResume(adapter, context, options);
+32 -19
View File
@@ -39,6 +39,10 @@ Break down complex content into eye-catching infographic series for Xiaohongshu
# Direct input with options
/baoyu-xhs-images --style bold --layout comparison
[paste content]
# Non-interactive (for scheduled tasks / automation)
/baoyu-xhs-images posts/ai-future/article.md --yes
/baoyu-xhs-images posts/ai-future/article.md --yes --preset knowledge-card
```
## Options
@@ -48,6 +52,7 @@ Break down complex content into eye-catching infographic series for Xiaohongshu
| `--style <name>` | Visual style (see Style Gallery) |
| `--layout <name>` | Information layout (see Layout Gallery) |
| `--preset <name>` | Style + layout shorthand (see [Style Presets](references/style-presets.md)) |
| `--yes` | Non-interactive mode: skip all confirmations. Uses EXTEND.md preferences if found, otherwise uses defaults (no watermark, auto style/layout). Auto-confirms recommended plan (Path A). Suitable for scheduled tasks and automation. |
## Two Dimensions
@@ -237,11 +242,11 @@ Copy and track progress:
```
XHS Infographic Progress:
- [ ] Step 0: Check preferences (EXTEND.md) ⛔ BLOCKING
- [ ] Step 0: Check preferences (EXTEND.md) ⛔ BLOCKING (--yes: use defaults if not found)
- [ ] Found → load preferences → continue
- [ ] Not found → run first-time setup → MUST complete before Step 1
- [ ] Not found → run first-time setup → MUST complete before Step 1 (--yes: skip setup, use defaults)
- [ ] Step 1: Analyze content → analysis.md
- [ ] Step 2: Smart Confirm ⚠️ REQUIRED
- [ ] Step 2: Smart Confirm ⚠️ REQUIRED (--yes: auto-confirm Path A)
- [ ] Path A: Quick confirm → generate recommended outline
- [ ] Path B: Customize → adjust then generate outline
- [ ] Path C: Detailed → 3 outlines → second confirm → generate outline
@@ -252,26 +257,30 @@ XHS Infographic Progress:
### Flow
```
Input → [Step 0: Preferences] ─┬─ Found → Continue
└─ Not found → First-Time Setup ⛔ BLOCKING
└─ Complete setup → Save EXTEND.md → Continue
┌───────────────────────────────────────────────────────────────────────────┘
Analyze → [Smart Confirm] ─┬─ Quick: confirm recommended → outline.md → Generate → Complete
├─ Customize: adjust options → outline.md → Generate → Complete
└─ Detailed: 3 outlines → [Confirm 2] → outline.md → Generate → Complete
Input → [--yes?] ─┬─ Yes → [Step 0: Load or defaults] → Analyze → Auto-confirm → Generate → Complete
└─ No → [Step 0: Preferences] ─┬─ Found → Continue
└─ Not found → First-Time Setup ⛔ BLOCKING
└─ Complete setup → Save EXTEND.md → Continue
┌─────────────────────────────────────────────────────────────────────────────────────┘
Analyze → [Smart Confirm] ─┬─ Quick: confirm recommended → outline.md → Generate → Complete
├─ Customize: adjust options → outline.md → Generate → Complete
└─ Detailed: 3 outlines → [Confirm 2] → outline.md → Generate → Complete
```
### Step 0: Load Preferences (EXTEND.md) ⛔ BLOCKING
**Purpose**: Load user preferences or run first-time setup.
**CRITICAL**: If EXTEND.md not found, MUST complete first-time setup before ANY other questions or steps. Do NOT proceed to content analysis, do NOT ask about style, do NOT ask about layout — ONLY complete the preferences setup first.
**`--yes` mode**: If EXTEND.md found → load it. If not found → use built-in defaults (no watermark, style/layout auto-select, language from content). Do NOT run first-time setup, do NOT create EXTEND.md, do NOT ask any questions. Proceed directly to Step 1.
**CRITICAL** (interactive mode only): If EXTEND.md not found, MUST complete first-time setup before ANY other questions or steps. Do NOT proceed to content analysis, do NOT ask about style, do NOT ask about layout — ONLY complete the preferences setup first.
Check EXTEND.md existence (priority order):
@@ -340,7 +349,11 @@ Read source content, save it if needed, and perform deep analysis.
### Step 2: Smart Confirm ⚠️
**Purpose**: Present auto-recommended plan, let user confirm or adjust. **Do NOT skip.**
**Purpose**: Present auto-recommended plan, let user confirm or adjust.
**`--yes` mode**: Skip this entire step. Use auto-recommended strategy + style + layout from Step 1 analysis (or `--style`/`--layout`/`--preset` if provided). Generate outline directly using Path A logic → save to `outline.md` → proceed to Step 3. No AskUserQuestion calls.
**Interactive mode**: Do NOT skip.
**Auto-Recommendation Logic**:
1. Use Auto Selection table to match content signals → best strategy + style + layout
@@ -491,7 +504,7 @@ Reference: `references/config/watermark-guide.md`
**Image Generation Skill Selection**:
- Check available image generation skills
- If multiple skills available, ask user preference
- If multiple skills available: ask user preference (interactive) or use first available skill (`--yes` mode)
**Session Management**:
If image generation skill supports `--sessionId`:
@@ -2,7 +2,7 @@ import test from "node:test";
import assert from "node:assert/strict";
import { findTranscript, parseTranscriptJson3, parseWebVtt } from "./transcript.ts";
import { buildTranscriptListFromYtDlp, resolveVideoSource, selectYtDlpTrack } from "./youtube.ts";
import { buildTranscriptListFromYtDlp, fetchTranscriptWithFallback, resolveVideoSource, selectYtDlpTrack } from "./youtube.ts";
test("selectYtDlpTrack prefers json3 over xml and vtt", () => {
const track = selectYtDlpTrack([
@@ -123,3 +123,61 @@ test("resolveVideoSource falls back to yt-dlp only after fallback-eligible error
assert.equal(fallbackCalled, true);
assert.equal(source.transcripts[0].languageCode, "en");
});
test("fetchTranscriptWithFallback retries with yt-dlp when InnerTube transcript payload is empty", async () => {
const warnings: string[] = [];
let fallbackCalled = false;
const result = await fetchTranscriptWithFallback(
"video12345ab",
{
kind: "innertube",
data: { videoDetails: { title: "Primary" } },
transcripts: [{
language: "English",
languageCode: "en",
isGenerated: false,
isTranslatable: false,
baseUrl: "https://www.youtube.com/api/timedtext?v=video12345ab&lang=en&fmt=json3",
translationLanguages: [],
}],
},
{
languages: ["en"],
translate: "",
excludeGenerated: false,
excludeManual: false,
},
async (info) => {
if (info.baseUrl.includes("youtube.com/api/timedtext")) {
return { snippets: [], language: info.language, languageCode: info.languageCode };
}
return {
snippets: [{ text: "Recovered subtitle", start: 0, duration: 2 }],
language: info.language,
languageCode: info.languageCode,
};
},
async () => {
fallbackCalled = true;
return {
kind: "yt-dlp",
info: { title: "Fallback" },
transcripts: [{
language: "English",
languageCode: "en",
isGenerated: false,
isTranslatable: false,
baseUrl: "https://example.com/subtitles.en.json3",
translationLanguages: [],
}],
};
},
(message) => warnings.push(message)
);
assert.equal(fallbackCalled, true);
assert.equal(result.source.kind, "yt-dlp");
assert.equal(result.snippets.length, 1);
assert.equal(result.snippets[0].text, "Recovered subtitle");
assert.match(warnings[0] || "", /Retrying with yt-dlp fallback/);
});
+16 -14
View File
@@ -13,13 +13,13 @@ import {
registerVideoDir,
resolveBaseDir,
} from "./storage.ts";
import { findTranscript, formatListOutput, formatMarkdown, formatSrt, segmentIntoSentences } from "./transcript.ts";
import { formatListOutput, formatMarkdown, formatSrt, segmentIntoSentences } from "./transcript.ts";
import type { Options, Sentence, Snippet, VideoMeta, VideoResult } from "./types.ts";
import {
buildVideoMeta,
buildVideoMetaFromYtDlp,
downloadCoverImage,
fetchTranscriptSnippets,
fetchTranscriptWithFallback,
fetchVideoSource,
getThumbnailUrls,
getYtDlpThumbnailUrls,
@@ -31,10 +31,12 @@ async function fetchAndCache(
baseDir: string,
opts: Options
): Promise<{ meta: VideoMeta; snippets: Snippet[]; sentences: Sentence[]; videoDir: string }> {
const source = await fetchVideoSource(videoId);
const requestedLanguages = source.kind === "yt-dlp" && opts.translate ? [opts.translate] : opts.languages;
const transcript = findTranscript(source.transcripts, requestedLanguages, opts.excludeGenerated, opts.excludeManual);
const result = await fetchTranscriptSnippets(transcript, source.kind === "yt-dlp" ? undefined : opts.translate || undefined);
const initialSource = await fetchVideoSource(videoId);
const { source, transcript, snippets, language, languageCode } = await fetchTranscriptWithFallback(
videoId,
initialSource,
opts
);
const description = source.kind === "yt-dlp"
? source.info.description || ""
: source.data?.videoDetails?.shortDescription || "";
@@ -42,21 +44,21 @@ async function fetchAndCache(
? Number(source.info.duration || 0)
: parseInt(source.data?.videoDetails?.lengthSeconds || "0");
const chapters = parseChapters(description, duration);
const language = {
code: result.languageCode,
name: result.language,
const languageMeta = {
code: languageCode,
name: language,
isGenerated: transcript.isGenerated,
};
const meta = source.kind === "yt-dlp"
? buildVideoMetaFromYtDlp(source.info, videoId, language, chapters)
: buildVideoMeta(source.data, videoId, language, chapters);
? buildVideoMetaFromYtDlp(source.info, videoId, languageMeta, chapters)
: buildVideoMeta(source.data, videoId, languageMeta, chapters);
const videoDir = registerVideoDir(videoId, slugify(meta.channel), slugify(meta.title), baseDir);
ensureDir(join(videoDir, "meta.json"));
writeFileSync(join(videoDir, "transcript-raw.json"), JSON.stringify(result.snippets, null, 2));
writeFileSync(join(videoDir, "transcript-raw.json"), JSON.stringify(snippets, null, 2));
const sentences = segmentIntoSentences(result.snippets);
const sentences = segmentIntoSentences(snippets);
writeFileSync(join(videoDir, "transcript-sentences.json"), JSON.stringify(sentences, null, 2));
const imagePath = join(videoDir, "imgs", "cover.jpg");
@@ -69,7 +71,7 @@ async function fetchAndCache(
writeFileSync(join(videoDir, "meta.json"), JSON.stringify(meta, null, 2));
return { meta, snippets: result.snippets, sentences, videoDir };
return { meta, snippets, sentences, videoDir };
}
async function processVideo(videoId: string, opts: Options): Promise<VideoResult> {
@@ -2,12 +2,13 @@ import { spawnSync } from "child_process";
import { writeFileSync } from "fs";
import { makeError, normalizeError, normalizePublishDate, shouldTryAlternateClient, shouldTryYtDlpFallback } from "./shared.ts";
import { parseTranscriptPayload } from "./transcript.ts";
import { findTranscript, parseTranscriptPayload } from "./transcript.ts";
import type {
Chapter,
InnerTubeClient,
InnerTubeSession,
LanguageMeta,
Options,
Snippet,
TranscriptInfo,
VideoMeta,
@@ -219,6 +220,68 @@ export async function fetchTranscriptSnippets(
};
}
function buildYtDlpVideoSource(videoId: string, info: YtDlpInfo): VideoSource {
const transcripts = buildTranscriptListFromYtDlp(info);
if (!transcripts.length) throw makeError(`Transcripts disabled for ${videoId}`, "TRANSCRIPTS_DISABLED");
return { kind: "yt-dlp", info, transcripts };
}
function getRequestedLanguages(
source: VideoSource,
opts: Pick<Options, "languages" | "translate">
): string[] {
return source.kind === "yt-dlp" && opts.translate ? [opts.translate] : opts.languages;
}
export async function fetchTranscriptWithFallback(
videoId: string,
source: VideoSource,
opts: Pick<Options, "languages" | "translate" | "excludeGenerated" | "excludeManual">,
fetchSnippets: (
info: TranscriptInfo,
translateTo?: string
) => Promise<{ snippets: Snippet[]; language: string; languageCode: string }> = fetchTranscriptSnippets,
fetchFallbackSource: (videoId: string) => Promise<VideoSource> | VideoSource = (requestedVideoId) =>
buildYtDlpVideoSource(requestedVideoId, fetchYtDlpInfo(requestedVideoId)),
logWarning: (message: string) => void = (message) => console.error(message)
): Promise<{
source: VideoSource;
transcript: TranscriptInfo;
snippets: Snippet[];
language: string;
languageCode: string;
}> {
const transcript = findTranscript(
source.transcripts,
getRequestedLanguages(source, opts),
opts.excludeGenerated,
opts.excludeManual
);
const result = await fetchSnippets(transcript, source.kind === "yt-dlp" ? undefined : opts.translate || undefined);
if (result.snippets.length > 0) return { source, transcript, ...result };
if (source.kind === "yt-dlp") {
throw makeError(`Transcript fetch returned empty snippets for ${videoId}`, "EMPTY_TRANSCRIPT");
}
logWarning(`Warning (${videoId}): Transcript fetch returned empty snippets. Retrying with yt-dlp fallback.`);
const fallbackSource = await fetchFallbackSource(videoId);
const fallbackTranscript = findTranscript(
fallbackSource.transcripts,
getRequestedLanguages(fallbackSource, opts),
opts.excludeGenerated,
opts.excludeManual
);
const fallbackResult = await fetchSnippets(
fallbackTranscript,
fallbackSource.kind === "yt-dlp" ? undefined : opts.translate || undefined
);
if (!fallbackResult.snippets.length) {
throw makeError(`Transcript fetch returned empty snippets for ${videoId} after yt-dlp fallback`, "EMPTY_TRANSCRIPT");
}
return { source: fallbackSource, transcript: fallbackTranscript, ...fallbackResult };
}
export function detectYtDlpCommand(): { command: string; args: string[]; label: string } | null {
if (cachedYtDlpCommand !== undefined) return cachedYtDlpCommand;
const candidates = [
@@ -366,10 +429,7 @@ export async function resolveVideoSource(
const normalized = normalizeError(error);
if (!shouldTryYtDlpFallback(normalized)) throw normalized;
logWarning(`Warning (${videoId}): ${normalized.message}. Retrying with yt-dlp fallback.`);
const info = fetchFallback(videoId);
const transcripts = buildTranscriptListFromYtDlp(info);
if (!transcripts.length) throw makeError(`Transcripts disabled for ${videoId}`, "TRANSCRIPTS_DISABLED");
return { kind: "yt-dlp", info, transcripts };
return buildYtDlpVideoSource(videoId, fetchFallback(videoId));
}
}