mirror of
https://github.com/JimLiu/baoyu-skills.git
synced 2026-07-14 14:49:48 +08:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 94c9309aa6 | |||
| eb92bdb9df | |||
| e07d33fed0 | |||
| e964feb5e5 | |||
| 7669556736 | |||
| 97da7ab4eb |
@@ -6,7 +6,7 @@
|
||||
},
|
||||
"metadata": {
|
||||
"description": "Skills shared by Baoyu for improving daily work efficiency",
|
||||
"version": "1.12.0"
|
||||
"version": "1.15.1"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
@@ -42,7 +42,8 @@
|
||||
"strict": false,
|
||||
"skills": [
|
||||
"./skills/baoyu-danger-x-to-markdown",
|
||||
"./skills/baoyu-compress-image"
|
||||
"./skills/baoyu-compress-image",
|
||||
"./skills/baoyu-url-to-markdown"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -6,6 +6,7 @@ yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
@@ -145,3 +146,6 @@ tests-data/
|
||||
.baoyu-skills/
|
||||
x-to-markdown/
|
||||
xhs-images/
|
||||
url-to-markdown/
|
||||
cover-image/
|
||||
slide-deck/
|
||||
|
||||
@@ -2,6 +2,35 @@
|
||||
|
||||
English | [中文](./CHANGELOG.zh.md)
|
||||
|
||||
## 1.15.1 - 2026-01-22
|
||||
|
||||
### Refactor
|
||||
- `baoyu-xhs-images`: restructures reference documents into modular architecture—reorganizes scattered files into `config/` (settings), `elements/` (visual building blocks), `presets/` (style definitions), and `workflows/` (process guides) directories for improved maintainability.
|
||||
|
||||
## 1.15.0 - 2026-01-22
|
||||
|
||||
### Features
|
||||
- `baoyu-xhs-images`: adds user preferences support via EXTEND.md—configure watermark (content, position, opacity), preferred style, preferred layout, and custom styles. New Step 0 checks for preferences at project (`.baoyu-skills/`) or user (`~/.baoyu-skills/`) level with first-time setup flow.
|
||||
|
||||
### Documentation
|
||||
- `baoyu-xhs-images`: adds three reference documents—`preferences-schema.md` (YAML schema), `watermark-guide.md` (position and opacity guide), `first-time-setup.md` (setup flow).
|
||||
|
||||
## 1.14.0 - 2026-01-22
|
||||
|
||||
### Fixes
|
||||
- `baoyu-post-to-x`: improves video ready detection for more reliable video posting.
|
||||
|
||||
### Documentation
|
||||
- `baoyu-slide-deck`: comprehensive SKILL.md enhancement—adds slide count guidance (recommended 8-25, max 30), audience guidelines table with audience-specific principles, style selection principles with content-type recommendations, layout selection tips with common mistakes to avoid, visual hierarchy principles, content density guidelines (McKinsey-style high-density principles), color selection guide, typography principles with font recommendations (English and Chinese fonts with multilingual pairing), and visual elements reference (backgrounds, typography treatments, geometric accents).
|
||||
|
||||
## 1.13.0 - 2026-01-21
|
||||
|
||||
### Features
|
||||
- `baoyu-url-to-markdown`: new utility skill for fetching any URL via Chrome CDP and converting to clean markdown. Supports two capture modes—auto (immediate capture on page load) and wait (user-controlled capture for login-required pages).
|
||||
|
||||
### Improvements
|
||||
- `baoyu-xhs-images`: updates style recommendations—replaces `tech` references with `notion` and `chalkboard` for technical and educational content.
|
||||
|
||||
## 1.12.0 - 2026-01-21
|
||||
|
||||
### Refactor
|
||||
|
||||
@@ -2,6 +2,35 @@
|
||||
|
||||
[English](./CHANGELOG.md) | 中文
|
||||
|
||||
## 1.15.1 - 2026-01-22
|
||||
|
||||
### 重构
|
||||
- `baoyu-xhs-images`:参考文档模块化重构——将分散的文件整理为 `config/`(配置设置)、`elements/`(视觉构建块)、`presets/`(风格预设)、`workflows/`(流程指南)四个目录,提升可维护性。
|
||||
|
||||
## 1.15.0 - 2026-01-22
|
||||
|
||||
### 新功能
|
||||
- `baoyu-xhs-images`:新增用户偏好设置支持(通过 EXTEND.md 配置)——可设置水印(内容、位置、透明度)、首选风格、首选布局和自定义风格。新增 Step 0 检查项目级(`.baoyu-skills/`)或用户级(`~/.baoyu-skills/`)偏好设置,首次使用时引导设置。
|
||||
|
||||
### 文档
|
||||
- `baoyu-xhs-images`:新增三个参考文档——`preferences-schema.md`(YAML 配置模式)、`watermark-guide.md`(水印位置和透明度指南)、`first-time-setup.md`(首次设置流程)。
|
||||
|
||||
## 1.14.0 - 2026-01-22
|
||||
|
||||
### 修复
|
||||
- `baoyu-post-to-x`:改进视频就绪检测,提升视频发布稳定性。
|
||||
|
||||
### 文档
|
||||
- `baoyu-slide-deck`:SKILL.md 全面增强——新增幻灯片数量指南(推荐 8-25 张,最多 30 张)、受众指南表格及各受众特定原则、风格选择原则与内容类型推荐、布局选择技巧与常见错误提示、视觉层次原则、内容密度指南(麦肯锡风格高密度原则)、配色选择指南、字体排版原则与字体推荐(中英文字体及多语言搭配方案)、视觉元素参考(背景处理、字体处理、几何装饰)。
|
||||
|
||||
## 1.13.0 - 2026-01-21
|
||||
|
||||
### 新功能
|
||||
- `baoyu-url-to-markdown`:新增 URL 转 Markdown 工具技能,通过 Chrome CDP 抓取任意网页并转换为干净的 Markdown 格式。支持两种抓取模式——自动模式(页面加载后立即抓取)和等待模式(用户控制抓取时机,适用于需要登录的页面)。
|
||||
|
||||
### 改进
|
||||
- `baoyu-xhs-images`:更新风格推荐——将 `tech` 风格引用替换为 `notion` 和 `chalkboard`,用于技术和教育内容。
|
||||
|
||||
## 1.12.0 - 2026-01-21
|
||||
|
||||
### 重构
|
||||
|
||||
@@ -55,7 +55,7 @@ Simply tell Claude Code:
|
||||
|--------|-------------|--------|
|
||||
| **content-skills** | Content generation and publishing | [xhs-images](#baoyu-xhs-images), [infographic](#baoyu-infographic), [cover-image](#baoyu-cover-image), [slide-deck](#baoyu-slide-deck), [comic](#baoyu-comic), [article-illustrator](#baoyu-article-illustrator), [post-to-x](#baoyu-post-to-x), [post-to-wechat](#baoyu-post-to-wechat) |
|
||||
| **ai-generation-skills** | AI-powered generation backends | [image-gen](#baoyu-image-gen), [danger-gemini-web](#baoyu-danger-gemini-web) |
|
||||
| **utility-skills** | Utility tools for content processing | [danger-x-to-markdown](#baoyu-danger-x-to-markdown), [compress-image](#baoyu-compress-image) |
|
||||
| **utility-skills** | Utility tools for content processing | [url-to-markdown](#baoyu-url-to-markdown), [danger-x-to-markdown](#baoyu-danger-x-to-markdown), [compress-image](#baoyu-compress-image) |
|
||||
|
||||
## Update Skills
|
||||
|
||||
@@ -586,6 +586,35 @@ Interacts with Gemini Web to generate text and images.
|
||||
|
||||
Utility tools for content processing.
|
||||
|
||||
#### baoyu-url-to-markdown
|
||||
|
||||
Fetch any URL via Chrome CDP and convert to clean markdown. Supports two capture modes for different scenarios.
|
||||
|
||||
```bash
|
||||
# Auto mode (default) - capture when page loads
|
||||
/baoyu-url-to-markdown https://example.com/article
|
||||
|
||||
# Wait mode - for login-required pages
|
||||
/baoyu-url-to-markdown https://example.com/private --wait
|
||||
|
||||
# Save to specific file
|
||||
/baoyu-url-to-markdown https://example.com/article -o output.md
|
||||
```
|
||||
|
||||
**Capture Modes**:
|
||||
| Mode | Description | Best For |
|
||||
|------|-------------|----------|
|
||||
| Auto (default) | Captures immediately after page load | Public pages, static content |
|
||||
| Wait (`--wait`) | Waits for user signal before capture | Login-required, dynamic content |
|
||||
|
||||
**Options**:
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `<url>` | URL to fetch |
|
||||
| `-o <path>` | Output file path |
|
||||
| `--wait` | Wait for user signal before capturing |
|
||||
| `--timeout <ms>` | Page load timeout (default: 30000) |
|
||||
|
||||
#### baoyu-danger-x-to-markdown
|
||||
|
||||
Converts X (Twitter) content to markdown format. Supports tweet threads and X Articles.
|
||||
|
||||
+30
-1
@@ -55,7 +55,7 @@ npx skills add jimliu/baoyu-skills
|
||||
|------|------|----------|
|
||||
| **content-skills** | 内容生成和发布 | [xhs-images](#baoyu-xhs-images), [infographic](#baoyu-infographic), [cover-image](#baoyu-cover-image), [slide-deck](#baoyu-slide-deck), [comic](#baoyu-comic), [article-illustrator](#baoyu-article-illustrator), [post-to-x](#baoyu-post-to-x), [post-to-wechat](#baoyu-post-to-wechat) |
|
||||
| **ai-generation-skills** | AI 生成后端 | [image-gen](#baoyu-image-gen), [danger-gemini-web](#baoyu-danger-gemini-web) |
|
||||
| **utility-skills** | 内容处理工具 | [danger-x-to-markdown](#baoyu-danger-x-to-markdown), [compress-image](#baoyu-compress-image) |
|
||||
| **utility-skills** | 内容处理工具 | [url-to-markdown](#baoyu-url-to-markdown), [danger-x-to-markdown](#baoyu-danger-x-to-markdown), [compress-image](#baoyu-compress-image) |
|
||||
|
||||
## 更新技能
|
||||
|
||||
@@ -586,6 +586,35 @@ AI 驱动的生成后端。
|
||||
|
||||
内容处理工具。
|
||||
|
||||
#### baoyu-url-to-markdown
|
||||
|
||||
通过 Chrome CDP 抓取任意 URL 并转换为干净的 Markdown。支持两种抓取模式,适应不同场景。
|
||||
|
||||
```bash
|
||||
# 自动模式(默认)- 页面加载后立即抓取
|
||||
/baoyu-url-to-markdown https://example.com/article
|
||||
|
||||
# 等待模式 - 适用于需要登录的页面
|
||||
/baoyu-url-to-markdown https://example.com/private --wait
|
||||
|
||||
# 保存到指定文件
|
||||
/baoyu-url-to-markdown https://example.com/article -o output.md
|
||||
```
|
||||
|
||||
**抓取模式**:
|
||||
| 模式 | 说明 | 适用场景 |
|
||||
|------|------|----------|
|
||||
| 自动(默认) | 页面加载后立即抓取 | 公开页面、静态内容 |
|
||||
| 等待(`--wait`) | 等待用户信号后抓取 | 需登录页面、动态内容 |
|
||||
|
||||
**选项**:
|
||||
| 选项 | 说明 |
|
||||
|------|------|
|
||||
| `<url>` | 要抓取的 URL |
|
||||
| `-o <path>` | 输出文件路径 |
|
||||
| `--wait` | 等待用户信号后抓取 |
|
||||
| `--timeout <ms>` | 页面加载超时(默认:30000) |
|
||||
|
||||
#### baoyu-danger-x-to-markdown
|
||||
|
||||
将 X (Twitter) 内容转换为 markdown 格式。支持推文串和 X 文章。
|
||||
|
||||
@@ -112,24 +112,44 @@ export async function postVideoToX(options: XVideoOptions): Promise<void> {
|
||||
nodeId,
|
||||
files: [absVideoPath],
|
||||
}, { sessionId });
|
||||
console.log('[x-video] Video file set, waiting for processing...');
|
||||
console.log('[x-video] Video file set, uploading in background...');
|
||||
|
||||
// Wait for video to process
|
||||
// Wait a moment for upload to start, then type text while video processes
|
||||
await sleep(2000);
|
||||
|
||||
// Type text while video uploads in background
|
||||
if (text) {
|
||||
console.log('[x-video] Typing text...');
|
||||
await cdp.send('Runtime.evaluate', {
|
||||
expression: `
|
||||
const editor = document.querySelector('[data-testid="tweetTextarea_0"]');
|
||||
if (editor) {
|
||||
editor.focus();
|
||||
document.execCommand('insertText', false, ${JSON.stringify(text)});
|
||||
}
|
||||
`,
|
||||
}, { sessionId });
|
||||
await sleep(500);
|
||||
}
|
||||
|
||||
// Wait for video to finish processing by checking if tweet button is enabled
|
||||
console.log('[x-video] Waiting for video processing...');
|
||||
const waitForVideoReady = async (maxWaitMs = 180_000): Promise<boolean> => {
|
||||
const start = Date.now();
|
||||
let dots = 0;
|
||||
while (Date.now() - start < maxWaitMs) {
|
||||
const result = await cdp!.send<{ result: { value: { hasMedia: boolean; isProcessing: boolean } } }>('Runtime.evaluate', {
|
||||
const result = await cdp!.send<{ result: { value: { hasMedia: boolean; buttonEnabled: boolean } } }>('Runtime.evaluate', {
|
||||
expression: `(() => {
|
||||
const hasMedia = !!document.querySelector('[data-testid="attachments"] video, [data-testid="videoPlayer"], video');
|
||||
const isProcessing = !!document.querySelector('[role="progressbar"], [data-testid="progressBar"]');
|
||||
return { hasMedia, isProcessing };
|
||||
const tweetBtn = document.querySelector('[data-testid="tweetButton"]');
|
||||
const buttonEnabled = tweetBtn && !tweetBtn.disabled && tweetBtn.getAttribute('aria-disabled') !== 'true';
|
||||
return { hasMedia, buttonEnabled };
|
||||
})()`,
|
||||
returnByValue: true,
|
||||
}, { sessionId });
|
||||
|
||||
const { hasMedia, isProcessing } = result.result.value;
|
||||
if (hasMedia && !isProcessing) {
|
||||
const { hasMedia, buttonEnabled } = result.result.value;
|
||||
if (hasMedia && buttonEnabled) {
|
||||
console.log('');
|
||||
return true;
|
||||
}
|
||||
@@ -150,21 +170,6 @@ export async function postVideoToX(options: XVideoOptions): Promise<void> {
|
||||
console.log('[x-video] Video may still be processing. Please check browser window.');
|
||||
}
|
||||
|
||||
// Type text AFTER video is uploaded
|
||||
if (text) {
|
||||
console.log('[x-video] Typing text...');
|
||||
await cdp.send('Runtime.evaluate', {
|
||||
expression: `
|
||||
const editor = document.querySelector('[data-testid="tweetTextarea_0"]');
|
||||
if (editor) {
|
||||
editor.focus();
|
||||
document.execCommand('insertText', false, ${JSON.stringify(text)});
|
||||
}
|
||||
`,
|
||||
}, { sessionId });
|
||||
await sleep(500);
|
||||
}
|
||||
|
||||
if (submit) {
|
||||
console.log('[x-video] Submitting post...');
|
||||
await cdp.send('Runtime.evaluate', {
|
||||
|
||||
@@ -41,11 +41,74 @@ Transform content into professional slide deck images with flexible style option
|
||||
| `--style <name>` | Visual style (see Style Gallery) |
|
||||
| `--audience <type>` | Target audience: beginners, intermediate, experts, executives, general |
|
||||
| `--lang <code>` | Output language (en, zh, ja, etc.) |
|
||||
| `--slides <number>` | Target slide count |
|
||||
| `--slides <number>` | Target slide count (recommended: 8-25, max: 30) |
|
||||
| `--outline-only` | Generate outline only, skip image generation |
|
||||
|
||||
**Slide Count Guidance**:
|
||||
| Content Length | Recommended Slides |
|
||||
|----------------|-------------------|
|
||||
| Short (< 1000 words) | 5-10 |
|
||||
| Medium (1000-3000 words) | 10-18 |
|
||||
| Long (3000-5000 words) | 15-25 |
|
||||
| Very Long (> 5000 words) | 20-30 (consider splitting) |
|
||||
|
||||
Maximum 30 slides per deck. For longer content, split into multiple decks.
|
||||
|
||||
## Audience Guidelines
|
||||
|
||||
Design decisions should adapt to target audience. Use `--audience` to set.
|
||||
|
||||
| Audience | Content Density | Visual Style | Terminology | Slides |
|
||||
|----------|-----------------|--------------|-------------|--------|
|
||||
| `beginners` | Low | Friendly, illustrative | Plain language | 8-15 |
|
||||
| `intermediate` | Medium | Balanced, structured | Some jargon OK | 10-20 |
|
||||
| `experts` | High | Data-rich, precise | Technical terms | 12-25 |
|
||||
| `executives` | Medium-High | Clean, impactful | Business language | 8-12 |
|
||||
| `general` | Medium | Accessible, engaging | Minimal jargon | 10-18 |
|
||||
|
||||
### Audience-Specific Principles
|
||||
|
||||
**Beginners**:
|
||||
- One concept per slide
|
||||
- Visual metaphors over abstract diagrams
|
||||
- Step-by-step progression
|
||||
- Generous whitespace
|
||||
|
||||
**Experts**:
|
||||
- Multiple data points per slide acceptable
|
||||
- Technical diagrams with precise labels
|
||||
- Assume domain knowledge
|
||||
- Dense but organized information
|
||||
|
||||
**Executives**:
|
||||
- Lead with insights, not data
|
||||
- "So what?" on every slide
|
||||
- Decision-enabling content
|
||||
- Bottom-line upfront (BLUF)
|
||||
|
||||
## Style Gallery
|
||||
|
||||
### Style Selection Principles
|
||||
|
||||
**Content-First Approach**:
|
||||
1. Analyze content topic, mood, and industry before selecting
|
||||
2. Consider target audience expectations
|
||||
3. Match style to subject matter (not personal preference)
|
||||
|
||||
**Quick Reference by Content Type**:
|
||||
| Content Type | Recommended Styles |
|
||||
|--------------|-------------------|
|
||||
| Technical/Architecture | `blueprint`, `intuition-machine` |
|
||||
| Educational/Tutorials | `sketch-notes`, `chalkboard` |
|
||||
| Corporate/Business | `corporate`, `minimal` |
|
||||
| Creative/Artistic | `vector-illustration`, `watercolor` |
|
||||
| Product/SaaS | `notion`, `bold-editorial` |
|
||||
| Scientific/Research | `scientific`, `editorial-infographic` |
|
||||
|
||||
**Note**: Full style specifications in `references/styles/<style>.md`
|
||||
|
||||
### Available Styles
|
||||
|
||||
| Style | Description | Best For |
|
||||
|-------|-------------|----------|
|
||||
| `blueprint` (Default) | Technical schematics, grid texture | Architecture, system design |
|
||||
@@ -127,6 +190,32 @@ Optional layout hints for individual slides. Specify in outline's `// LAYOUT` se
|
||||
|
||||
**Usage**: Add `Layout: <name>` in slide's `// LAYOUT` section to guide visual composition.
|
||||
|
||||
### Layout Selection Tips
|
||||
|
||||
**Match Layout to Content**:
|
||||
| Content Type | Recommended Layouts |
|
||||
|--------------|-------------------|
|
||||
| Single narrative | `bullet-list`, `image-caption` |
|
||||
| Two concepts | `split-screen`, `binary-comparison` |
|
||||
| Three items | `three-columns`, `icon-grid` |
|
||||
| Process/Steps | `linear-progression`, `winding-roadmap` |
|
||||
| Data/Metrics | `dashboard`, `key-stat` |
|
||||
| Relationships | `hub-spoke`, `venn-diagram` |
|
||||
| Hierarchy | `hierarchical-layers`, `tree-branching` |
|
||||
|
||||
**Layout Flow Patterns**:
|
||||
| Position | Recommended Layouts |
|
||||
|----------|-------------------|
|
||||
| Opening | `title-hero`, `agenda` |
|
||||
| Middle | Content-specific layouts |
|
||||
| Closing | `quote-callout`, `key-stat` |
|
||||
|
||||
**Common Mistakes to Avoid**:
|
||||
- ✗ Using 3-column layout for 2 items (leaves columns empty)
|
||||
- ✗ Stacking charts/tables below text (use side-by-side instead)
|
||||
- ✗ Image layouts without actual images
|
||||
- ✗ Quote layouts for emphasis (use only for real quotes with attribution)
|
||||
|
||||
## Design Philosophy
|
||||
|
||||
This deck is designed for **reading and sharing**, not live presentation:
|
||||
@@ -135,6 +224,142 @@ This deck is designed for **reading and sharing**, not live presentation:
|
||||
- Include **all necessary context** within each slide
|
||||
- Optimize for **social media sharing** and offline reading
|
||||
|
||||
### Visual Hierarchy Principles
|
||||
|
||||
| Principle | Description |
|
||||
|-----------|-------------|
|
||||
| Focal Point | ONE dominant element per slide draws attention first |
|
||||
| Rule of Thirds | Position key elements at grid intersections |
|
||||
| Z-Pattern | Guide eye: top-left → top-right → bottom-left → bottom-right |
|
||||
| Size Contrast | Headlines 2-3x larger than body text |
|
||||
| Breathing Room | Minimum 10% margin from all edges |
|
||||
|
||||
### Content Density
|
||||
|
||||
Professional presentations balance information density with clarity.
|
||||
|
||||
| Level | Description | Use When |
|
||||
|-------|-------------|----------|
|
||||
| High | Multiple data points, detailed charts, dense text | Expert audience, technical reviews, data-driven decisions |
|
||||
| Medium | Key points with supporting details, moderate visuals | General business, mixed audiences |
|
||||
| Low | One main idea, large visuals, minimal text | Beginners, keynotes, emotional impact |
|
||||
|
||||
**High-Density Principles** (McKinsey-style):
|
||||
- Every element earns its space
|
||||
- Data speaks louder than decoration
|
||||
- Annotations explain insights, not describe data
|
||||
- White space is strategic, not filler
|
||||
- Information hierarchy guides the eye
|
||||
|
||||
**Density by Slide Type**:
|
||||
| Slide Type | Recommended Density |
|
||||
|------------|-------------------|
|
||||
| Cover/Title | Low |
|
||||
| Agenda/Overview | Medium |
|
||||
| Content/Analysis | Medium-High |
|
||||
| Data/Metrics | High |
|
||||
| Quote/Impact | Low |
|
||||
| Summary/Takeaway | Medium |
|
||||
|
||||
### Color Selection
|
||||
|
||||
**Content-First Approach**:
|
||||
1. Analyze content topic, mood, and industry
|
||||
2. Consider target audience expectations
|
||||
3. Match palette to subject matter (not defaults)
|
||||
4. Ensure strong contrast for readability
|
||||
|
||||
**Quick Palette Guide**:
|
||||
| Content Type | Recommended Palettes |
|
||||
|--------------|---------------------|
|
||||
| Technical/Architecture | Blues, grays, blueprint tones |
|
||||
| Educational/Friendly | Warm colors, earth tones |
|
||||
| Corporate/Professional | Navy, gold, structured palettes |
|
||||
| Creative/Artistic | Bold colors, unexpected combinations |
|
||||
| Scientific/Medical | Clean whites, precise color coding |
|
||||
|
||||
**Note**: Full color specs in `references/styles/<style>.md`
|
||||
|
||||
### Typography Principles
|
||||
|
||||
| Element | Treatment |
|
||||
|---------|-----------|
|
||||
| Headlines | Bold, 2-3x body size, narrative style |
|
||||
| Body Text | Regular weight, readable size |
|
||||
| Captions | Smaller, lighter weight |
|
||||
| Data Labels | Monospace for technical content |
|
||||
| Emphasis | Use bold or color, not underlines |
|
||||
|
||||
### Font Recommendations
|
||||
|
||||
Fonts for AI-generated slides. Specify in prompts for consistent rendering.
|
||||
|
||||
**English Fonts**:
|
||||
| Font | Style | Best For |
|
||||
|------|-------|----------|
|
||||
| Liter | Sans-serif, geometric | Modern, clean, technical |
|
||||
| HedvigLettersSans | Sans-serif, distinctive | Brand-forward, creative |
|
||||
| Oranienbaum | High-contrast serif | Elegant, classical |
|
||||
| SortsMillGoudy | Classical serif | Traditional, readable |
|
||||
| Coda | Round sans-serif | Friendly, approachable |
|
||||
|
||||
**Chinese Fonts**:
|
||||
| Font | Style | Best For |
|
||||
|------|-------|----------|
|
||||
| MiSans | Modern sans-serif | Clean, versatile, screen-optimized |
|
||||
| Noto Sans SC | Neutral sans-serif | Standard, multilingual |
|
||||
| siyuanSongti | Refined Song typeface | Elegant, editorial |
|
||||
| alimamashuheiti | Geometric sans-serif | Commercial, structured |
|
||||
| LXGW Bright | Song-Kai hybrid | Warm, readable |
|
||||
|
||||
**Multilingual Pairing**:
|
||||
| Use Case | English | Chinese |
|
||||
|----------|---------|---------|
|
||||
| Technical | Liter | MiSans |
|
||||
| Editorial | Oranienbaum | siyuanSongti |
|
||||
| Friendly | Coda | LXGW Bright |
|
||||
| Corporate | HedvigLettersSans | alimamashuheiti |
|
||||
|
||||
### Consistency Requirements
|
||||
|
||||
| Element | Guideline |
|
||||
|---------|-----------|
|
||||
| Spacing | Consistent margins and padding throughout |
|
||||
| Colors | Maximum 3-4 colors per slide, palette consistent across deck |
|
||||
| Typography | Same font families and sizes for same content types |
|
||||
| Visual Language | Repeat patterns, shapes, and treatments |
|
||||
|
||||
## Visual Elements Reference
|
||||
|
||||
Quick reference for visual treatments. Full specs in style definitions.
|
||||
|
||||
### Background Treatments
|
||||
|
||||
| Treatment | Description | Best For |
|
||||
|-----------|-------------|----------|
|
||||
| Solid color | Single background color | Clean, minimal |
|
||||
| Split background | Two colors, diagonal or vertical | Contrast, sections |
|
||||
| Gradient | Subtle vertical or diagonal fade | Modern, dynamic |
|
||||
| Textured | Pattern or texture overlay | Character, style |
|
||||
|
||||
### Typography Treatments
|
||||
|
||||
| Treatment | Description | Best For |
|
||||
|-----------|-------------|----------|
|
||||
| Size contrast | 3-4x difference headline vs body | Impact, hierarchy |
|
||||
| All-caps headers | Uppercase with letter spacing | Authority, structure |
|
||||
| Monospace data | Fixed-width for numbers/code | Technical, precision |
|
||||
| Hand-drawn | Organic, imperfect letterforms | Friendly, approachable |
|
||||
|
||||
### Geometric Accents
|
||||
|
||||
| Element | Description | Best For |
|
||||
|---------|-------------|----------|
|
||||
| Diagonal dividers | Angled section separators | Energy, movement |
|
||||
| Corner brackets | L-shaped frames | Focus, framing |
|
||||
| Circles/hexagons | Shape frames for images | Modern, tech |
|
||||
| Underline accents | Thick lines under headers | Emphasis, hierarchy |
|
||||
|
||||
## File Management
|
||||
|
||||
### Output Directory
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
---
|
||||
name: baoyu-url-to-markdown
|
||||
description: Fetch any URL and convert to markdown using Chrome CDP. Supports two modes - auto-capture on page load, or wait for user signal (for pages requiring login). Use when user wants to save a webpage as markdown.
|
||||
---
|
||||
|
||||
# URL to Markdown
|
||||
|
||||
Fetches any URL via Chrome CDP and converts HTML to clean markdown.
|
||||
|
||||
## Script Directory
|
||||
|
||||
**Important**: All scripts are located in the `scripts/` subdirectory of this skill.
|
||||
|
||||
**Agent Execution Instructions**:
|
||||
1. Determine this SKILL.md file's directory path as `SKILL_DIR`
|
||||
2. Script path = `${SKILL_DIR}/scripts/<script-name>.ts`
|
||||
3. Replace all `${SKILL_DIR}` in this document with the actual path
|
||||
|
||||
**Script Reference**:
|
||||
| Script | Purpose |
|
||||
|--------|---------|
|
||||
| `scripts/main.ts` | CLI entry point for URL fetching |
|
||||
|
||||
## Features
|
||||
|
||||
- Chrome CDP for full JavaScript rendering
|
||||
- Two capture modes: auto or wait-for-user
|
||||
- Clean markdown output with metadata
|
||||
- Handles login-required pages via wait mode
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Auto mode (default) - capture when page loads
|
||||
npx -y bun ${SKILL_DIR}/scripts/main.ts <url>
|
||||
|
||||
# Wait mode - wait for user signal before capture
|
||||
npx -y bun ${SKILL_DIR}/scripts/main.ts <url> --wait
|
||||
|
||||
# Save to specific file
|
||||
npx -y bun ${SKILL_DIR}/scripts/main.ts <url> -o output.md
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `<url>` | URL to fetch |
|
||||
| `-o <path>` | Output file path (default: auto-generated) |
|
||||
| `--wait` | Wait for user signal before capturing |
|
||||
| `--timeout <ms>` | Page load timeout (default: 30000) |
|
||||
|
||||
## Capture Modes
|
||||
|
||||
### Auto Mode (default)
|
||||
|
||||
Page loads → waits for network idle → captures immediately.
|
||||
|
||||
Best for:
|
||||
- Public pages
|
||||
- Static content
|
||||
- No login required
|
||||
|
||||
### Wait Mode (`--wait`)
|
||||
|
||||
Page opens → user can interact (login, scroll, etc.) → user signals ready → captures.
|
||||
|
||||
Best for:
|
||||
- Login-required pages
|
||||
- Dynamic content needing interaction
|
||||
- Pages with lazy loading
|
||||
|
||||
**Agent workflow for wait mode**:
|
||||
1. Run script with `--wait` flag
|
||||
2. Script outputs: `Page opened. Press Enter when ready to capture...`
|
||||
3. Use `AskUserQuestion` to ask user if page is ready
|
||||
4. When user confirms, send newline to stdin to trigger capture
|
||||
|
||||
## Output Format
|
||||
|
||||
```markdown
|
||||
---
|
||||
url: https://example.com/page
|
||||
title: "Page Title"
|
||||
description: "Meta description if available"
|
||||
author: "Author if available"
|
||||
published: "2024-01-01"
|
||||
captured_at: "2024-01-15T10:30:00Z"
|
||||
---
|
||||
|
||||
# Page Title
|
||||
|
||||
Converted markdown content...
|
||||
```
|
||||
|
||||
## Mode Selection Guide
|
||||
|
||||
When user requests URL capture, help select appropriate mode:
|
||||
|
||||
**Suggest Auto Mode when**:
|
||||
- URL is public (no login wall visible)
|
||||
- Content appears static
|
||||
- User doesn't mention login requirements
|
||||
|
||||
**Suggest Wait Mode when**:
|
||||
- User mentions needing to log in
|
||||
- Site known to require authentication
|
||||
- User wants to scroll/interact before capture
|
||||
- Content is behind paywall
|
||||
|
||||
**Ask user when unclear**:
|
||||
```
|
||||
The page may require login or interaction before capturing.
|
||||
|
||||
Which mode should I use?
|
||||
1. Auto - Capture immediately when loaded
|
||||
2. Wait - Wait for you to interact first
|
||||
```
|
||||
|
||||
## Output Directory
|
||||
|
||||
Each capture creates a file organized by domain:
|
||||
|
||||
```
|
||||
url-to-markdown/
|
||||
└── <domain>/
|
||||
└── <slug>.md
|
||||
```
|
||||
|
||||
**Path Components**:
|
||||
- `<domain>`: Site domain (e.g., `example.com`, `github.com`)
|
||||
- `<slug>`: Generated from page title or URL path (kebab-case)
|
||||
|
||||
**Slug Generation**:
|
||||
1. Extract from page title (preferred) or URL path
|
||||
2. Convert to kebab-case, 2-6 words
|
||||
3. Example: "Getting Started with React" → `getting-started-with-react`
|
||||
|
||||
**Conflict Resolution**:
|
||||
If `url-to-markdown/<domain>/<slug>.md` already exists:
|
||||
- Append timestamp: `<slug>-YYYYMMDD-HHMMSS.md`
|
||||
- Example: `getting-started.md` exists → `getting-started-20260118-143052.md`
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Chrome not found | Install Chrome or set `URL_CHROME_PATH` env |
|
||||
| Page timeout | Increase `--timeout` value |
|
||||
| Capture failed | Try wait mode for complex pages |
|
||||
| Empty content | Page may need JS rendering time |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `URL_CHROME_PATH` | Custom Chrome executable path |
|
||||
| `URL_DATA_DIR` | Custom data directory |
|
||||
| `URL_CHROME_PROFILE_DIR` | Custom Chrome profile directory |
|
||||
|
||||
## Extension Support
|
||||
|
||||
Custom configurations via EXTEND.md.
|
||||
|
||||
**Check paths** (priority order):
|
||||
1. `.baoyu-skills/baoyu-url-to-markdown/EXTEND.md` (project)
|
||||
2. `~/.baoyu-skills/baoyu-url-to-markdown/EXTEND.md` (user)
|
||||
|
||||
If found, load before workflow. Extension content overrides defaults.
|
||||
@@ -0,0 +1,290 @@
|
||||
import { spawn, type ChildProcess } from "node:child_process";
|
||||
import fs from "node:fs";
|
||||
import { mkdir } from "node:fs/promises";
|
||||
import net from "node:net";
|
||||
import process from "node:process";
|
||||
|
||||
import { resolveUrlToMarkdownChromeProfileDir } from "./paths.js";
|
||||
import { CDP_CONNECT_TIMEOUT_MS, NETWORK_IDLE_TIMEOUT_MS } from "./constants.js";
|
||||
|
||||
type CdpSendOptions = { sessionId?: string; timeoutMs?: number };
|
||||
|
||||
function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function fetchWithTimeout(url: string, init: RequestInit & { timeoutMs?: number } = {}): Promise<Response> {
|
||||
const { timeoutMs, ...rest } = init;
|
||||
if (!timeoutMs || timeoutMs <= 0) return fetch(url, rest);
|
||||
const ctl = new AbortController();
|
||||
const t = setTimeout(() => ctl.abort(), timeoutMs);
|
||||
try {
|
||||
return await fetch(url, { ...rest, signal: ctl.signal });
|
||||
} finally {
|
||||
clearTimeout(t);
|
||||
}
|
||||
}
|
||||
|
||||
export class CdpConnection {
|
||||
private ws: WebSocket;
|
||||
private nextId = 0;
|
||||
private pending = new Map<number, { resolve: (v: unknown) => void; reject: (e: Error) => void; timer: ReturnType<typeof setTimeout> | null }>();
|
||||
private eventHandlers = new Map<string, Set<(params: unknown) => void>>();
|
||||
|
||||
private constructor(ws: WebSocket) {
|
||||
this.ws = ws;
|
||||
this.ws.addEventListener("message", (event) => {
|
||||
try {
|
||||
const data = typeof event.data === "string" ? event.data : new TextDecoder().decode(event.data as ArrayBuffer);
|
||||
const msg = JSON.parse(data) as { id?: number; method?: string; params?: unknown; result?: unknown; error?: { message?: string } };
|
||||
if (msg.id) {
|
||||
const p = this.pending.get(msg.id);
|
||||
if (p) {
|
||||
this.pending.delete(msg.id);
|
||||
if (p.timer) clearTimeout(p.timer);
|
||||
if (msg.error?.message) p.reject(new Error(msg.error.message));
|
||||
else p.resolve(msg.result);
|
||||
}
|
||||
} else if (msg.method) {
|
||||
const handlers = this.eventHandlers.get(msg.method);
|
||||
if (handlers) {
|
||||
for (const h of handlers) h(msg.params);
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
});
|
||||
this.ws.addEventListener("close", () => {
|
||||
for (const [id, p] of this.pending.entries()) {
|
||||
this.pending.delete(id);
|
||||
if (p.timer) clearTimeout(p.timer);
|
||||
p.reject(new Error("CDP connection closed."));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static async connect(url: string, timeoutMs: number): Promise<CdpConnection> {
|
||||
const ws = new WebSocket(url);
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const t = setTimeout(() => reject(new Error("CDP connection timeout.")), timeoutMs);
|
||||
ws.addEventListener("open", () => { clearTimeout(t); resolve(); });
|
||||
ws.addEventListener("error", () => { clearTimeout(t); reject(new Error("CDP connection failed.")); });
|
||||
});
|
||||
return new CdpConnection(ws);
|
||||
}
|
||||
|
||||
on(event: string, handler: (params: unknown) => void): void {
|
||||
let handlers = this.eventHandlers.get(event);
|
||||
if (!handlers) {
|
||||
handlers = new Set();
|
||||
this.eventHandlers.set(event, handlers);
|
||||
}
|
||||
handlers.add(handler);
|
||||
}
|
||||
|
||||
off(event: string, handler: (params: unknown) => void): void {
|
||||
this.eventHandlers.get(event)?.delete(handler);
|
||||
}
|
||||
|
||||
async send<T = unknown>(method: string, params?: Record<string, unknown>, opts?: CdpSendOptions): Promise<T> {
|
||||
const id = ++this.nextId;
|
||||
const msg: Record<string, unknown> = { id, method };
|
||||
if (params) msg.params = params;
|
||||
if (opts?.sessionId) msg.sessionId = opts.sessionId;
|
||||
const timeoutMs = opts?.timeoutMs ?? 15_000;
|
||||
const out = await new Promise<unknown>((resolve, reject) => {
|
||||
const t = timeoutMs > 0 ? setTimeout(() => { this.pending.delete(id); reject(new Error(`CDP timeout: ${method}`)); }, timeoutMs) : null;
|
||||
this.pending.set(id, { resolve, reject, timer: t });
|
||||
this.ws.send(JSON.stringify(msg));
|
||||
});
|
||||
return out as T;
|
||||
}
|
||||
|
||||
close(): void {
|
||||
try { this.ws.close(); } catch {}
|
||||
}
|
||||
}
|
||||
|
||||
export async function getFreePort(): Promise<number> {
|
||||
return await new Promise((resolve, reject) => {
|
||||
const srv = net.createServer();
|
||||
srv.unref();
|
||||
srv.on("error", reject);
|
||||
srv.listen(0, "127.0.0.1", () => {
|
||||
const addr = srv.address();
|
||||
if (!addr || typeof addr === "string") {
|
||||
srv.close(() => reject(new Error("Unable to allocate a free TCP port.")));
|
||||
return;
|
||||
}
|
||||
const port = addr.port;
|
||||
srv.close((err) => (err ? reject(err) : resolve(port)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function findChromeExecutable(): string | null {
|
||||
const override = process.env.URL_CHROME_PATH?.trim();
|
||||
if (override && fs.existsSync(override)) return override;
|
||||
|
||||
const candidates: string[] = [];
|
||||
switch (process.platform) {
|
||||
case "darwin":
|
||||
candidates.push(
|
||||
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
||||
"/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary",
|
||||
"/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta",
|
||||
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
||||
"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"
|
||||
);
|
||||
break;
|
||||
case "win32":
|
||||
candidates.push(
|
||||
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
|
||||
"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
|
||||
"C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe",
|
||||
"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe"
|
||||
);
|
||||
break;
|
||||
default:
|
||||
candidates.push(
|
||||
"/usr/bin/google-chrome",
|
||||
"/usr/bin/google-chrome-stable",
|
||||
"/usr/bin/chromium",
|
||||
"/usr/bin/chromium-browser",
|
||||
"/snap/bin/chromium",
|
||||
"/usr/bin/microsoft-edge"
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
for (const p of candidates) {
|
||||
if (fs.existsSync(p)) return p;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function waitForChromeDebugPort(port: number, timeoutMs: number): Promise<string> {
|
||||
const start = Date.now();
|
||||
while (Date.now() - start < timeoutMs) {
|
||||
try {
|
||||
const res = await fetchWithTimeout(`http://127.0.0.1:${port}/json/version`, { timeoutMs: 5_000 });
|
||||
if (!res.ok) throw new Error(`status=${res.status}`);
|
||||
const j = (await res.json()) as { webSocketDebuggerUrl?: string };
|
||||
if (j.webSocketDebuggerUrl) return j.webSocketDebuggerUrl;
|
||||
} catch {}
|
||||
await sleep(200);
|
||||
}
|
||||
throw new Error("Chrome debug port not ready");
|
||||
}
|
||||
|
||||
export async function launchChrome(url: string, port: number, headless: boolean = false): Promise<ChildProcess> {
|
||||
const chrome = findChromeExecutable();
|
||||
if (!chrome) throw new Error("Chrome executable not found. Install Chrome or set URL_CHROME_PATH env.");
|
||||
const profileDir = resolveUrlToMarkdownChromeProfileDir();
|
||||
await mkdir(profileDir, { recursive: true });
|
||||
|
||||
const args = [
|
||||
`--remote-debugging-port=${port}`,
|
||||
`--user-data-dir=${profileDir}`,
|
||||
"--no-first-run",
|
||||
"--no-default-browser-check",
|
||||
"--disable-popup-blocking",
|
||||
];
|
||||
if (headless) args.push("--headless=new");
|
||||
args.push(url);
|
||||
|
||||
return spawn(chrome, args, { stdio: "ignore" });
|
||||
}
|
||||
|
||||
export async function waitForNetworkIdle(cdp: CdpConnection, sessionId: string, timeoutMs: number = NETWORK_IDLE_TIMEOUT_MS): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||
let pending = 0;
|
||||
const cleanup = () => {
|
||||
if (timer) clearTimeout(timer);
|
||||
cdp.off("Network.requestWillBeSent", onRequest);
|
||||
cdp.off("Network.loadingFinished", onFinish);
|
||||
cdp.off("Network.loadingFailed", onFinish);
|
||||
};
|
||||
const done = () => { cleanup(); resolve(); };
|
||||
const resetTimer = () => {
|
||||
if (timer) clearTimeout(timer);
|
||||
timer = setTimeout(done, timeoutMs);
|
||||
};
|
||||
const onRequest = () => { pending++; resetTimer(); };
|
||||
const onFinish = () => { pending = Math.max(0, pending - 1); if (pending <= 2) resetTimer(); };
|
||||
cdp.on("Network.requestWillBeSent", onRequest);
|
||||
cdp.on("Network.loadingFinished", onFinish);
|
||||
cdp.on("Network.loadingFailed", onFinish);
|
||||
resetTimer();
|
||||
});
|
||||
}
|
||||
|
||||
export async function waitForPageLoad(cdp: CdpConnection, sessionId: string, timeoutMs: number = 30_000): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timer = setTimeout(() => {
|
||||
cdp.off("Page.loadEventFired", handler);
|
||||
resolve();
|
||||
}, timeoutMs);
|
||||
const handler = () => {
|
||||
clearTimeout(timer);
|
||||
cdp.off("Page.loadEventFired", handler);
|
||||
resolve();
|
||||
};
|
||||
cdp.on("Page.loadEventFired", handler);
|
||||
});
|
||||
}
|
||||
|
||||
export async function createTargetAndAttach(cdp: CdpConnection, url: string): Promise<{ targetId: string; sessionId: string }> {
|
||||
const { targetId } = await cdp.send<{ targetId: string }>("Target.createTarget", { url });
|
||||
const { sessionId } = await cdp.send<{ sessionId: string }>("Target.attachToTarget", { targetId, flatten: true });
|
||||
await cdp.send("Network.enable", {}, { sessionId });
|
||||
await cdp.send("Page.enable", {}, { sessionId });
|
||||
return { targetId, sessionId };
|
||||
}
|
||||
|
||||
export async function navigateAndWait(cdp: CdpConnection, sessionId: string, url: string, timeoutMs: number): Promise<void> {
|
||||
const loadPromise = new Promise<void>((resolve, reject) => {
|
||||
const timer = setTimeout(() => reject(new Error("Page load timeout")), timeoutMs);
|
||||
const handler = (params: unknown) => {
|
||||
const p = params as { name?: string };
|
||||
if (p.name === "load" || p.name === "DOMContentLoaded") {
|
||||
clearTimeout(timer);
|
||||
cdp.off("Page.lifecycleEvent", handler);
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
cdp.on("Page.lifecycleEvent", handler);
|
||||
});
|
||||
await cdp.send("Page.navigate", { url }, { sessionId });
|
||||
await loadPromise;
|
||||
}
|
||||
|
||||
export async function evaluateScript<T>(cdp: CdpConnection, sessionId: string, expression: string, timeoutMs: number = 30_000): Promise<T> {
|
||||
const result = await cdp.send<{ result: { value?: T; type?: string; description?: string } }>(
|
||||
"Runtime.evaluate",
|
||||
{ expression, returnByValue: true, awaitPromise: true },
|
||||
{ sessionId, timeoutMs }
|
||||
);
|
||||
return result.result.value as T;
|
||||
}
|
||||
|
||||
export async function autoScroll(cdp: CdpConnection, sessionId: string, steps: number = 8, waitMs: number = 600): Promise<void> {
|
||||
let lastHeight = await evaluateScript<number>(cdp, sessionId, "document.body.scrollHeight");
|
||||
for (let i = 0; i < steps; i++) {
|
||||
await evaluateScript<void>(cdp, sessionId, "window.scrollTo(0, document.body.scrollHeight)");
|
||||
await sleep(waitMs);
|
||||
const newHeight = await evaluateScript<number>(cdp, sessionId, "document.body.scrollHeight");
|
||||
if (newHeight === lastHeight) break;
|
||||
lastHeight = newHeight;
|
||||
}
|
||||
await evaluateScript<void>(cdp, sessionId, "window.scrollTo(0, 0)");
|
||||
}
|
||||
|
||||
export function killChrome(chrome: ChildProcess): void {
|
||||
try { chrome.kill("SIGTERM"); } catch {}
|
||||
setTimeout(() => {
|
||||
if (!chrome.killed) {
|
||||
try { chrome.kill("SIGKILL"); } catch {}
|
||||
}
|
||||
}, 2_000).unref?.();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { resolveUrlToMarkdownChromeProfileDir } from "./paths.js";
|
||||
|
||||
export const DEFAULT_USER_AGENT =
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36";
|
||||
|
||||
export const USER_DATA_DIR = resolveUrlToMarkdownChromeProfileDir();
|
||||
|
||||
export const DEFAULT_TIMEOUT_MS = 30_000;
|
||||
export const CDP_CONNECT_TIMEOUT_MS = 15_000;
|
||||
export const NETWORK_IDLE_TIMEOUT_MS = 1_500;
|
||||
export const POST_LOAD_DELAY_MS = 800;
|
||||
export const SCROLL_STEP_WAIT_MS = 600;
|
||||
export const SCROLL_MAX_STEPS = 8;
|
||||
@@ -0,0 +1,223 @@
|
||||
export interface PageMetadata {
|
||||
url: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
author?: string;
|
||||
published?: string;
|
||||
captured_at: string;
|
||||
}
|
||||
|
||||
export interface ConversionResult {
|
||||
metadata: PageMetadata;
|
||||
markdown: string;
|
||||
}
|
||||
|
||||
export const cleanupAndExtractScript = `
|
||||
(function() {
|
||||
const removeSelectors = [
|
||||
'script', 'style', 'noscript', 'iframe', 'svg', 'canvas',
|
||||
'header nav', 'footer', '.sidebar', '.nav', '.navigation',
|
||||
'.advertisement', '.ad', '.ads', '.cookie-banner', '.popup',
|
||||
'[role="banner"]', '[role="navigation"]', '[role="complementary"]'
|
||||
];
|
||||
|
||||
for (const sel of removeSelectors) {
|
||||
try {
|
||||
document.querySelectorAll(sel).forEach(el => el.remove());
|
||||
} catch {}
|
||||
}
|
||||
|
||||
document.querySelectorAll('*').forEach(el => {
|
||||
el.removeAttribute('style');
|
||||
el.removeAttribute('onclick');
|
||||
el.removeAttribute('onload');
|
||||
el.removeAttribute('onerror');
|
||||
});
|
||||
|
||||
const baseUrl = document.baseURI || location.href;
|
||||
document.querySelectorAll('a[href]').forEach(a => {
|
||||
try {
|
||||
const href = a.getAttribute('href');
|
||||
if (href && !href.startsWith('#') && !href.startsWith('javascript:')) {
|
||||
a.setAttribute('href', new URL(href, baseUrl).href);
|
||||
}
|
||||
} catch {}
|
||||
});
|
||||
document.querySelectorAll('img[src]').forEach(img => {
|
||||
try {
|
||||
const src = img.getAttribute('src');
|
||||
if (src) img.setAttribute('src', new URL(src, baseUrl).href);
|
||||
} catch {}
|
||||
});
|
||||
|
||||
const getMeta = (names) => {
|
||||
for (const name of names) {
|
||||
const el = document.querySelector(\`meta[name="\${name}"], meta[property="\${name}"]\`);
|
||||
if (el) {
|
||||
const content = el.getAttribute('content');
|
||||
if (content) return content.trim();
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const getTitle = () => {
|
||||
const ogTitle = getMeta(['og:title', 'twitter:title']);
|
||||
if (ogTitle) return ogTitle;
|
||||
const h1 = document.querySelector('h1');
|
||||
if (h1) return h1.textContent?.trim();
|
||||
return document.title?.trim() || '';
|
||||
};
|
||||
|
||||
const getPublished = () => {
|
||||
const timeEl = document.querySelector('time[datetime]');
|
||||
if (timeEl) return timeEl.getAttribute('datetime');
|
||||
return getMeta(['article:published_time', 'datePublished', 'date']);
|
||||
};
|
||||
|
||||
const main = document.querySelector('main, article, [role="main"], .main-content, .post-content, .article-content, .content');
|
||||
const html = main ? main.innerHTML : document.body.innerHTML;
|
||||
|
||||
return {
|
||||
title: getTitle(),
|
||||
description: getMeta(['description', 'og:description', 'twitter:description']),
|
||||
author: getMeta(['author', 'article:author', 'twitter:creator']),
|
||||
published: getPublished(),
|
||||
html: html
|
||||
};
|
||||
})()
|
||||
`;
|
||||
|
||||
function decodeHtmlEntities(text: string): string {
|
||||
return text
|
||||
.replace(/ /g, ' ')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, "'")
|
||||
.replace(/'/g, "'")
|
||||
.replace(/&#(\d+);/g, (_, n) => String.fromCharCode(parseInt(n, 10)))
|
||||
.replace(/&#x([0-9a-fA-F]+);/g, (_, n) => String.fromCharCode(parseInt(n, 16)));
|
||||
}
|
||||
|
||||
function stripTags(html: string): string {
|
||||
return html.replace(/<[^>]+>/g, '');
|
||||
}
|
||||
|
||||
function normalizeWhitespace(text: string): string {
|
||||
return text.replace(/[ \t]+/g, ' ').replace(/\n{3,}/g, '\n\n').trim();
|
||||
}
|
||||
|
||||
export function htmlToMarkdown(html: string): string {
|
||||
let md = html;
|
||||
|
||||
md = md.replace(/<br\s*\/?>/gi, '\n');
|
||||
md = md.replace(/<hr\s*\/?>/gi, '\n\n---\n\n');
|
||||
|
||||
md = md.replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, (_, c) => `\n\n# ${stripTags(c).trim()}\n\n`);
|
||||
md = md.replace(/<h2[^>]*>([\s\S]*?)<\/h2>/gi, (_, c) => `\n\n## ${stripTags(c).trim()}\n\n`);
|
||||
md = md.replace(/<h3[^>]*>([\s\S]*?)<\/h3>/gi, (_, c) => `\n\n### ${stripTags(c).trim()}\n\n`);
|
||||
md = md.replace(/<h4[^>]*>([\s\S]*?)<\/h4>/gi, (_, c) => `\n\n#### ${stripTags(c).trim()}\n\n`);
|
||||
md = md.replace(/<h5[^>]*>([\s\S]*?)<\/h5>/gi, (_, c) => `\n\n##### ${stripTags(c).trim()}\n\n`);
|
||||
md = md.replace(/<h6[^>]*>([\s\S]*?)<\/h6>/gi, (_, c) => `\n\n###### ${stripTags(c).trim()}\n\n`);
|
||||
|
||||
md = md.replace(/<strong[^>]*>([\s\S]*?)<\/strong>/gi, (_, c) => `**${stripTags(c).trim()}**`);
|
||||
md = md.replace(/<b[^>]*>([\s\S]*?)<\/b>/gi, (_, c) => `**${stripTags(c).trim()}**`);
|
||||
md = md.replace(/<em[^>]*>([\s\S]*?)<\/em>/gi, (_, c) => `*${stripTags(c).trim()}*`);
|
||||
md = md.replace(/<i[^>]*>([\s\S]*?)<\/i>/gi, (_, c) => `*${stripTags(c).trim()}*`);
|
||||
md = md.replace(/<del[^>]*>([\s\S]*?)<\/del>/gi, (_, c) => `~~${stripTags(c).trim()}~~`);
|
||||
md = md.replace(/<s[^>]*>([\s\S]*?)<\/s>/gi, (_, c) => `~~${stripTags(c).trim()}~~`);
|
||||
md = md.replace(/<mark[^>]*>([\s\S]*?)<\/mark>/gi, (_, c) => `==${stripTags(c).trim()}==`);
|
||||
|
||||
md = md.replace(/<a[^>]*href=["']([^"']+)["'][^>]*>([\s\S]*?)<\/a>/gi, (_, href, text) => {
|
||||
const t = stripTags(text).trim();
|
||||
if (!t || href.startsWith('javascript:')) return t;
|
||||
return `[${t}](${href})`;
|
||||
});
|
||||
|
||||
md = md.replace(/<img[^>]*src=["']([^"']+)["'][^>]*alt=["']([^"']*)["'][^>]*\/?>/gi, (_, src, alt) => ``);
|
||||
md = md.replace(/<img[^>]*alt=["']([^"']*)["'][^>]*src=["']([^"']+)["'][^>]*\/?>/gi, (_, alt, src) => ``);
|
||||
md = md.replace(/<img[^>]*src=["']([^"']+)["'][^>]*\/?>/gi, (_, src) => ``);
|
||||
|
||||
md = md.replace(/<pre[^>]*><code[^>]*>([\s\S]*?)<\/code><\/pre>/gi, (_, code) => `\n\n\`\`\`\n${decodeHtmlEntities(stripTags(code)).trim()}\n\`\`\`\n\n`);
|
||||
md = md.replace(/<pre[^>]*>([\s\S]*?)<\/pre>/gi, (_, code) => `\n\n\`\`\`\n${decodeHtmlEntities(stripTags(code)).trim()}\n\`\`\`\n\n`);
|
||||
md = md.replace(/<code[^>]*>([\s\S]*?)<\/code>/gi, (_, code) => `\`${decodeHtmlEntities(stripTags(code)).trim()}\``);
|
||||
|
||||
md = md.replace(/<blockquote[^>]*>([\s\S]*?)<\/blockquote>/gi, (_, content) => {
|
||||
const lines = stripTags(content).trim().split('\n');
|
||||
return '\n\n' + lines.map(l => `> ${l.trim()}`).join('\n') + '\n\n';
|
||||
});
|
||||
|
||||
md = md.replace(/<ul[^>]*>([\s\S]*?)<\/ul>/gi, (_, items) => {
|
||||
const lis = items.match(/<li[^>]*>([\s\S]*?)<\/li>/gi) || [];
|
||||
const lines = lis.map(li => {
|
||||
const content = li.replace(/<li[^>]*>([\s\S]*?)<\/li>/i, '$1');
|
||||
return `- ${stripTags(content).trim()}`;
|
||||
});
|
||||
return '\n\n' + lines.join('\n') + '\n\n';
|
||||
});
|
||||
|
||||
md = md.replace(/<ol[^>]*>([\s\S]*?)<\/ol>/gi, (_, items) => {
|
||||
const lis = items.match(/<li[^>]*>([\s\S]*?)<\/li>/gi) || [];
|
||||
const lines = lis.map((li, i) => {
|
||||
const content = li.replace(/<li[^>]*>([\s\S]*?)<\/li>/i, '$1');
|
||||
return `${i + 1}. ${stripTags(content).trim()}`;
|
||||
});
|
||||
return '\n\n' + lines.join('\n') + '\n\n';
|
||||
});
|
||||
|
||||
md = md.replace(/<table[^>]*>([\s\S]*?)<\/table>/gi, (_, table) => {
|
||||
const rows: string[][] = [];
|
||||
const trMatches = table.match(/<tr[^>]*>([\s\S]*?)<\/tr>/gi) || [];
|
||||
for (const tr of trMatches) {
|
||||
const cells: string[] = [];
|
||||
const cellMatches = tr.match(/<t[hd][^>]*>([\s\S]*?)<\/t[hd]>/gi) || [];
|
||||
for (const cell of cellMatches) {
|
||||
const content = cell.replace(/<t[hd][^>]*>([\s\S]*?)<\/t[hd]>/i, '$1');
|
||||
cells.push(stripTags(content).trim().replace(/\|/g, '\\|'));
|
||||
}
|
||||
if (cells.length > 0) rows.push(cells);
|
||||
}
|
||||
if (rows.length === 0) return '';
|
||||
const colCount = Math.max(...rows.map(r => r.length));
|
||||
const normalizedRows = rows.map(r => {
|
||||
while (r.length < colCount) r.push('');
|
||||
return r;
|
||||
});
|
||||
const header = `| ${normalizedRows[0].join(' | ')} |`;
|
||||
const sep = `| ${normalizedRows[0].map(() => '---').join(' | ')} |`;
|
||||
const body = normalizedRows.slice(1).map(r => `| ${r.join(' | ')} |`).join('\n');
|
||||
return '\n\n' + header + '\n' + sep + (body ? '\n' + body : '') + '\n\n';
|
||||
});
|
||||
|
||||
md = md.replace(/<p[^>]*>([\s\S]*?)<\/p>/gi, (_, c) => `\n\n${stripTags(c).trim()}\n\n`);
|
||||
md = md.replace(/<div[^>]*>([\s\S]*?)<\/div>/gi, (_, c) => `\n${stripTags(c).trim()}\n`);
|
||||
md = md.replace(/<span[^>]*>([\s\S]*?)<\/span>/gi, (_, c) => stripTags(c));
|
||||
|
||||
md = stripTags(md);
|
||||
md = decodeHtmlEntities(md);
|
||||
md = normalizeWhitespace(md);
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
export function formatMetadataYaml(meta: PageMetadata): string {
|
||||
const lines = ['---'];
|
||||
lines.push(`url: ${meta.url}`);
|
||||
lines.push(`title: "${meta.title.replace(/"/g, '\\"')}"`);
|
||||
if (meta.description) lines.push(`description: "${meta.description.replace(/"/g, '\\"')}"`);
|
||||
if (meta.author) lines.push(`author: "${meta.author.replace(/"/g, '\\"')}"`);
|
||||
if (meta.published) lines.push(`published: "${meta.published}"`);
|
||||
lines.push(`captured_at: "${meta.captured_at}"`);
|
||||
lines.push('---');
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
export function createMarkdownDocument(result: ConversionResult): string {
|
||||
const yaml = formatMetadataYaml(result.metadata);
|
||||
const titleRegex = new RegExp(`^#\\s+${result.metadata.title.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*\\n`, 'i');
|
||||
const hasTitle = titleRegex.test(result.markdown);
|
||||
const title = result.metadata.title && !hasTitle ? `\n\n# ${result.metadata.title}\n\n` : '\n\n';
|
||||
return yaml + title + result.markdown;
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
import { createInterface } from "node:readline";
|
||||
import { writeFile, mkdir, access } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import process from "node:process";
|
||||
|
||||
import { CdpConnection, getFreePort, launchChrome, waitForChromeDebugPort, waitForNetworkIdle, waitForPageLoad, autoScroll, evaluateScript, killChrome } from "./cdp.js";
|
||||
import { cleanupAndExtractScript, htmlToMarkdown, createMarkdownDocument, type PageMetadata, type ConversionResult } from "./html-to-markdown.js";
|
||||
import { resolveUrlToMarkdownDataDir } from "./paths.js";
|
||||
import { DEFAULT_TIMEOUT_MS, CDP_CONNECT_TIMEOUT_MS, NETWORK_IDLE_TIMEOUT_MS, POST_LOAD_DELAY_MS, SCROLL_STEP_WAIT_MS, SCROLL_MAX_STEPS } from "./constants.js";
|
||||
|
||||
function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function fileExists(filePath: string): Promise<boolean> {
|
||||
try {
|
||||
await access(filePath);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
interface Args {
|
||||
url: string;
|
||||
output?: string;
|
||||
wait: boolean;
|
||||
timeout: number;
|
||||
}
|
||||
|
||||
function parseArgs(argv: string[]): Args {
|
||||
const args: Args = { url: "", wait: false, timeout: DEFAULT_TIMEOUT_MS };
|
||||
for (let i = 2; i < argv.length; i++) {
|
||||
const arg = argv[i];
|
||||
if (arg === "--wait" || arg === "-w") {
|
||||
args.wait = true;
|
||||
} else if (arg === "-o" || arg === "--output") {
|
||||
args.output = argv[++i];
|
||||
} else if (arg === "--timeout" || arg === "-t") {
|
||||
args.timeout = parseInt(argv[++i], 10) || DEFAULT_TIMEOUT_MS;
|
||||
} else if (!arg.startsWith("-") && !args.url) {
|
||||
args.url = arg;
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
function generateSlug(title: string, url: string): string {
|
||||
const text = title || new URL(url).pathname.replace(/\//g, "-");
|
||||
return text
|
||||
.toLowerCase()
|
||||
.replace(/[^\w\s-]/g, "")
|
||||
.replace(/\s+/g, "-")
|
||||
.replace(/-+/g, "-")
|
||||
.replace(/^-|-$/g, "")
|
||||
.slice(0, 50) || "page";
|
||||
}
|
||||
|
||||
function formatTimestamp(): string {
|
||||
const now = new Date();
|
||||
const pad = (n: number) => n.toString().padStart(2, "0");
|
||||
return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
|
||||
}
|
||||
|
||||
async function generateOutputPath(url: string, title: string): Promise<string> {
|
||||
const domain = new URL(url).hostname.replace(/^www\./, "");
|
||||
const slug = generateSlug(title, url);
|
||||
const dataDir = resolveUrlToMarkdownDataDir();
|
||||
const basePath = path.join(dataDir, domain, `${slug}.md`);
|
||||
|
||||
if (!(await fileExists(basePath))) {
|
||||
return basePath;
|
||||
}
|
||||
|
||||
const timestampSlug = `${slug}-${formatTimestamp()}`;
|
||||
return path.join(dataDir, domain, `${timestampSlug}.md`);
|
||||
}
|
||||
|
||||
async function waitForUserSignal(): Promise<void> {
|
||||
console.log("Page opened. Press Enter when ready to capture...");
|
||||
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
||||
await new Promise<void>((resolve) => {
|
||||
rl.once("line", () => { rl.close(); resolve(); });
|
||||
});
|
||||
}
|
||||
|
||||
async function captureUrl(args: Args): Promise<ConversionResult> {
|
||||
const port = await getFreePort();
|
||||
const chrome = await launchChrome(args.url, port, false);
|
||||
|
||||
let cdp: CdpConnection | null = null;
|
||||
try {
|
||||
const wsUrl = await waitForChromeDebugPort(port, 30_000);
|
||||
cdp = await CdpConnection.connect(wsUrl, CDP_CONNECT_TIMEOUT_MS);
|
||||
|
||||
const targets = await cdp.send<{ targetInfos: Array<{ targetId: string; type: string; url: string }> }>("Target.getTargets");
|
||||
const pageTarget = targets.targetInfos.find(t => t.type === "page" && t.url.startsWith("http"));
|
||||
if (!pageTarget) throw new Error("No page target found");
|
||||
|
||||
const { sessionId } = await cdp.send<{ sessionId: string }>("Target.attachToTarget", { targetId: pageTarget.targetId, flatten: true });
|
||||
await cdp.send("Network.enable", {}, { sessionId });
|
||||
await cdp.send("Page.enable", {}, { sessionId });
|
||||
|
||||
if (args.wait) {
|
||||
await waitForUserSignal();
|
||||
} else {
|
||||
console.log("Waiting for page to load...");
|
||||
await Promise.race([
|
||||
waitForPageLoad(cdp, sessionId, 15_000),
|
||||
sleep(8_000)
|
||||
]);
|
||||
await waitForNetworkIdle(cdp, sessionId, NETWORK_IDLE_TIMEOUT_MS);
|
||||
await sleep(POST_LOAD_DELAY_MS);
|
||||
console.log("Scrolling to trigger lazy load...");
|
||||
await autoScroll(cdp, sessionId, SCROLL_MAX_STEPS, SCROLL_STEP_WAIT_MS);
|
||||
await sleep(POST_LOAD_DELAY_MS);
|
||||
}
|
||||
|
||||
console.log("Capturing page content...");
|
||||
const extracted = await evaluateScript<{ title: string; description?: string; author?: string; published?: string; html: string }>(
|
||||
cdp, sessionId, cleanupAndExtractScript, args.timeout
|
||||
);
|
||||
|
||||
const metadata: PageMetadata = {
|
||||
url: args.url,
|
||||
title: extracted.title || "",
|
||||
description: extracted.description,
|
||||
author: extracted.author,
|
||||
published: extracted.published,
|
||||
captured_at: new Date().toISOString()
|
||||
};
|
||||
|
||||
const markdown = htmlToMarkdown(extracted.html);
|
||||
return { metadata, markdown };
|
||||
} finally {
|
||||
if (cdp) {
|
||||
try { await cdp.send("Browser.close", {}, { timeoutMs: 5_000 }); } catch {}
|
||||
cdp.close();
|
||||
}
|
||||
killChrome(chrome);
|
||||
}
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const args = parseArgs(process.argv);
|
||||
if (!args.url) {
|
||||
console.error("Usage: bun main.ts <url> [-o output.md] [--wait] [--timeout ms]");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
new URL(args.url);
|
||||
} catch {
|
||||
console.error(`Invalid URL: ${args.url}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Fetching: ${args.url}`);
|
||||
console.log(`Mode: ${args.wait ? "wait" : "auto"}`);
|
||||
|
||||
const result = await captureUrl(args);
|
||||
const outputPath = args.output || await generateOutputPath(args.url, result.metadata.title);
|
||||
const outputDir = path.dirname(outputPath);
|
||||
await mkdir(outputDir, { recursive: true });
|
||||
|
||||
const document = createMarkdownDocument(result);
|
||||
await writeFile(outputPath, document, "utf-8");
|
||||
|
||||
console.log(`Saved: ${outputPath}`);
|
||||
console.log(`Title: ${result.metadata.title || "(no title)"}`);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error("Error:", err instanceof Error ? err.message : String(err));
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import process from "node:process";
|
||||
|
||||
const APP_DATA_DIR = "baoyu-skills";
|
||||
const URL_TO_MARKDOWN_DATA_DIR = "url-to-markdown";
|
||||
const PROFILE_DIR_NAME = "chrome-profile";
|
||||
|
||||
export function resolveUserDataRoot(): string {
|
||||
if (process.platform === "win32") {
|
||||
return process.env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming");
|
||||
}
|
||||
if (process.platform === "darwin") {
|
||||
return path.join(os.homedir(), "Library", "Application Support");
|
||||
}
|
||||
return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
|
||||
}
|
||||
|
||||
export function resolveUrlToMarkdownDataDir(): string {
|
||||
const override = process.env.URL_DATA_DIR?.trim();
|
||||
if (override) return path.resolve(override);
|
||||
return path.join(process.cwd(), URL_TO_MARKDOWN_DATA_DIR);
|
||||
}
|
||||
|
||||
export function resolveUrlToMarkdownChromeProfileDir(): string {
|
||||
const override = process.env.URL_CHROME_PROFILE_DIR?.trim();
|
||||
if (override) return path.resolve(override);
|
||||
return path.join(resolveUserDataRoot(), APP_DATA_DIR, URL_TO_MARKDOWN_DATA_DIR, PROFILE_DIR_NAME);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: baoyu-xhs-images
|
||||
description: Xiaohongshu (Little Red Book) infographic series generator with multiple style options. Breaks down content into 1-10 cartoon-style infographics. Use when user asks to create "小红书图片", "XHS images", or "RedNote infographics".
|
||||
description: Generates Xiaohongshu (Little Red Book) infographic series with 9 visual styles and 6 layouts. Breaks content into 1-10 cartoon-style images optimized for XHS engagement. Use when user mentions "小红书图片", "XHS images", "RedNote infographics", "小红书种草", or wants social media infographics for Chinese platforms.
|
||||
---
|
||||
|
||||
# Xiaohongshu Infographic Series Generator
|
||||
@@ -20,7 +20,7 @@ Break down complex content into eye-catching infographic series for Xiaohongshu
|
||||
/baoyu-xhs-images posts/ai-future/article.md --layout dense
|
||||
|
||||
# Combine style and layout
|
||||
/baoyu-xhs-images posts/ai-future/article.md --style tech --layout list
|
||||
/baoyu-xhs-images posts/ai-future/article.md --style notion --layout list
|
||||
|
||||
# Direct content input
|
||||
/baoyu-xhs-images
|
||||
@@ -61,7 +61,7 @@ Style × Layout can be freely combined. Example: `--style notion --layout dense`
|
||||
| `notion` | Minimalist hand-drawn line art, intellectual |
|
||||
| `chalkboard` | Colorful chalk on black board, educational |
|
||||
|
||||
Detailed style definitions: `references/styles/<style>.md`
|
||||
Detailed style definitions: `references/presets/<style>.md`
|
||||
|
||||
## Layout Gallery
|
||||
|
||||
@@ -74,7 +74,7 @@ Detailed style definitions: `references/styles/<style>.md`
|
||||
| `comparison` | Side-by-side contrast layout |
|
||||
| `flow` | Process and timeline layout (3-6 steps) |
|
||||
|
||||
Detailed layout definitions: `references/layouts/<layout>.md`
|
||||
Detailed layout definitions: `references/elements/canvas.md`
|
||||
|
||||
## Auto Selection
|
||||
|
||||
@@ -90,6 +90,37 @@ Detailed layout definitions: `references/layouts/<layout>.md`
|
||||
| Knowledge, concept, productivity, SaaS | `notion` | dense/list |
|
||||
| Education, tutorial, learning, teaching, classroom | `chalkboard` | balanced/dense |
|
||||
|
||||
## Outline Strategies
|
||||
|
||||
Three differentiated outline strategies for different content goals:
|
||||
|
||||
### Strategy A: Story-Driven (故事驱动型)
|
||||
|
||||
| Aspect | Description |
|
||||
|--------|-------------|
|
||||
| **Concept** | Personal experience as main thread, emotional resonance first |
|
||||
| **Features** | Start from pain point, show before/after change, strong authenticity |
|
||||
| **Best for** | Reviews, personal shares, transformation stories |
|
||||
| **Structure** | Hook → Problem → Discovery → Experience → Conclusion |
|
||||
|
||||
### Strategy B: Information-Dense (信息密集型)
|
||||
|
||||
| Aspect | Description |
|
||||
|--------|-------------|
|
||||
| **Concept** | Value-first, efficient information delivery |
|
||||
| **Features** | Clear structure, explicit points, professional credibility |
|
||||
| **Best for** | Tutorials, comparisons, product reviews, checklists |
|
||||
| **Structure** | Core conclusion → Info card → Pros/Cons → Recommendation |
|
||||
|
||||
### Strategy C: Visual-First (视觉优先型)
|
||||
|
||||
| Aspect | Description |
|
||||
|--------|-------------|
|
||||
| **Concept** | Visual impact as core, minimal text |
|
||||
| **Features** | Large images, atmospheric, instant appeal |
|
||||
| **Best for** | High-aesthetic products, lifestyle, mood-based content |
|
||||
| **Structure** | Hero image → Detail shots → Lifestyle scene → CTA |
|
||||
|
||||
## File Structure
|
||||
|
||||
Each session creates an independent directory named by content slug:
|
||||
@@ -97,11 +128,11 @@ Each session creates an independent directory named by content slug:
|
||||
```
|
||||
xhs-images/{topic-slug}/
|
||||
├── source-{slug}.{ext} # Source files (text, images, etc.)
|
||||
├── analysis.md # Deep analysis results
|
||||
├── outline-style-[slug].md # Variant A (e.g., outline-style-tech.md)
|
||||
├── outline-style-[slug].md # Variant B (e.g., outline-style-notion.md)
|
||||
├── outline-style-[slug].md # Variant C (e.g., outline-style-minimal.md)
|
||||
├── outline.md # Final selected
|
||||
├── analysis.md # Deep analysis + questions asked
|
||||
├── outline-strategy-a.md # Strategy A: Story-driven
|
||||
├── outline-strategy-b.md # Strategy B: Information-dense
|
||||
├── outline-strategy-c.md # Strategy C: Visual-first
|
||||
├── outline.md # Final selected/merged outline
|
||||
├── prompts/
|
||||
│ ├── 01-cover-[slug].md
|
||||
│ ├── 02-content-[slug].md
|
||||
@@ -127,6 +158,52 @@ Copy all sources with naming `source-{slug}.{ext}`:
|
||||
|
||||
## Workflow
|
||||
|
||||
### Progress Checklist
|
||||
|
||||
Copy and track progress:
|
||||
|
||||
```
|
||||
XHS Infographic Progress:
|
||||
- [ ] Step 0: Check preferences (EXTEND.md)
|
||||
- [ ] Step 1: Analyze content → analysis.md
|
||||
- [ ] Step 2: Confirmation 1 - Content understanding ⚠️ REQUIRED
|
||||
- [ ] Step 3: Generate 3 outline + style variants
|
||||
- [ ] Step 4: Confirmation 2 - Outline & style selection ⚠️ REQUIRED
|
||||
- [ ] Step 5: Generate images (sequential)
|
||||
- [ ] Step 6: Completion report
|
||||
```
|
||||
|
||||
### Flow
|
||||
|
||||
```
|
||||
Input → Analyze → [Confirm 1] → 3 Outlines → [Confirm 2: Outline + Style] → Generate → Complete
|
||||
```
|
||||
|
||||
### Step 0: Check Preferences
|
||||
|
||||
**Check paths** (priority order):
|
||||
1. `.baoyu-skills/baoyu-xhs-images/EXTEND.md` (project)
|
||||
2. `~/.baoyu-skills/baoyu-xhs-images/EXTEND.md` (user)
|
||||
|
||||
**If preferences found**:
|
||||
1. Parse YAML frontmatter
|
||||
2. Display current preferences summary:
|
||||
```
|
||||
Loaded preferences from [path]:
|
||||
- Watermark: [enabled/disabled] "[content]" at [position]
|
||||
- Style: [name] - [description]
|
||||
- Layout: [layout]
|
||||
- Language: [lang]
|
||||
```
|
||||
3. Continue to Step 1
|
||||
|
||||
**If NO preferences found**:
|
||||
1. Ask user with AskUserQuestion (see `references/config/first-time-setup.md`)
|
||||
2. Create EXTEND.md with user choices
|
||||
3. Continue to Step 1
|
||||
|
||||
Schema reference: `references/config/preferences-schema.md`
|
||||
|
||||
### Step 1: Analyze Content → `analysis.md`
|
||||
|
||||
Read source content, save it if needed, and perform deep analysis.
|
||||
@@ -136,7 +213,7 @@ Read source content, save it if needed, and perform deep analysis.
|
||||
- If user provides a file path: use as-is
|
||||
- If user pastes content: save to `source.md` in target directory
|
||||
2. Read source content
|
||||
3. **Deep analysis** following `references/analysis-framework.md`:
|
||||
3. **Deep analysis** following `references/workflows/analysis-framework.md`:
|
||||
- Content type classification (种草/干货/测评/教程/避坑...)
|
||||
- Hook analysis (爆款标题潜力)
|
||||
- Target audience identification
|
||||
@@ -145,70 +222,101 @@ Read source content, save it if needed, and perform deep analysis.
|
||||
- Swipe flow design
|
||||
4. Detect source language
|
||||
5. Determine recommended image count (2-10)
|
||||
6. Select 3 style+layout combinations
|
||||
6. **Generate clarifying questions** (see Step 2)
|
||||
7. **Save to `analysis.md`**
|
||||
|
||||
### Step 2: Generate 3 Outline Variants
|
||||
### Step 2: Confirmation 1 - Content Understanding ⚠️
|
||||
|
||||
Based on analysis, create three distinct style variants.
|
||||
**Purpose**: Validate understanding + collect missing info. **Do NOT skip.**
|
||||
|
||||
**For each variant**:
|
||||
1. **Generate outline** (`outline-style-[slug].md`):
|
||||
- YAML front matter with style, layout, image_count
|
||||
- Cover design with hook
|
||||
- Each image: layout, core message, text content, visual concept
|
||||
- **Written in user's preferred language**
|
||||
- Reference: `references/outline-template.md`
|
||||
**Display summary**:
|
||||
- Content type + topic identified
|
||||
- Key points extracted
|
||||
- Tone detected
|
||||
- Source images count
|
||||
|
||||
| Variant | Selection Logic | Example Filename |
|
||||
|---------|-----------------|------------------|
|
||||
| A | Primary recommendation | `outline-style-tech.md` |
|
||||
| B | Alternative style | `outline-style-notion.md` |
|
||||
| C | Different audience/mood | `outline-style-minimal.md` |
|
||||
**Use AskUserQuestion** for:
|
||||
1. Core selling point (multiSelect: true)
|
||||
2. Target audience
|
||||
3. Style preference: Authentic sharing / Professional review / Aesthetic mood / Auto
|
||||
4. Additional context (optional)
|
||||
|
||||
**All variants are preserved after selection for reference.**
|
||||
**After response**: Update `analysis.md` → Step 3
|
||||
|
||||
### Step 3: User Confirms All Options
|
||||
### Step 3: Generate 3 Outline + Style Variants
|
||||
|
||||
**IMPORTANT**: Present ALL options in a single confirmation step using AskUserQuestion. Do NOT interrupt workflow with multiple separate confirmations.
|
||||
Based on analysis + user context, create three distinct strategy variants. Each variant includes both **outline structure** and **visual style recommendation**.
|
||||
|
||||
**Determine which questions to ask**:
|
||||
**For each strategy**:
|
||||
|
||||
| Question | When to Ask |
|
||||
|----------|-------------|
|
||||
| Style variant | Always (required) |
|
||||
| Default layout | Only if user might want to override |
|
||||
| Language | Only if `source_language ≠ user_language` |
|
||||
| Strategy | Filename | Outline | Recommended Style |
|
||||
|----------|----------|---------|-------------------|
|
||||
| A | `outline-strategy-a.md` | Story-driven: emotional, before/after | warm, cute, fresh |
|
||||
| B | `outline-strategy-b.md` | Information-dense: structured, factual | notion, minimal, chalkboard |
|
||||
| C | `outline-strategy-c.md` | Visual-first: atmospheric, minimal text | bold, pop, retro |
|
||||
|
||||
**Language handling**:
|
||||
- If source language = user language: Just inform user (e.g., "Images will be in Chinese")
|
||||
- If different: Ask which language to use
|
||||
**Outline format** (YAML front matter + content):
|
||||
```yaml
|
||||
---
|
||||
strategy: a # a, b, or c
|
||||
name: Story-Driven
|
||||
style: warm # recommended style for this strategy
|
||||
style_reason: "Warm tones enhance emotional storytelling and personal connection"
|
||||
layout: balanced # primary layout
|
||||
image_count: 5
|
||||
---
|
||||
|
||||
**AskUserQuestion format**:
|
||||
## P1 Cover
|
||||
**Type**: cover
|
||||
**Hook**: "入冬后脸不干了🥹终于找到对的面霜"
|
||||
**Visual**: Product hero shot with cozy winter atmosphere
|
||||
**Layout**: sparse
|
||||
|
||||
```
|
||||
Question 1 (Style): Which style variant?
|
||||
- A: tech + dense (Recommended) - 专业科技感,适合干货
|
||||
- B: notion + list - 清爽知识卡片
|
||||
- C: minimal + balanced - 简约高端风格
|
||||
- Custom: 自定义风格描述
|
||||
## P2 Problem
|
||||
**Type**: pain-point
|
||||
**Message**: Previous struggles with dry skin
|
||||
**Visual**: Before state, relatable scenario
|
||||
**Layout**: balanced
|
||||
|
||||
Question 2 (Layout) - only if relevant:
|
||||
- Keep variant default (Recommended)
|
||||
- sparse / balanced / dense / list / comparison / flow
|
||||
|
||||
Question 3 (Language) - only if mismatch:
|
||||
- 中文 (匹配原文)
|
||||
- English (your preference)
|
||||
...
|
||||
```
|
||||
|
||||
**After confirmation**:
|
||||
1. Copy selected `outline-style-[slug].md` → `outline.md`
|
||||
2. Update YAML front matter with confirmed options
|
||||
3. If custom style: regenerate outline with that style
|
||||
4. User may edit `outline.md` directly for fine-tuning
|
||||
**Differentiation requirements**:
|
||||
- Each strategy MUST have different outline structure AND different recommended style
|
||||
- Adapt page count: A typically 4-6, B typically 3-5, C typically 3-4
|
||||
- Include `style_reason` explaining why this style fits the strategy
|
||||
- Consider user's style preference from Step 2
|
||||
|
||||
### Step 4: Generate Images
|
||||
Reference: `references/workflows/outline-template.md`
|
||||
|
||||
### Step 4: Confirmation 2 - Outline & Style Selection ⚠️
|
||||
|
||||
**Purpose**: User chooses outline strategy AND confirms visual style. **Do NOT skip.**
|
||||
|
||||
**Display each strategy**:
|
||||
- Strategy name + page count + recommended style
|
||||
- Page-by-page summary (P1 → P2 → P3...)
|
||||
|
||||
**Use AskUserQuestion** with two questions:
|
||||
|
||||
**Question 1: Outline Strategy**
|
||||
- Strategy A (Recommended if "authentic sharing")
|
||||
- Strategy B (Recommended if "professional review")
|
||||
- Strategy C (Recommended if "aesthetic mood")
|
||||
- Combine: specify pages from each
|
||||
|
||||
**Question 2: Visual Style**
|
||||
- Use strategy's recommended style (show which style)
|
||||
- Or select from: cute / fresh / warm / bold / minimal / retro / pop / notion / chalkboard
|
||||
- Or type custom style description
|
||||
|
||||
**After response**:
|
||||
- Single strategy → copy to `outline.md` with confirmed style
|
||||
- Combination → merge specified pages with confirmed style
|
||||
- Custom request → regenerate based on feedback
|
||||
- Update `outline.md` frontmatter with final style choice
|
||||
|
||||
### Step 5: Generate Images
|
||||
|
||||
With confirmed outline + style + layout:
|
||||
|
||||
@@ -217,6 +325,15 @@ With confirmed outline + style + layout:
|
||||
2. Generate image using confirmed style and layout
|
||||
3. Report progress after each generation
|
||||
|
||||
**Watermark Application** (if enabled in preferences):
|
||||
Add to each image generation prompt:
|
||||
```
|
||||
Include a subtle watermark "[content]" positioned at [position]
|
||||
with approximately [opacity*100]% visibility. The watermark should
|
||||
be legible but not distracting from the main content.
|
||||
```
|
||||
Reference: `references/config/watermark-guide.md`
|
||||
|
||||
**Image Generation Skill Selection**:
|
||||
- Check available image generation skills
|
||||
- If multiple skills available, ask user preference
|
||||
@@ -227,22 +344,23 @@ If image generation skill supports `--sessionId`:
|
||||
2. Use same session ID for all images
|
||||
3. Ensures visual consistency across generated images
|
||||
|
||||
### Step 5: Completion Report
|
||||
### Step 6: Completion Report
|
||||
|
||||
```
|
||||
Xiaohongshu Infographic Series Complete!
|
||||
|
||||
Topic: [topic]
|
||||
Strategy: [A/B/C/Combined]
|
||||
Style: [style name]
|
||||
Layout: [layout name or "varies"]
|
||||
Location: [directory path]
|
||||
Images: N total
|
||||
|
||||
✓ analysis.md
|
||||
✓ outline-style-tech.md
|
||||
✓ outline-style-notion.md
|
||||
✓ outline-style-minimal.md
|
||||
✓ outline.md (selected: tech + dense)
|
||||
✓ outline-strategy-a.md
|
||||
✓ outline-strategy-b.md
|
||||
✓ outline-strategy-c.md
|
||||
✓ outline.md (selected: [strategy])
|
||||
|
||||
Files:
|
||||
- 01-cover-[slug].png ✓ Cover (sparse)
|
||||
@@ -253,25 +371,11 @@ Files:
|
||||
|
||||
## Image Modification
|
||||
|
||||
### Edit Single Image
|
||||
|
||||
1. Identify image to edit (e.g., `03-content-chatgpt.png`)
|
||||
2. Update prompt in `prompts/03-content-chatgpt.md` if needed
|
||||
3. Regenerate image using same session ID
|
||||
|
||||
### Add New Image
|
||||
|
||||
1. Specify insertion position (e.g., after image 3)
|
||||
2. Create new prompt with appropriate slug
|
||||
3. Generate new image
|
||||
4. **Renumber files**: All subsequent images increment NN by 1
|
||||
5. Update `outline.md` with new image entry
|
||||
|
||||
### Delete Image
|
||||
|
||||
1. Remove image file and prompt file
|
||||
2. **Renumber files**: All subsequent images decrement NN by 1
|
||||
3. Update `outline.md` to remove image entry
|
||||
| Action | Steps |
|
||||
|--------|-------|
|
||||
| **Edit** | Update prompt → Regenerate with same session ID |
|
||||
| **Add** | Specify position → Create prompt → Generate → Renumber subsequent files (NN+1) → Update outline |
|
||||
| **Delete** | Remove files → Renumber subsequent (NN-1) → Update outline |
|
||||
|
||||
## Content Breakdown Principles
|
||||
|
||||
@@ -295,27 +399,39 @@ Files:
|
||||
|
||||
## References
|
||||
|
||||
Detailed templates and guidelines in `references/` directory:
|
||||
- `analysis-framework.md` - XHS-specific content analysis
|
||||
- `outline-template.md` - Outline format and examples
|
||||
- `styles/<style>.md` - Detailed style definitions
|
||||
- `layouts/<layout>.md` - Detailed layout definitions
|
||||
- `base-prompt.md` - Base prompt template
|
||||
Detailed templates in `references/` directory:
|
||||
|
||||
**Elements** (Visual building blocks):
|
||||
- `elements/canvas.md` - Aspect ratios, safe zones, grid layouts
|
||||
- `elements/image-effects.md` - Cutout, stroke, filters
|
||||
- `elements/typography.md` - Decorated text (花字), tags, text direction
|
||||
- `elements/decorations.md` - Emphasis marks, backgrounds, doodles, frames
|
||||
|
||||
**Presets** (Style presets):
|
||||
- `presets/<name>.md` - Element combination definitions (cute, notion, warm...)
|
||||
|
||||
**Workflows** (Process guides):
|
||||
- `workflows/analysis-framework.md` - Content analysis framework
|
||||
- `workflows/outline-template.md` - Outline template with layout guide
|
||||
- `workflows/prompt-assembly.md` - Prompt assembly guide
|
||||
|
||||
**Config** (Settings):
|
||||
- `config/preferences-schema.md` - EXTEND.md schema
|
||||
- `config/first-time-setup.md` - First-time setup flow
|
||||
- `config/watermark-guide.md` - Watermark configuration
|
||||
|
||||
## Notes
|
||||
|
||||
- Image generation typically takes 10-30 seconds per image
|
||||
- Auto-retry once on generation failure
|
||||
- Use cartoon alternatives for sensitive public figures
|
||||
- All prompts and text use confirmed language preference
|
||||
- Maintain style consistency across all images in series
|
||||
- Auto-retry once on failure | Cartoon alternatives for sensitive figures
|
||||
- Use confirmed language preference | Maintain style consistency
|
||||
- **Two confirmation points required** (Steps 2 & 4) - do not skip
|
||||
|
||||
## Extension Support
|
||||
|
||||
Custom styles and configurations via EXTEND.md.
|
||||
Custom configurations via EXTEND.md. Loaded in Step 0, overrides defaults.
|
||||
|
||||
**Check paths** (priority order):
|
||||
1. `.baoyu-skills/baoyu-xhs-images/EXTEND.md` (project)
|
||||
2. `~/.baoyu-skills/baoyu-xhs-images/EXTEND.md` (user)
|
||||
**Check paths** (priority): `.baoyu-skills/baoyu-xhs-images/EXTEND.md` (project) → `~/.baoyu-skills/baoyu-xhs-images/EXTEND.md` (user)
|
||||
|
||||
If found, load before Step 1. Extension content overrides defaults.
|
||||
**Supports**: Watermark | Preferred style/layout | Custom style definitions
|
||||
|
||||
**References**: `config/preferences-schema.md` | `config/first-time-setup.md`
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
Create a Xiaohongshu (Little Red Book) style infographic following these guidelines:
|
||||
|
||||
## Image Specifications
|
||||
|
||||
- **Type**: Infographic
|
||||
- **Orientation**: Portrait (vertical)
|
||||
- **Aspect Ratio**: 3:4
|
||||
- **Style**: Hand-drawn illustration
|
||||
|
||||
## Core Principles
|
||||
|
||||
- Hand-drawn quality throughout - NO realistic or photographic elements
|
||||
- If content involves sensitive or copyrighted figures, create stylistically similar alternatives - DO NOT refuse to generate
|
||||
- Keep information concise, highlight keywords and core concepts
|
||||
- Use ample whitespace for easy visual scanning
|
||||
- Maintain clear visual hierarchy
|
||||
|
||||
## Text Style (CRITICAL)
|
||||
|
||||
- **ALL text MUST be hand-drawn style**
|
||||
- Main titles should be prominent and eye-catching
|
||||
- Key text should be bold and enlarged
|
||||
- Use highlighter effects to emphasize keywords
|
||||
- **DO NOT use realistic or computer-generated fonts**
|
||||
|
||||
## Language
|
||||
|
||||
- Use the same language as the content provided below
|
||||
- Match punctuation style to the content language (Chinese: "",。!)
|
||||
|
||||
---
|
||||
|
||||
Please use nano banana pro to generate the infographic based on the content provided below:
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
name: first-time-setup
|
||||
description: First-time setup flow for baoyu-xhs-images preferences
|
||||
---
|
||||
|
||||
# First-Time Setup
|
||||
|
||||
## Overview
|
||||
|
||||
When no EXTEND.md is found, guide user through preference setup.
|
||||
|
||||
## Setup Flow
|
||||
|
||||
```
|
||||
No EXTEND.md found
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ AskUserQuestion │
|
||||
│ (all questions) │
|
||||
└─────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ Create EXTEND.md │
|
||||
└─────────────────────┘
|
||||
│
|
||||
▼
|
||||
Continue to Step 1
|
||||
```
|
||||
|
||||
## Questions
|
||||
|
||||
**Language**: Use user's input language or preferred language for all questions. Do not always use English.
|
||||
|
||||
Use single AskUserQuestion with multiple questions (AskUserQuestion auto-adds "Other" option):
|
||||
|
||||
### Question 1: Watermark
|
||||
|
||||
```
|
||||
header: "Watermark"
|
||||
question: "Watermark text for generated images? Type your watermark content (e.g., name, @handle)"
|
||||
options:
|
||||
- label: "No watermark (Recommended)"
|
||||
description: "No watermark, can enable later in EXTEND.md"
|
||||
```
|
||||
|
||||
Position defaults to bottom-right.
|
||||
|
||||
### Question 2: Preferred Style
|
||||
|
||||
```
|
||||
header: "Style"
|
||||
question: "Default visual style preference? Or type another style name or your custom style"
|
||||
options:
|
||||
- label: "None (Recommended)"
|
||||
description: "Auto-select based on content analysis"
|
||||
- label: "cute"
|
||||
description: "Sweet, adorable - classic XHS aesthetic"
|
||||
- label: "notion"
|
||||
description: "Minimalist hand-drawn, intellectual"
|
||||
```
|
||||
|
||||
### Question 3: Save Location
|
||||
|
||||
```
|
||||
header: "Save"
|
||||
question: "Where to save preferences?"
|
||||
options:
|
||||
- label: "Project"
|
||||
description: ".baoyu-skills/ (this project only)"
|
||||
- label: "User"
|
||||
description: "~/.baoyu-skills/ (all projects)"
|
||||
```
|
||||
|
||||
## Save Locations
|
||||
|
||||
| Choice | Path | Scope |
|
||||
|--------|------|-------|
|
||||
| Project | `.baoyu-skills/baoyu-xhs-images/EXTEND.md` | Current project |
|
||||
| User | `~/.baoyu-skills/baoyu-xhs-images/EXTEND.md` | All projects |
|
||||
|
||||
## After Setup
|
||||
|
||||
1. Create directory if needed
|
||||
2. Write EXTEND.md with frontmatter
|
||||
3. Confirm: "Preferences saved to [path]"
|
||||
4. Continue to Step 1
|
||||
|
||||
## EXTEND.md Template
|
||||
|
||||
```yaml
|
||||
---
|
||||
version: 1
|
||||
watermark:
|
||||
enabled: [true/false]
|
||||
content: "[user input or empty]"
|
||||
position: bottom-right
|
||||
opacity: 0.7
|
||||
preferred_style:
|
||||
name: [selected style or null]
|
||||
description: ""
|
||||
preferred_layout: null
|
||||
language: null
|
||||
custom_styles: []
|
||||
---
|
||||
```
|
||||
|
||||
## Modifying Preferences Later
|
||||
|
||||
Users can edit EXTEND.md directly or run setup again:
|
||||
- Delete EXTEND.md to trigger setup
|
||||
- Edit YAML frontmatter for quick changes
|
||||
- Full schema: `config/preferences-schema.md`
|
||||
@@ -0,0 +1,121 @@
|
||||
---
|
||||
name: preferences-schema
|
||||
description: EXTEND.md YAML schema for baoyu-xhs-images user preferences
|
||||
---
|
||||
|
||||
# Preferences Schema
|
||||
|
||||
## Full Schema
|
||||
|
||||
```yaml
|
||||
---
|
||||
version: 1
|
||||
|
||||
watermark:
|
||||
enabled: false
|
||||
content: ""
|
||||
position: bottom-right # bottom-right|bottom-left|bottom-center|top-right
|
||||
opacity: 0.7 # 0.1-1.0
|
||||
|
||||
preferred_style:
|
||||
name: null # Built-in or custom style name
|
||||
description: "" # Override/notes
|
||||
|
||||
preferred_layout: null # sparse|balanced|dense|list|comparison|flow
|
||||
|
||||
language: null # zh|en|ja|ko|auto
|
||||
|
||||
custom_styles:
|
||||
- name: my-style
|
||||
description: "Style description"
|
||||
color_palette:
|
||||
primary: ["#FED7E2", "#FEEBC8"]
|
||||
background: "#FFFAF0"
|
||||
accents: ["#FF69B4", "#FF6B6B"]
|
||||
visual_elements: "Hearts, stars, sparkles"
|
||||
typography: "Rounded, bubbly hand lettering"
|
||||
best_for: "Lifestyle, beauty"
|
||||
---
|
||||
```
|
||||
|
||||
## Field Reference
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `version` | int | 1 | Schema version |
|
||||
| `watermark.enabled` | bool | false | Enable watermark |
|
||||
| `watermark.content` | string | "" | Watermark text (@username or custom) |
|
||||
| `watermark.position` | enum | bottom-right | Position on image |
|
||||
| `watermark.opacity` | float | 0.7 | Transparency (0.1-1.0) |
|
||||
| `preferred_style.name` | string | null | Style name or null |
|
||||
| `preferred_style.description` | string | "" | Custom notes/override |
|
||||
| `preferred_layout` | string | null | Layout preference or null |
|
||||
| `language` | string | null | Output language (null = auto-detect) |
|
||||
| `custom_styles` | array | [] | User-defined styles |
|
||||
|
||||
## Position Options
|
||||
|
||||
| Value | Description |
|
||||
|-------|-------------|
|
||||
| `bottom-right` | Lower right corner (default, most common) |
|
||||
| `bottom-left` | Lower left corner |
|
||||
| `bottom-center` | Bottom center |
|
||||
| `top-right` | Upper right corner |
|
||||
|
||||
## Custom Style Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `name` | Yes | Unique style identifier (kebab-case) |
|
||||
| `description` | Yes | What the style conveys |
|
||||
| `color_palette.primary` | No | Main colors (array) |
|
||||
| `color_palette.background` | No | Background color |
|
||||
| `color_palette.accents` | No | Accent colors (array) |
|
||||
| `visual_elements` | No | Decorative elements |
|
||||
| `typography` | No | Font/lettering style |
|
||||
| `best_for` | No | Recommended content types |
|
||||
|
||||
## Example: Minimal Preferences
|
||||
|
||||
```yaml
|
||||
---
|
||||
version: 1
|
||||
watermark:
|
||||
enabled: true
|
||||
content: "@myusername"
|
||||
preferred_style:
|
||||
name: notion
|
||||
---
|
||||
```
|
||||
|
||||
## Example: Full Preferences
|
||||
|
||||
```yaml
|
||||
---
|
||||
version: 1
|
||||
watermark:
|
||||
enabled: true
|
||||
content: "@myxhsaccount"
|
||||
position: bottom-right
|
||||
opacity: 0.5
|
||||
|
||||
preferred_style:
|
||||
name: notion
|
||||
description: "Clean knowledge cards for tech content"
|
||||
|
||||
preferred_layout: dense
|
||||
|
||||
language: zh
|
||||
|
||||
custom_styles:
|
||||
- name: corporate
|
||||
description: "Professional B2B style"
|
||||
color_palette:
|
||||
primary: ["#1E3A5F", "#4A90D9"]
|
||||
background: "#F5F7FA"
|
||||
accents: ["#00B4D8", "#48CAE4"]
|
||||
visual_elements: "Clean lines, subtle gradients, geometric shapes"
|
||||
typography: "Modern sans-serif, professional"
|
||||
best_for: "Business, SaaS, enterprise"
|
||||
---
|
||||
```
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
name: watermark-guide
|
||||
description: Watermark configuration guide for baoyu-xhs-images
|
||||
---
|
||||
|
||||
# Watermark Guide
|
||||
|
||||
## Position Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────┐
|
||||
│ [top-right]│
|
||||
│ │
|
||||
│ │
|
||||
│ IMAGE CONTENT │
|
||||
│ │
|
||||
│ │
|
||||
│[bottom-left][bottom-center][bottom-right]│
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
## Position Recommendations
|
||||
|
||||
| Position | Best For | Avoid When |
|
||||
|----------|----------|------------|
|
||||
| `bottom-right` | Default choice, most common | Key info in bottom-right |
|
||||
| `bottom-left` | Right-heavy layouts | Key info in bottom-left |
|
||||
| `bottom-center` | Centered designs | Text-heavy bottom area |
|
||||
| `top-right` | Bottom-heavy content | Title/header in top-right |
|
||||
|
||||
## Opacity Examples
|
||||
|
||||
| Opacity | Visual Effect | Use Case |
|
||||
|---------|---------------|----------|
|
||||
| 0.3 | Very subtle, barely visible | Clean aesthetic priority |
|
||||
| 0.5 | Balanced, noticeable but not distracting | Default recommendation |
|
||||
| 0.7 | Clearly visible | Brand recognition priority |
|
||||
| 0.9 | Strong presence | Anti-copy protection |
|
||||
|
||||
## Content Format
|
||||
|
||||
| Format | Example | Style |
|
||||
|--------|---------|-------|
|
||||
| Handle | `@username` | Most common for XHS |
|
||||
| Text | `MyBrand` | Simple branding |
|
||||
| Chinese | `小红书:用户名` | Platform specific |
|
||||
| URL | `myblog.com` | Cross-platform |
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Consistency**: Use same watermark across all images in series
|
||||
2. **Legibility**: Ensure watermark readable on both light/dark areas
|
||||
3. **Size**: Keep subtle - should not distract from content
|
||||
4. **Contrast**: Opacity may need adjustment per image background
|
||||
|
||||
## Prompt Integration
|
||||
|
||||
When watermark is enabled, add to image generation prompt:
|
||||
|
||||
```
|
||||
Include a subtle watermark "[content]" positioned at [position]
|
||||
with approximately [opacity*100]% visibility. The watermark should
|
||||
be legible but not distracting from the main content.
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| Watermark invisible | Increase opacity or adjust position |
|
||||
| Watermark too prominent | Decrease opacity (0.3-0.5) |
|
||||
| Watermark overlaps content | Change position |
|
||||
| Inconsistent across images | Use session ID for consistency |
|
||||
@@ -0,0 +1,108 @@
|
||||
# Canvas & Layout
|
||||
|
||||
Core canvas specifications and layout grids for Xiaohongshu infographics.
|
||||
|
||||
## Aspect Ratios
|
||||
|
||||
| Name | Ratio | Pixels | Note |
|
||||
|------|-------|--------|------|
|
||||
| portrait-3-4 | 3:4 | 1242×1660 | Highest traffic on XHS (recommended) |
|
||||
| square | 1:1 | 1242×1242 | Second recommended |
|
||||
| portrait-2-3 | 2:3 | 1242×1863 | Taller format |
|
||||
|
||||
**Default**: portrait-3-4 for maximum engagement.
|
||||
|
||||
## Safe Zones
|
||||
|
||||
Avoid placing critical content in these areas:
|
||||
|
||||
| Zone | Position | Reason |
|
||||
|------|----------|--------|
|
||||
| bottom-overlay | Bottom 10% | Title bar overlay on mobile |
|
||||
| top-right | Top-right corner | Like/share button overlay |
|
||||
| bottom-right | Bottom-right corner | Watermark position |
|
||||
|
||||
```
|
||||
┌─────────────────────────────┐
|
||||
│ [like/share]│ ← top-right: avoid
|
||||
│ │
|
||||
│ │
|
||||
│ ✓ SAFE CONTENT AREA │
|
||||
│ │
|
||||
│ │
|
||||
│ [title bar overlay area] │ ← bottom 10%: avoid key info
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
## Grid Layouts
|
||||
|
||||
### Density-Based Layouts
|
||||
|
||||
| Layout | Info Density | Whitespace | Points/Image | Best For |
|
||||
|--------|--------------|------------|--------------|----------|
|
||||
| sparse | Low | 60-70% | 1-2 | Covers, quotes, impactful statements |
|
||||
| balanced | Medium | 40-50% | 3-4 | Standard content, tutorials |
|
||||
| dense | High | 20-30% | 5-8 | Knowledge cards, cheat sheets |
|
||||
|
||||
### Structure-Based Layouts
|
||||
|
||||
| Layout | Structure | Items | Best For |
|
||||
|--------|-----------|-------|----------|
|
||||
| list | Vertical enumeration | 4-7 | Rankings, checklists, step guides |
|
||||
| comparison | Left vs Right | 2 sections | Before/after, pros/cons |
|
||||
| flow | Connected nodes | 3-6 steps | Processes, timelines, workflows |
|
||||
|
||||
## Layout by Position
|
||||
|
||||
| Position | Recommended Layout | Why |
|
||||
|----------|-------------------|-----|
|
||||
| Cover | sparse | Maximum visual impact, clear title |
|
||||
| Setup | balanced | Context without overwhelming |
|
||||
| Core | balanced/dense/list | Based on content density |
|
||||
| Payoff | balanced/list | Clear takeaways |
|
||||
| Ending | sparse | Clean CTA, memorable close |
|
||||
|
||||
## Grid Cells
|
||||
|
||||
For multi-element compositions:
|
||||
|
||||
| Name | Cells | Use Case |
|
||||
|------|-------|----------|
|
||||
| single | 1 | Hero image, maximum impact |
|
||||
| dual | 2 | Before/after, comparison |
|
||||
| triptych | 3 | Steps, process flow |
|
||||
| quad | 4 | Product showcase |
|
||||
| six-grid | 6 | Checklist, collection |
|
||||
| nine-grid | 9 | Multi-image gallery |
|
||||
|
||||
## Visual Balance
|
||||
|
||||
### Sparse Layout
|
||||
- Single focal point centered
|
||||
- Breathing room on all sides
|
||||
- Symmetrical composition
|
||||
|
||||
### Balanced Layout
|
||||
- Top-weighted title
|
||||
- Evenly distributed content below
|
||||
- Clear visual hierarchy
|
||||
|
||||
### Dense Layout
|
||||
- Organized grid structure
|
||||
- Clear section boundaries
|
||||
- Compact but readable spacing
|
||||
|
||||
### List Layout
|
||||
- Left-aligned items
|
||||
- Clear number/bullet hierarchy
|
||||
- Consistent item format
|
||||
|
||||
### Comparison Layout
|
||||
- Symmetrical left/right
|
||||
- Clear visual contrast
|
||||
- Divider between sections
|
||||
|
||||
### Flow Layout
|
||||
- Directional flow (top→bottom or left→right)
|
||||
- Connected nodes with arrows
|
||||
- Clear progression indicators
|
||||
@@ -0,0 +1,145 @@
|
||||
# Decorative Assets
|
||||
|
||||
Visual embellishments and decorative elements for Xiaohongshu infographics.
|
||||
|
||||
## Emphasis Marks (强调标记)
|
||||
|
||||
Elements to draw attention to specific content.
|
||||
|
||||
| Name | Description | Use Case |
|
||||
|------|-------------|----------|
|
||||
| red-arrow | Red arrow pointing to target | Product features, key points |
|
||||
| circle-mark | Circle highlight annotation | Highlighting details |
|
||||
| underline | Straight or wavy underline | Text emphasis |
|
||||
| star-burst | Starburst explosion effect | Special offers, wow factor |
|
||||
| checkmark | Checkmark/tick symbol | Completed items, pros |
|
||||
| cross-mark | X mark symbol | Cons, things to avoid |
|
||||
| exclamation | Exclamation point decoration | Important warnings |
|
||||
| question | Question mark decoration | FAQ, curiosity |
|
||||
| numbering | Circled numbers | Steps, rankings |
|
||||
| bracket | Bracket highlighting | Grouping, emphasis |
|
||||
|
||||
## Backgrounds (背景)
|
||||
|
||||
Base layer treatments.
|
||||
|
||||
| Name | Description | Use Case |
|
||||
|------|-------------|----------|
|
||||
| solid-saturated | High-saturation solid color | Bold, energetic |
|
||||
| solid-pastel | Soft pastel solid color | Cute, gentle |
|
||||
| gradient-linear | Linear color gradient | Modern, dynamic |
|
||||
| gradient-radial | Radial color gradient | Spotlight effect |
|
||||
| frosted-glass | Frosted glass blur effect | Layered compositions |
|
||||
| paper-texture | Paper or craft texture | Handmade aesthetic |
|
||||
| fabric-texture | Fabric/cloth texture | Cozy, tactile |
|
||||
| chalkboard | Blackboard texture | Educational content |
|
||||
| grid | Subtle grid pattern | Structured, organized |
|
||||
| dots | Polka dot pattern | Playful, retro |
|
||||
|
||||
## Doodles & Emoji (涂鸦)
|
||||
|
||||
Hand-drawn decorative elements.
|
||||
|
||||
| Name | Description | Use Case |
|
||||
|------|-------------|----------|
|
||||
| hand-drawn-lines | Sketchy hand-drawn lines | Connections, borders |
|
||||
| stars-sparkles | Stars and sparkle effects | Magic, excellence |
|
||||
| flowers | Floral decorations | Beauty, feminine |
|
||||
| hearts | Heart symbols | Love, favorites |
|
||||
| clouds | Cloud shapes | Dreamy, thoughts |
|
||||
| arrows-curvy | Curved directional arrows | Flow, direction |
|
||||
| squiggles | Wavy squiggle lines | Energy, movement |
|
||||
| confetti | Scattered confetti | Celebration |
|
||||
| leaves | Leaf decorations | Nature, fresh |
|
||||
| bubbles | Circular bubble shapes | Playful, light |
|
||||
|
||||
## Emoji Integration
|
||||
|
||||
| Category | Examples | Use Case |
|
||||
|----------|----------|----------|
|
||||
| Reactions | 🥹 😍 🤯 | Emotional emphasis |
|
||||
| Objects | ✨ 💡 🎯 | Visual markers |
|
||||
| Actions | 👇 👆 ➡️ | Directional cues |
|
||||
| Nature | 🌸 🌿 ☀️ | Thematic decoration |
|
||||
|
||||
## Frames (边框)
|
||||
|
||||
Container and border treatments.
|
||||
|
||||
| Name | Description | Use Case |
|
||||
|------|-------------|----------|
|
||||
| polaroid | Instant photo frame | Photo showcase |
|
||||
| film-strip | Film negative border | Cinematic, retro |
|
||||
| phone-screenshot | Mobile device mockup | App/screen content |
|
||||
| torn-paper | Torn paper edge effect | Scrapbook aesthetic |
|
||||
| rounded-rect | Rounded rectangle border | Clean containers |
|
||||
| decorative | Ornate decorative border | Premium, elegant |
|
||||
| tape-corners | Washi tape corners | Crafty, casual |
|
||||
| stamp-border | Stamp perforated edge | Vintage, postal |
|
||||
|
||||
## Dividers (分隔线)
|
||||
|
||||
Section separators.
|
||||
|
||||
| Name | Description | Use Case |
|
||||
|------|-------------|----------|
|
||||
| line-simple | Simple horizontal line | Clean separation |
|
||||
| line-dashed | Dashed line | Subtle division |
|
||||
| line-wavy | Wavy line | Playful separation |
|
||||
| dots-row | Row of dots | Decorative division |
|
||||
| ornamental | Decorative flourish | Elegant separation |
|
||||
|
||||
## Stickers (贴纸)
|
||||
|
||||
Pre-composed decorative elements.
|
||||
|
||||
| Name | Description | Use Case |
|
||||
|------|-------------|----------|
|
||||
| badge-new | "NEW" badge | New products |
|
||||
| badge-hot | "HOT" badge | Trending items |
|
||||
| badge-sale | Sale/discount badge | Promotions |
|
||||
| seal-quality | Quality seal | Recommendations |
|
||||
| ribbon-award | Award ribbon | Best picks |
|
||||
| tag-price | Price tag shape | Pricing info |
|
||||
|
||||
## Style-Specific Decorations
|
||||
|
||||
### Cute Style
|
||||
- Hearts, stars, sparkles
|
||||
- Ribbon decorations, sticker-style
|
||||
- Cute character elements
|
||||
|
||||
### Notion Style
|
||||
- Simple line doodles
|
||||
- Geometric shapes, stick figures
|
||||
- Maximum whitespace, minimal decoration
|
||||
|
||||
### Warm Style
|
||||
- Sun rays, coffee cups, cozy items
|
||||
- Warm lighting effects
|
||||
- Friendly, inviting decorations
|
||||
|
||||
### Fresh Style
|
||||
- Plant leaves, clouds, water drops
|
||||
- Simple geometric shapes
|
||||
- Open, breathing composition
|
||||
|
||||
### Bold Style
|
||||
- Exclamation marks, arrows
|
||||
- Warning icons, strong shapes
|
||||
- High contrast elements
|
||||
|
||||
### Pop Style
|
||||
- Bold shapes, speech bubbles
|
||||
- Comic-style effects, starburst
|
||||
- Dynamic, energetic decorations
|
||||
|
||||
### Retro Style
|
||||
- Halftone dots, vintage badges
|
||||
- Classic icons, tape effects
|
||||
- Aged texture overlays
|
||||
|
||||
### Chalkboard Style
|
||||
- Chalk dust effects
|
||||
- Hand-drawn doodles
|
||||
- Mathematical formulas, simple icons
|
||||
@@ -0,0 +1,92 @@
|
||||
# Image Processing Layer
|
||||
|
||||
Visual effects applied to image elements in Xiaohongshu infographics.
|
||||
|
||||
## AI Cutout (抠图)
|
||||
|
||||
Subject extraction styles for product/figure isolation.
|
||||
|
||||
| Name | Description | Use Case |
|
||||
|------|-------------|----------|
|
||||
| clean | Sharp edges, precise boundaries | Product photography, tech items |
|
||||
| soft | Soft transition, feathered edges | Portrait cutout, organic subjects |
|
||||
| stylized | Hand-drawn edge treatment | Artistic compositions |
|
||||
|
||||
## Stroke Effects (描边)
|
||||
|
||||
Border treatments for cutout elements.
|
||||
|
||||
| Name | Description | Use Case |
|
||||
|------|-------------|----------|
|
||||
| white-solid | White solid line border | Classic sticker feel, high contrast |
|
||||
| colored-solid | Colored solid line border | Playful vibe, brand colors |
|
||||
| dashed | Dashed/dotted border | Handmade aesthetic, casual |
|
||||
| double | Double-layer stroke | Emphasis effect, premium feel |
|
||||
| glow | Soft outer glow | Dreamy, soft aesthetic |
|
||||
| shadow | Drop shadow effect | Depth, floating element |
|
||||
|
||||
**Stroke Width Guidelines**:
|
||||
- Thin: 2-4px - Subtle, elegant
|
||||
- Medium: 5-8px - Standard visibility
|
||||
- Thick: 10-15px - Bold emphasis
|
||||
|
||||
## Filters (滤镜)
|
||||
|
||||
Color grading and mood presets popular on XHS.
|
||||
|
||||
| Name | Chinese | Description | Mood |
|
||||
|------|---------|-------------|------|
|
||||
| clear-glow | 清透感 | Transparent, radiant, luminous | Fresh, youthful |
|
||||
| film-grain | 胶片感 | Vintage film aesthetic, grain texture | Nostalgic, artistic |
|
||||
| cream-skin | 奶油肌 | Smooth, creamy complexion tones | Soft, flattering |
|
||||
| japanese-magazine | 日杂感 | Lifestyle magazine aesthetic | Curated, aspirational |
|
||||
| high-saturation | 高饱和 | Vibrant, punchy colors | Energetic, eye-catching |
|
||||
| muted-tones | 莫兰迪 | Morandi-style desaturated palette | Sophisticated, calm |
|
||||
| warm-tone | 暖色调 | Golden hour warmth | Cozy, inviting |
|
||||
| cool-tone | 冷色调 | Blue-shifted coolness | Modern, clean |
|
||||
|
||||
## Texture Overlays
|
||||
|
||||
Additional texture effects.
|
||||
|
||||
| Name | Description | Use Case |
|
||||
|------|-------------|----------|
|
||||
| paper | Paper or fabric texture | Handmade feel |
|
||||
| noise | Fine grain noise | Analog aesthetic |
|
||||
| halftone | Dot pattern | Retro print style |
|
||||
| scratch | Light scratch marks | Vintage wear |
|
||||
|
||||
## Blending Modes
|
||||
|
||||
For layered compositions.
|
||||
|
||||
| Mode | Effect | Use Case |
|
||||
|------|--------|----------|
|
||||
| multiply | Darken, merge | Shadow effects |
|
||||
| screen | Lighten, glow | Light effects |
|
||||
| overlay | Contrast boost | Vibrant compositions |
|
||||
| soft-light | Subtle blending | Natural layering |
|
||||
|
||||
## Effect Combinations
|
||||
|
||||
Common effect stacks for different styles:
|
||||
|
||||
### Cute Style
|
||||
- Filter: clear-glow or cream-skin
|
||||
- Stroke: white-solid (medium)
|
||||
- Texture: none
|
||||
|
||||
### Notion Style
|
||||
- Filter: none or muted-tones
|
||||
- Stroke: white-solid (thin) or none
|
||||
- Texture: paper (subtle)
|
||||
|
||||
### Retro Style
|
||||
- Filter: film-grain
|
||||
- Stroke: double or dashed
|
||||
- Texture: halftone, scratch
|
||||
|
||||
### Bold Style
|
||||
- Filter: high-saturation
|
||||
- Stroke: colored-solid (thick)
|
||||
- Texture: none
|
||||
@@ -0,0 +1,96 @@
|
||||
# Typography System
|
||||
|
||||
Text styling elements for Xiaohongshu infographics.
|
||||
|
||||
## Decorated Text (花字)
|
||||
|
||||
Stylized text treatments for emphasis and visual appeal.
|
||||
|
||||
| Name | Description | Use Case |
|
||||
|------|-------------|----------|
|
||||
| gradient | Gradient color fill | Title emphasis, modern feel |
|
||||
| stroke-text | Outlined text with stroke | Cover headlines, high visibility |
|
||||
| shadow-3d | 3D shadow/extrusion effect | Key terms, depth |
|
||||
| highlight | Highlighter marker effect | Critical information, key points |
|
||||
| neon | Neon glow effect | Tech content, night aesthetic |
|
||||
| handwritten | Authentic handwritten style | Personal touch, casual |
|
||||
| bubble | Rounded, inflated letterforms | Cute, playful content |
|
||||
| brush | Brush stroke texture | Artistic, dynamic |
|
||||
|
||||
## Tags & Labels (标签)
|
||||
|
||||
Structured text containers.
|
||||
|
||||
| Name | Description | Use Case |
|
||||
|------|-------------|----------|
|
||||
| black-white | Black background, white text | Brand names, prices, categories |
|
||||
| white-black | White background, black text | Clean labels, minimal style |
|
||||
| bubble | Speech bubble style | Dialogue, annotations, callouts |
|
||||
| pointer | Arrow pointer with label | Product callouts, pointing to features |
|
||||
| ribbon | Ribbon/banner shape | Special offers, highlights |
|
||||
| stamp | Stamp/seal style | Authenticity, recommendations |
|
||||
| pill | Rounded pill shape | Tags, categories, keywords |
|
||||
|
||||
## Text Hierarchy
|
||||
|
||||
Recommended text sizing for visual hierarchy.
|
||||
|
||||
| Level | Role | Relative Size | Style |
|
||||
|-------|------|---------------|-------|
|
||||
| H1 | Main title | 100% | Bold, decorated |
|
||||
| H2 | Section header | 70-80% | Semi-bold |
|
||||
| H3 | Subsection | 50-60% | Medium weight |
|
||||
| Body | Content text | 40-50% | Regular |
|
||||
| Caption | Small notes | 30-35% | Light |
|
||||
|
||||
## Text Direction
|
||||
|
||||
| Direction | Description | Use Case |
|
||||
|-----------|-------------|----------|
|
||||
| horizontal | Standard left-to-right | Default for most content |
|
||||
| vertical | Top-to-bottom columns | Magazine style, traditional Chinese |
|
||||
| curved | Text following a curve | Decorative, around shapes |
|
||||
| diagonal | Angled text | Dynamic compositions |
|
||||
|
||||
## Text Effects
|
||||
|
||||
| Effect | Description | Use Case |
|
||||
|--------|-------------|----------|
|
||||
| shadow | Drop shadow behind text | Readability on busy backgrounds |
|
||||
| outline | Outline around letterforms | High contrast visibility |
|
||||
| glow | Soft glow around text | Dreamy, emphasis |
|
||||
| underline-wavy | Wavy underline decoration | Playful emphasis |
|
||||
| strikethrough | Crossed out text | Before/after, corrections |
|
||||
|
||||
## Language Considerations
|
||||
|
||||
### Chinese Text (中文)
|
||||
- Punctuation: 「」()、。!?
|
||||
- Spacing: No spaces between characters
|
||||
- Line height: 1.5-1.8x for readability
|
||||
|
||||
### Mixed Text
|
||||
- English in Chinese context: Maintain consistent baseline
|
||||
- Numbers: Use consistent number style (lining vs old-style)
|
||||
|
||||
## Style-Specific Typography
|
||||
|
||||
### Cute Style
|
||||
- Rounded, bubbly hand lettering
|
||||
- Soft shadows, playful decorations
|
||||
- Pink/pastel color accents
|
||||
|
||||
### Notion Style
|
||||
- Clean hand-drawn lettering
|
||||
- Simple sans-serif labels
|
||||
- Minimal decoration
|
||||
|
||||
### Bold Style
|
||||
- Impactful hand lettering with shadows
|
||||
- High contrast colors
|
||||
- Strong outlines
|
||||
|
||||
### Chalkboard Style
|
||||
- Chalk texture on all text
|
||||
- Visible imperfections
|
||||
- Multi-color chalk variety
|
||||
@@ -1,30 +0,0 @@
|
||||
# balanced
|
||||
|
||||
Standard content layout
|
||||
|
||||
## Information Density
|
||||
|
||||
- 3-4 key points per image
|
||||
- Whitespace: 40-50% of canvas
|
||||
|
||||
## Structure
|
||||
|
||||
- Title at top
|
||||
- 3-4 bullet points or sections below
|
||||
|
||||
## Text Elements
|
||||
|
||||
- Title + 3-4 bullet points or key messages
|
||||
|
||||
## Visual Balance
|
||||
|
||||
- Top-weighted title
|
||||
- Evenly distributed content below
|
||||
|
||||
## Best For
|
||||
|
||||
Regular content pages, tutorials, explanations
|
||||
|
||||
## Best Style Pairings
|
||||
|
||||
All styles work well
|
||||
@@ -1,31 +0,0 @@
|
||||
# comparison
|
||||
|
||||
Side-by-side contrast layout
|
||||
|
||||
## Information Density
|
||||
|
||||
- 2 main sections with 2-4 points each
|
||||
- Whitespace: 30-40% of canvas
|
||||
|
||||
## Structure
|
||||
|
||||
- Left vs Right layout
|
||||
- Before/After, Pros/Cons format
|
||||
- Clear divider between sections
|
||||
|
||||
## Text Elements
|
||||
|
||||
- Title + left label + right label + mirrored points
|
||||
|
||||
## Visual Balance
|
||||
|
||||
- Symmetrical left/right
|
||||
- Clear visual contrast
|
||||
|
||||
## Best For
|
||||
|
||||
Comparisons, transformations, decision helpers, 对比图
|
||||
|
||||
## Best Style Pairings
|
||||
|
||||
bold (dramatic contrast), tech (data comparison), warm (before/after stories)
|
||||
@@ -1,31 +0,0 @@
|
||||
# dense
|
||||
|
||||
High information density, knowledge card style
|
||||
|
||||
## Information Density
|
||||
|
||||
- 5-8 key points per image
|
||||
- Whitespace: 20-30% of canvas
|
||||
|
||||
## Structure
|
||||
|
||||
- Multiple sections, structured grid
|
||||
- More text, compact but organized
|
||||
|
||||
## Text Elements
|
||||
|
||||
- Title + multiple sections with headers + numerous points
|
||||
|
||||
## Visual Balance
|
||||
|
||||
- Organized chaos
|
||||
- Clear section boundaries
|
||||
- Compact spacing
|
||||
|
||||
## Best For
|
||||
|
||||
Summary cards, cheat sheets, comprehensive guides, 干货总结
|
||||
|
||||
## Best Style Pairings
|
||||
|
||||
tech, notion, minimal (clean styles prevent visual overload)
|
||||
@@ -1,30 +0,0 @@
|
||||
# flow
|
||||
|
||||
Process and timeline layout
|
||||
|
||||
## Information Density
|
||||
|
||||
- 3-6 steps/stages
|
||||
- Whitespace: 30-40% of canvas
|
||||
|
||||
## Structure
|
||||
|
||||
- Connected nodes with arrows
|
||||
- Sequential flow, directional
|
||||
|
||||
## Text Elements
|
||||
|
||||
- Title + step labels + optional descriptions per step
|
||||
|
||||
## Visual Balance
|
||||
|
||||
- Directional flow (top→bottom or left→right)
|
||||
- Clear progression
|
||||
|
||||
## Best For
|
||||
|
||||
Processes, timelines, cause-effect chains, workflows
|
||||
|
||||
## Best Style Pairings
|
||||
|
||||
tech (process diagrams), notion (simple flows), fresh (organic flows)
|
||||
@@ -1,31 +0,0 @@
|
||||
# list
|
||||
|
||||
Enumeration and ranking format
|
||||
|
||||
## Information Density
|
||||
|
||||
- 4-7 items
|
||||
- Whitespace: 30-40% of canvas
|
||||
|
||||
## Structure
|
||||
|
||||
- Numbered or bulleted vertical list
|
||||
- Consistent item format
|
||||
|
||||
## Text Elements
|
||||
|
||||
- Title + numbered/bulleted items
|
||||
- Consistent format per item
|
||||
|
||||
## Visual Balance
|
||||
|
||||
- Left-aligned list
|
||||
- Clear number/bullet hierarchy
|
||||
|
||||
## Best For
|
||||
|
||||
Top N lists, checklists, step-by-step guides, rankings
|
||||
|
||||
## Best Style Pairings
|
||||
|
||||
All styles, especially cute (checklist), bold (rankings)
|
||||
@@ -1,31 +0,0 @@
|
||||
# sparse
|
||||
|
||||
Minimal information, maximum impact
|
||||
|
||||
## Information Density
|
||||
|
||||
- 1-2 key points per image
|
||||
- Whitespace: 60-70% of canvas
|
||||
|
||||
## Structure
|
||||
|
||||
- Single focal point centered
|
||||
- One core message
|
||||
- Single centered focal point
|
||||
|
||||
## Text Elements
|
||||
|
||||
- Title only, or title + one subtitle/tagline
|
||||
|
||||
## Visual Balance
|
||||
|
||||
- Centered, symmetrical
|
||||
- Breathing room on all sides
|
||||
|
||||
## Best For
|
||||
|
||||
Covers, quotes, impactful statements, emotional content
|
||||
|
||||
## Best Style Pairings
|
||||
|
||||
Any style, especially effective with bold, minimal, notion
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
name: bold
|
||||
category: impact
|
||||
---
|
||||
|
||||
# Bold Style
|
||||
|
||||
High impact, attention-grabbing aesthetic.
|
||||
|
||||
## Element Combination
|
||||
|
||||
```yaml
|
||||
canvas:
|
||||
ratio: portrait-3-4
|
||||
grid: single | dual
|
||||
|
||||
image_effects:
|
||||
cutout: clean
|
||||
stroke: colored-solid | double
|
||||
filter: high-saturation
|
||||
|
||||
typography:
|
||||
decorated: shadow-3d | stroke-text
|
||||
tags: black-white | ribbon
|
||||
direction: horizontal | diagonal
|
||||
|
||||
decorations:
|
||||
emphasis: exclamation | star-burst | red-arrow
|
||||
background: solid-saturated | gradient-linear
|
||||
doodles: arrows-curvy | squiggles
|
||||
frames: none
|
||||
```
|
||||
|
||||
## Color Palette
|
||||
|
||||
| Role | Colors | Hex |
|
||||
|------|--------|-----|
|
||||
| Primary | Vibrant red, orange, yellow | #E53E3E, #DD6B20, #F6E05E |
|
||||
| Background | Deep black, dark charcoal | #000000, #1A1A1A |
|
||||
| Accents | White, neon yellow | #FFFFFF, #F7FF00 |
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Exclamation marks, arrows, warning icons
|
||||
- Strong shapes, high contrast elements
|
||||
- Dramatic compositions
|
||||
- Bold geometric forms
|
||||
|
||||
## Typography
|
||||
|
||||
- Bold, impactful hand lettering with shadows
|
||||
- High contrast text treatments
|
||||
- Large, commanding headlines
|
||||
|
||||
## Best Layout Pairings
|
||||
|
||||
| Layout | Compatibility | Use Case |
|
||||
|--------|---------------|----------|
|
||||
| sparse | ✓✓ | Impactful statements |
|
||||
| balanced | ✓ | Warning content |
|
||||
| dense | ✓ | Critical information cards |
|
||||
| list | ✓✓ | Must-know lists, rankings |
|
||||
| comparison | ✓✓ | Dramatic contrasts |
|
||||
| flow | ✓ | Critical process steps |
|
||||
|
||||
## Best For
|
||||
|
||||
- Important tips and warnings
|
||||
- Must-know content
|
||||
- Critical announcements
|
||||
- Rankings and comparisons
|
||||
- Attention-grabbing hooks
|
||||
@@ -0,0 +1,97 @@
|
||||
---
|
||||
name: chalkboard
|
||||
category: educational
|
||||
---
|
||||
|
||||
# Chalkboard Style
|
||||
|
||||
Black chalkboard background with colorful chalk drawing aesthetic.
|
||||
|
||||
## Element Combination
|
||||
|
||||
```yaml
|
||||
canvas:
|
||||
ratio: portrait-3-4
|
||||
grid: single | dual | triptych
|
||||
|
||||
image_effects:
|
||||
cutout: stylized
|
||||
stroke: none
|
||||
filter: none
|
||||
|
||||
typography:
|
||||
decorated: handwritten
|
||||
tags: none
|
||||
direction: horizontal | vertical
|
||||
|
||||
decorations:
|
||||
emphasis: underline | circle-mark | arrows-curvy
|
||||
background: chalkboard
|
||||
doodles: hand-drawn-lines | stars-sparkles
|
||||
frames: none
|
||||
```
|
||||
|
||||
## Color Palette
|
||||
|
||||
| Role | Colors | Hex |
|
||||
|------|--------|-----|
|
||||
| Background | Chalkboard black, green-black | #1A1A1A, #1C2B1C |
|
||||
| Primary Text | Chalk white | #F5F5F5 |
|
||||
| Accent 1 | Chalk yellow | #FFE566 |
|
||||
| Accent 2 | Chalk pink | #FF9999 |
|
||||
| Accent 3 | Chalk blue | #66B3FF |
|
||||
| Accent 4 | Chalk green | #90EE90 |
|
||||
| Accent 5 | Chalk orange | #FFB366 |
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Hand-drawn chalk illustrations with sketchy, imperfect lines
|
||||
- Chalk dust effects around text and key elements
|
||||
- Doodles: stars, arrows, underlines, circles, checkmarks
|
||||
- Mathematical formulas and simple diagrams
|
||||
- Eraser smudges and chalk residue textures
|
||||
- Stick figures and simple icons
|
||||
- Connection lines with hand-drawn feel
|
||||
|
||||
## Typography
|
||||
|
||||
- Hand-drawn chalk lettering style
|
||||
- Visible chalk texture on all text
|
||||
- Imperfect baseline adds authenticity
|
||||
- White or bright colored chalk for emphasis
|
||||
|
||||
## Style Rules
|
||||
|
||||
### Do
|
||||
- Maintain authentic chalk texture on all elements
|
||||
- Use imperfect, hand-drawn quality throughout
|
||||
- Add subtle chalk dust and smudge effects
|
||||
- Create visual hierarchy with color variety
|
||||
- Include playful doodles and annotations
|
||||
|
||||
### Don't
|
||||
- Use perfect geometric shapes
|
||||
- Create clean digital-looking lines
|
||||
- Add photorealistic elements
|
||||
- Use gradients or glossy effects
|
||||
|
||||
## Best Layout Pairings
|
||||
|
||||
| Layout | Compatibility | Use Case |
|
||||
|--------|---------------|----------|
|
||||
| sparse | ✓✓ | Educational covers |
|
||||
| balanced | ✓✓ | Standard lessons |
|
||||
| dense | ✓✓ | Detailed tutorials |
|
||||
| list | ✓✓ | Learning checklists |
|
||||
| comparison | ✓ | Concept comparisons |
|
||||
| flow | ✓✓ | Process explanations |
|
||||
|
||||
## Best For
|
||||
|
||||
- Educational content
|
||||
- Tutorials and how-to's
|
||||
- Classroom themes
|
||||
- Teaching materials
|
||||
- Workshops
|
||||
- Informal learning sessions
|
||||
- Knowledge sharing
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
name: cute
|
||||
category: sweet
|
||||
---
|
||||
|
||||
# Cute Style
|
||||
|
||||
Sweet, adorable, girly - classic Xiaohongshu aesthetic.
|
||||
|
||||
## Element Combination
|
||||
|
||||
```yaml
|
||||
canvas:
|
||||
ratio: portrait-3-4
|
||||
grid: single | dual | quad
|
||||
|
||||
image_effects:
|
||||
cutout: soft
|
||||
stroke: white-solid | colored-solid
|
||||
filter: clear-glow | cream-skin
|
||||
|
||||
typography:
|
||||
decorated: bubble | highlight
|
||||
tags: pill | bubble
|
||||
direction: horizontal
|
||||
|
||||
decorations:
|
||||
emphasis: star-burst | hearts
|
||||
background: solid-pastel | gradient-linear
|
||||
doodles: hearts | stars-sparkles | flowers
|
||||
frames: polaroid | tape-corners
|
||||
```
|
||||
|
||||
## Color Palette
|
||||
|
||||
| Role | Colors | Hex |
|
||||
|------|--------|-----|
|
||||
| Primary | Pink, peach, mint, lavender | #FED7E2, #FEEBC8, #C6F6D5, #E9D8FD |
|
||||
| Background | Cream, soft pink | #FFFAF0, #FFF5F7 |
|
||||
| Accents | Hot pink, coral | #FF69B4, #FF6B6B |
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Hearts, stars, sparkles, cute faces
|
||||
- Ribbon decorations, sticker-style
|
||||
- Cute stickers, emoji icons
|
||||
- Soft, rounded shapes
|
||||
|
||||
## Typography
|
||||
|
||||
- Rounded, bubbly hand lettering
|
||||
- Soft shadows, playful decorations
|
||||
- Pink/pastel color accents on text
|
||||
|
||||
## Best Layout Pairings
|
||||
|
||||
| Layout | Compatibility | Use Case |
|
||||
|--------|---------------|----------|
|
||||
| sparse | ✓✓ | Covers, emotional impact |
|
||||
| balanced | ✓✓ | Standard cute content |
|
||||
| dense | ✓ | Cute knowledge cards |
|
||||
| list | ✓✓ | Checklists, cute rankings |
|
||||
| comparison | ✓ | Before/after transformations |
|
||||
| flow | ✓ | Cute step guides |
|
||||
|
||||
## Best For
|
||||
|
||||
- Lifestyle content
|
||||
- Beauty and skincare
|
||||
- Fashion and style
|
||||
- Daily tips and hacks
|
||||
- Personal shares
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
name: fresh
|
||||
category: natural
|
||||
---
|
||||
|
||||
# Fresh Style
|
||||
|
||||
Clean, refreshing, natural aesthetic.
|
||||
|
||||
## Element Combination
|
||||
|
||||
```yaml
|
||||
canvas:
|
||||
ratio: portrait-3-4
|
||||
grid: single | triptych
|
||||
|
||||
image_effects:
|
||||
cutout: soft
|
||||
stroke: white-solid | none
|
||||
filter: clear-glow | cool-tone
|
||||
|
||||
typography:
|
||||
decorated: none | highlight
|
||||
tags: pill | white-black
|
||||
direction: horizontal
|
||||
|
||||
decorations:
|
||||
emphasis: checkmark | circle-mark
|
||||
background: solid-white | solid-pastel
|
||||
doodles: leaves | clouds | bubbles
|
||||
frames: rounded-rect | none
|
||||
```
|
||||
|
||||
## Color Palette
|
||||
|
||||
| Role | Colors | Hex |
|
||||
|------|--------|-----|
|
||||
| Primary | Mint green, sky blue, light yellow | #9AE6B4, #90CDF4, #FAF089 |
|
||||
| Background | Pure white, soft mint | #FFFFFF, #F0FFF4 |
|
||||
| Accents | Leaf green, water blue | #48BB78, #4299E1 |
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Plant leaves, clouds, water drops
|
||||
- Simple geometric shapes
|
||||
- Breathing room, open composition
|
||||
- Natural, organic elements
|
||||
|
||||
## Typography
|
||||
|
||||
- Clean, light hand lettering with breathing room
|
||||
- Airy spacing
|
||||
- Fresh color accents
|
||||
|
||||
## Best Layout Pairings
|
||||
|
||||
| Layout | Compatibility | Use Case |
|
||||
|--------|---------------|----------|
|
||||
| sparse | ✓✓ | Clean covers |
|
||||
| balanced | ✓✓ | Standard fresh content |
|
||||
| dense | ✓ | Organized information |
|
||||
| list | ✓ | Wellness tips |
|
||||
| comparison | ✓ | Before/after health |
|
||||
| flow | ✓✓ | Organic processes |
|
||||
|
||||
## Best For
|
||||
|
||||
- Health and wellness
|
||||
- Minimalist lifestyle
|
||||
- Self-care content
|
||||
- Nature-related topics
|
||||
- Clean living tips
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
name: minimal
|
||||
category: elegant
|
||||
---
|
||||
|
||||
# Minimal Style
|
||||
|
||||
Ultra-clean, sophisticated aesthetic.
|
||||
|
||||
## Element Combination
|
||||
|
||||
```yaml
|
||||
canvas:
|
||||
ratio: portrait-3-4
|
||||
grid: single
|
||||
|
||||
image_effects:
|
||||
cutout: clean
|
||||
stroke: none | white-solid
|
||||
filter: none | muted-tones
|
||||
|
||||
typography:
|
||||
decorated: none
|
||||
tags: white-black | pill
|
||||
direction: horizontal
|
||||
|
||||
decorations:
|
||||
emphasis: underline | circle-mark
|
||||
background: solid-white | solid-pastel
|
||||
doodles: hand-drawn-lines
|
||||
frames: none | rounded-rect
|
||||
```
|
||||
|
||||
## Color Palette
|
||||
|
||||
| Role | Colors | Hex |
|
||||
|------|--------|-----|
|
||||
| Primary | Black, white | #000000, #FFFFFF |
|
||||
| Background | Off-white, pure white | #FAFAFA, #FFFFFF |
|
||||
| Accents | Single color (content-derived) | Blue, green, or coral |
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Single focal point, thin lines
|
||||
- Maximum whitespace
|
||||
- Simple, clean decorations
|
||||
- Restrained visual elements
|
||||
|
||||
## Typography
|
||||
|
||||
- Clean, simple hand lettering
|
||||
- Minimal weight variations
|
||||
- Elegant spacing
|
||||
|
||||
## Best Layout Pairings
|
||||
|
||||
| Layout | Compatibility | Use Case |
|
||||
|--------|---------------|----------|
|
||||
| sparse | ✓✓ | Elegant statements |
|
||||
| balanced | ✓✓ | Professional content |
|
||||
| dense | ✓✓ | Clean knowledge cards |
|
||||
| list | ✓ | Simple lists |
|
||||
| comparison | ✓ | Clean comparisons |
|
||||
| flow | ✓ | Elegant processes |
|
||||
|
||||
## Best For
|
||||
|
||||
- Professional content
|
||||
- Serious topics
|
||||
- Elegant presentations
|
||||
- High-end products
|
||||
- Business content
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
name: notion
|
||||
category: minimal
|
||||
---
|
||||
|
||||
# Notion Style
|
||||
|
||||
Minimalist hand-drawn line art, intellectual aesthetic.
|
||||
|
||||
## Element Combination
|
||||
|
||||
```yaml
|
||||
canvas:
|
||||
ratio: portrait-3-4
|
||||
grid: single | dual
|
||||
|
||||
image_effects:
|
||||
cutout: clean
|
||||
stroke: none | white-solid
|
||||
filter: none | muted-tones
|
||||
|
||||
typography:
|
||||
decorated: none | handwritten
|
||||
tags: black-white | pill
|
||||
direction: horizontal
|
||||
|
||||
decorations:
|
||||
emphasis: circle-mark | underline
|
||||
background: solid-white | paper-texture
|
||||
doodles: hand-drawn-lines | arrows-curvy
|
||||
frames: none | rounded-rect
|
||||
```
|
||||
|
||||
## Color Palette
|
||||
|
||||
| Role | Colors | Hex |
|
||||
|------|--------|-----|
|
||||
| Primary | Black, dark gray | #1A1A1A, #4A4A4A |
|
||||
| Background | Pure white, off-white | #FFFFFF, #FAFAFA |
|
||||
| Accents | Pastel blue, pastel yellow, pastel pink | #A8D4F0, #F9E79F, #FADBD8 |
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Simple line doodles, hand-drawn wobble effect
|
||||
- Geometric shapes, stick figures
|
||||
- Maximum whitespace, single-weight ink lines
|
||||
- Clean, uncluttered compositions
|
||||
|
||||
## Typography
|
||||
|
||||
- Clean hand-drawn lettering
|
||||
- Simple sans-serif labels
|
||||
- Minimal decoration on text
|
||||
|
||||
## Best Layout Pairings
|
||||
|
||||
| Layout | Compatibility | Use Case |
|
||||
|--------|---------------|----------|
|
||||
| sparse | ✓✓ | Concept covers |
|
||||
| balanced | ✓✓ | Standard explanations |
|
||||
| dense | ✓✓ | Knowledge cards, cheat sheets |
|
||||
| list | ✓✓ | Productivity tips, tool lists |
|
||||
| comparison | ✓✓ | Data comparisons |
|
||||
| flow | ✓✓ | Process diagrams |
|
||||
|
||||
## Best For
|
||||
|
||||
- Knowledge sharing
|
||||
- Concept explanations
|
||||
- SaaS content
|
||||
- Productivity tips
|
||||
- Tech tutorials
|
||||
- Professional content
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
name: pop
|
||||
category: energetic
|
||||
---
|
||||
|
||||
# Pop Style
|
||||
|
||||
Vibrant, energetic, eye-catching aesthetic.
|
||||
|
||||
## Element Combination
|
||||
|
||||
```yaml
|
||||
canvas:
|
||||
ratio: portrait-3-4
|
||||
grid: single | quad
|
||||
|
||||
image_effects:
|
||||
cutout: stylized
|
||||
stroke: colored-solid | double
|
||||
filter: high-saturation
|
||||
|
||||
typography:
|
||||
decorated: stroke-text | shadow-3d
|
||||
tags: bubble | ribbon
|
||||
direction: horizontal | curved
|
||||
|
||||
decorations:
|
||||
emphasis: star-burst | exclamation
|
||||
background: solid-saturated | dots
|
||||
doodles: stars-sparkles | confetti | squiggles
|
||||
frames: none
|
||||
```
|
||||
|
||||
## Color Palette
|
||||
|
||||
| Role | Colors | Hex |
|
||||
|------|--------|-----|
|
||||
| Primary | Bright red, yellow, blue, green | #F56565, #ECC94B, #4299E1, #48BB78 |
|
||||
| Background | White, light gray | #FFFFFF, #F7FAFC |
|
||||
| Accents | Neon pink, electric purple | #FF69B4, #9F7AEA |
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Bold shapes, speech bubbles
|
||||
- Comic-style effects, starburst
|
||||
- Dynamic, energetic compositions
|
||||
- High-energy decorations
|
||||
|
||||
## Typography
|
||||
|
||||
- Dynamic, energetic hand lettering with outlines
|
||||
- Bold color combinations
|
||||
- Playful, expressive forms
|
||||
|
||||
## Best Layout Pairings
|
||||
|
||||
| Layout | Compatibility | Use Case |
|
||||
|--------|---------------|----------|
|
||||
| sparse | ✓✓ | Exciting announcements |
|
||||
| balanced | ✓✓ | Fun tutorials |
|
||||
| dense | ✓ | Packed information |
|
||||
| list | ✓✓ | Fun facts lists |
|
||||
| comparison | ✓✓ | Dynamic comparisons |
|
||||
| flow | ✓ | Energetic processes |
|
||||
|
||||
## Best For
|
||||
|
||||
- Exciting announcements
|
||||
- Fun facts
|
||||
- Engaging tutorials
|
||||
- Entertainment content
|
||||
- Youth-oriented content
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
name: retro
|
||||
category: vintage
|
||||
---
|
||||
|
||||
# Retro Style
|
||||
|
||||
Vintage, nostalgic, trendy aesthetic.
|
||||
|
||||
## Element Combination
|
||||
|
||||
```yaml
|
||||
canvas:
|
||||
ratio: portrait-3-4
|
||||
grid: single | dual
|
||||
|
||||
image_effects:
|
||||
cutout: stylized
|
||||
stroke: dashed | double
|
||||
filter: film-grain | muted-tones
|
||||
|
||||
typography:
|
||||
decorated: brush | handwritten
|
||||
tags: stamp | ribbon
|
||||
direction: horizontal
|
||||
|
||||
decorations:
|
||||
emphasis: star-burst | numbering
|
||||
background: paper-texture | dots
|
||||
doodles: stars-sparkles | squiggles
|
||||
frames: polaroid | film-strip | stamp-border
|
||||
```
|
||||
|
||||
## Color Palette
|
||||
|
||||
| Role | Colors | Hex |
|
||||
|------|--------|-----|
|
||||
| Primary | Muted orange, dusty pink, faded teal | #E07A4D, #D4A5A5, #6B9999 |
|
||||
| Background | Aged paper, sepia tones | #F5E6D3, #E8DCC8 |
|
||||
| Accents | Faded red, vintage gold | #C55A5A, #B8860B |
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Halftone dots, vintage badges
|
||||
- Classic icons, tape effects
|
||||
- Aged texture overlays
|
||||
- Nostalgic decorative elements
|
||||
|
||||
## Typography
|
||||
|
||||
- Vintage-style hand lettering
|
||||
- Classic feel with imperfections
|
||||
- Aged texture on text
|
||||
|
||||
## Best Layout Pairings
|
||||
|
||||
| Layout | Compatibility | Use Case |
|
||||
|--------|---------------|----------|
|
||||
| sparse | ✓✓ | Vintage covers |
|
||||
| balanced | ✓✓ | Classic content |
|
||||
| dense | ✓ | Vintage knowledge cards |
|
||||
| list | ✓✓ | Classic rankings |
|
||||
| comparison | ✓ | Then vs now |
|
||||
| flow | ✓ | Historical timelines |
|
||||
|
||||
## Best For
|
||||
|
||||
- Throwback content
|
||||
- Classic tips
|
||||
- Timeless advice
|
||||
- Vintage aesthetics
|
||||
- Nostalgic shares
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
name: warm
|
||||
category: cozy
|
||||
---
|
||||
|
||||
# Warm Style
|
||||
|
||||
Cozy, friendly, approachable aesthetic.
|
||||
|
||||
## Element Combination
|
||||
|
||||
```yaml
|
||||
canvas:
|
||||
ratio: portrait-3-4
|
||||
grid: single | dual
|
||||
|
||||
image_effects:
|
||||
cutout: soft
|
||||
stroke: white-solid | glow
|
||||
filter: warm-tone | cream-skin
|
||||
|
||||
typography:
|
||||
decorated: highlight | handwritten
|
||||
tags: ribbon | bubble
|
||||
direction: horizontal
|
||||
|
||||
decorations:
|
||||
emphasis: star-burst | hearts
|
||||
background: solid-pastel | gradient-radial
|
||||
doodles: clouds | stars-sparkles
|
||||
frames: polaroid | tape-corners
|
||||
```
|
||||
|
||||
## Color Palette
|
||||
|
||||
| Role | Colors | Hex |
|
||||
|------|--------|-----|
|
||||
| Primary | Warm orange, golden yellow, terracotta | #ED8936, #F6AD55, #C05621 |
|
||||
| Background | Cream, soft peach | #FFFAF0, #FED7AA |
|
||||
| Accents | Deep brown, soft red | #744210, #E57373 |
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Sun rays, coffee cups, cozy items
|
||||
- Warm lighting effects
|
||||
- Friendly, inviting decorations
|
||||
- Soft, comfortable shapes
|
||||
|
||||
## Typography
|
||||
|
||||
- Friendly, rounded hand lettering
|
||||
- Warm color accents
|
||||
- Comfortable, approachable feel
|
||||
|
||||
## Best Layout Pairings
|
||||
|
||||
| Layout | Compatibility | Use Case |
|
||||
|--------|---------------|----------|
|
||||
| sparse | ✓✓ | Emotional covers |
|
||||
| balanced | ✓✓ | Personal stories |
|
||||
| dense | ✓ | Detailed experiences |
|
||||
| list | ✓ | Life lessons |
|
||||
| comparison | ✓✓ | Before/after stories |
|
||||
| flow | ✓ | Journey narratives |
|
||||
|
||||
## Best For
|
||||
|
||||
- Personal stories
|
||||
- Life lessons
|
||||
- Emotional content
|
||||
- Comfort and lifestyle
|
||||
- Heartfelt shares
|
||||
@@ -1,23 +0,0 @@
|
||||
# bold
|
||||
|
||||
High impact, attention-grabbing
|
||||
|
||||
## Color Palette
|
||||
|
||||
- Primary: Vibrant red (#E53E3E), orange (#DD6B20), yellow (#F6E05E)
|
||||
- Background: Deep black (#000000), dark charcoal
|
||||
- Accents: White, neon yellow
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Exclamation marks, arrows, warning icons
|
||||
- Strong shapes, high contrast elements
|
||||
- Dramatic compositions
|
||||
|
||||
## Typography
|
||||
|
||||
- Bold, impactful hand lettering with shadows
|
||||
|
||||
## Best For
|
||||
|
||||
Important tips, warnings, must-know content
|
||||
@@ -1,61 +0,0 @@
|
||||
# chalkboard
|
||||
|
||||
Black chalkboard background with colorful chalk drawing style
|
||||
|
||||
## Design Aesthetic
|
||||
|
||||
Classic classroom chalkboard aesthetic with hand-drawn chalk illustrations. Nostalgic educational feel with imperfect, sketchy lines that capture the warmth of traditional teaching. Colorful chalk creates visual hierarchy while maintaining the authentic chalkboard experience.
|
||||
|
||||
## Background
|
||||
|
||||
- Color: Chalkboard Black (#1A1A1A) or Dark Green-Black (#1C2B1C)
|
||||
- Texture: Realistic chalkboard texture with subtle scratches, dust particles, and faint eraser marks
|
||||
|
||||
## Typography
|
||||
|
||||
Hand-drawn chalk lettering style with visible chalk texture. Imperfect baseline adds authenticity. White or bright colored chalk for emphasis.
|
||||
|
||||
## Color Palette
|
||||
|
||||
| Role | Color | Hex | Usage |
|
||||
|------|-------|-----|-------|
|
||||
| Background | Chalkboard Black | #1A1A1A | Primary background |
|
||||
| Alt Background | Green-Black | #1C2B1C | Traditional green board |
|
||||
| Primary Text | Chalk White | #F5F5F5 | Main text, outlines |
|
||||
| Accent 1 | Chalk Yellow | #FFE566 | Highlights, emphasis |
|
||||
| Accent 2 | Chalk Pink | #FF9999 | Secondary highlights |
|
||||
| Accent 3 | Chalk Blue | #66B3FF | Diagrams, links |
|
||||
| Accent 4 | Chalk Green | #90EE90 | Success, nature |
|
||||
| Accent 5 | Chalk Orange | #FFB366 | Warnings, energy |
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Hand-drawn chalk illustrations with sketchy, imperfect lines
|
||||
- Chalk dust effects around text and key elements
|
||||
- Doodles: stars, arrows, underlines, circles, checkmarks
|
||||
- Mathematical formulas and simple diagrams
|
||||
- Eraser smudges and chalk residue textures
|
||||
- Wooden frame border optional
|
||||
- Stick figures and simple icons
|
||||
- Connection lines with hand-drawn feel
|
||||
|
||||
## Style Rules
|
||||
|
||||
### Do
|
||||
|
||||
- Maintain authentic chalk texture on all elements
|
||||
- Use imperfect, hand-drawn quality throughout
|
||||
- Add subtle chalk dust and smudge effects
|
||||
- Create visual hierarchy with color variety
|
||||
- Include playful doodles and annotations
|
||||
|
||||
### Don't
|
||||
|
||||
- Use perfect geometric shapes
|
||||
- Create clean digital-looking lines
|
||||
- Add photorealistic elements
|
||||
- Use gradients or glossy effects
|
||||
|
||||
## Best For
|
||||
|
||||
Educational content, tutorials, classroom themes, teaching materials, workshops, informal learning sessions, knowledge sharing
|
||||
@@ -1,23 +0,0 @@
|
||||
# cute
|
||||
|
||||
Sweet, adorable, girly - classic Xiaohongshu aesthetic
|
||||
|
||||
## Color Palette
|
||||
|
||||
- Primary: Pink (#FED7E2), peach (#FEEBC8), mint (#C6F6D5), lavender (#E9D8FD)
|
||||
- Background: Cream (#FFFAF0), soft pink (#FFF5F7)
|
||||
- Accents: Hot pink, coral
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Hearts, stars, sparkles, cute faces
|
||||
- Ribbon decorations, sticker-style
|
||||
- Cute stickers, emoji icons
|
||||
|
||||
## Typography
|
||||
|
||||
- Rounded, bubbly hand lettering
|
||||
|
||||
## Best For
|
||||
|
||||
Lifestyle, beauty, fashion, daily tips
|
||||
@@ -1,23 +0,0 @@
|
||||
# fresh
|
||||
|
||||
Clean, refreshing, natural
|
||||
|
||||
## Color Palette
|
||||
|
||||
- Primary: Mint green (#9AE6B4), sky blue (#90CDF4), light yellow (#FAF089)
|
||||
- Background: Pure white (#FFFFFF), soft mint (#F0FFF4)
|
||||
- Accents: Leaf green, water blue
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Plant leaves, clouds, water drops
|
||||
- Simple geometric shapes
|
||||
- Breathing room, open composition
|
||||
|
||||
## Typography
|
||||
|
||||
- Clean, light hand lettering with breathing room
|
||||
|
||||
## Best For
|
||||
|
||||
Health, wellness, minimalist lifestyle, self-care
|
||||
@@ -1,23 +0,0 @@
|
||||
# minimal
|
||||
|
||||
Ultra-clean, sophisticated
|
||||
|
||||
## Color Palette
|
||||
|
||||
- Primary: Black (#000000), white (#FFFFFF)
|
||||
- Background: Off-white (#FAFAFA), pure white
|
||||
- Accents: Single color (content-derived - blue, green, or coral)
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Single focal point, thin lines
|
||||
- Maximum whitespace
|
||||
- Simple, clean decorations
|
||||
|
||||
## Typography
|
||||
|
||||
- Clean, simple hand lettering
|
||||
|
||||
## Best For
|
||||
|
||||
Professional content, serious topics, elegant presentations
|
||||
@@ -1,23 +0,0 @@
|
||||
# notion
|
||||
|
||||
Minimalist hand-drawn line art, intellectual
|
||||
|
||||
## Color Palette
|
||||
|
||||
- Primary: Black (#1A1A1A), dark gray (#4A4A4A)
|
||||
- Background: Pure white (#FFFFFF), off-white (#FAFAFA)
|
||||
- Accents: Pastel blue (#A8D4F0), pastel yellow (#F9E79F), pastel pink (#FADBD8)
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Simple line doodles, hand-drawn wobble effect
|
||||
- Geometric shapes, stick figures
|
||||
- Maximum whitespace, single-weight ink lines
|
||||
|
||||
## Typography
|
||||
|
||||
- Clean hand-drawn lettering, simple sans-serif labels
|
||||
|
||||
## Best For
|
||||
|
||||
Knowledge sharing, concept explanations, SaaS content, productivity tips
|
||||
@@ -1,23 +0,0 @@
|
||||
# pop
|
||||
|
||||
Vibrant, energetic, eye-catching
|
||||
|
||||
## Color Palette
|
||||
|
||||
- Primary: Bright red (#F56565), yellow (#ECC94B), blue (#4299E1), green (#48BB78)
|
||||
- Background: White (#FFFFFF), light gray
|
||||
- Accents: Neon pink, electric purple
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Bold shapes, speech bubbles
|
||||
- Comic-style effects, starburst
|
||||
- Dynamic, energetic compositions
|
||||
|
||||
## Typography
|
||||
|
||||
- Dynamic, energetic hand lettering with outlines
|
||||
|
||||
## Best For
|
||||
|
||||
Exciting announcements, fun facts, engaging tutorials
|
||||
@@ -1,23 +0,0 @@
|
||||
# retro
|
||||
|
||||
Vintage, nostalgic, trendy
|
||||
|
||||
## Color Palette
|
||||
|
||||
- Primary: Muted orange, dusty pink (#FED7E2 at 70%), faded teal
|
||||
- Background: Aged paper (#F5E6D3), sepia tones
|
||||
- Accents: Faded red, vintage gold
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Halftone dots, vintage badges
|
||||
- Classic icons, tape effects
|
||||
- Aged texture overlays
|
||||
|
||||
## Typography
|
||||
|
||||
- Vintage-style hand lettering, classic feel
|
||||
|
||||
## Best For
|
||||
|
||||
Throwback content, classic tips, timeless advice
|
||||
@@ -1,23 +0,0 @@
|
||||
# warm
|
||||
|
||||
Cozy, friendly, approachable
|
||||
|
||||
## Color Palette
|
||||
|
||||
- Primary: Warm orange (#ED8936), golden yellow (#F6AD55), terracotta (#C05621)
|
||||
- Background: Cream (#FFFAF0), soft peach (#FED7AA)
|
||||
- Accents: Deep brown (#744210), soft red
|
||||
|
||||
## Visual Elements
|
||||
|
||||
- Sun rays, coffee cups, cozy items
|
||||
- Warm lighting effects
|
||||
- Friendly, inviting decorations
|
||||
|
||||
## Typography
|
||||
|
||||
- Friendly, rounded hand lettering
|
||||
|
||||
## Best For
|
||||
|
||||
Personal stories, life lessons, emotional content
|
||||
+6
-6
@@ -25,9 +25,9 @@ Unlike other platforms, Xiaohongshu content must prioritize:
|
||||
| Type | Characteristics | Best Style | Best Layout |
|
||||
|------|----------------|------------|-------------|
|
||||
| 种草/安利 | Product recommendation, benefits focus | cute/fresh | balanced/list |
|
||||
| 干货分享 | Knowledge, tips, how-to | notion/tech | dense/list |
|
||||
| 干货分享 | Knowledge, tips, how-to | notion | dense/list |
|
||||
| 个人故事 | Personal experience, emotional | warm | balanced |
|
||||
| 测评对比 | Review, comparison, pros/cons | tech/bold | comparison |
|
||||
| 测评对比 | Review, comparison, pros/cons | bold/notion | comparison |
|
||||
| 教程步骤 | Step-by-step guide | fresh/notion | flow/list |
|
||||
| 避坑指南 | Warnings, mistakes to avoid | bold | list/comparison |
|
||||
| 清单合集 | Collections, recommendations | cute/minimal | list/dense |
|
||||
@@ -55,10 +55,10 @@ Evaluate title/hook potential using these patterns:
|
||||
| Audience | Interests | Preferred Style | Content Focus |
|
||||
|----------|-----------|-----------------|---------------|
|
||||
| 学生党 | 省钱、学习、校园 | cute/fresh | 平价、教程、学习方法 |
|
||||
| 打工人 | 效率、职场、减压 | minimal/tech | 工具、技巧、摸鱼 |
|
||||
| 打工人 | 效率、职场、减压 | minimal/notion | 工具、技巧、摸鱼 |
|
||||
| 宝妈 | 育儿、家居、省心 | warm/fresh | 实用、安全、经验 |
|
||||
| 精致女孩 | 美妆、穿搭、仪式感 | cute/retro | 好看、氛围、品质 |
|
||||
| 技术宅 | 工具、效率、极客 | tech/notion | 深度、专业、新奇 |
|
||||
| 技术宅 | 工具、效率、极客 | notion/chalkboard | 深度、专业、新奇 |
|
||||
| 美食爱好者 | 探店、食谱、测评 | warm/pop | 好吃、简单、颜值 |
|
||||
| 旅行达人 | 攻略、打卡、小众 | fresh/retro | 省钱、避坑、拍照 |
|
||||
|
||||
@@ -165,7 +165,7 @@ recommended_image_count: 6
|
||||
|
||||
## Content Signals
|
||||
|
||||
- "AI工具" → tech + dense
|
||||
- "AI工具" → notion + dense
|
||||
- "效率" → notion + list
|
||||
- "干货" → minimal + dense
|
||||
|
||||
@@ -180,7 +180,7 @@ recommended_image_count: 6
|
||||
|
||||
## Recommended Approaches
|
||||
|
||||
1. **Tech + Dense** - 专业科技感,适合干货分享 (recommended)
|
||||
1. **Notion + Dense** - 知识卡片风格,适合干货分享 (recommended)
|
||||
2. **Notion + List** - 清爽知识卡片风格
|
||||
3. **Minimal + Balanced** - 简约高端,适合职场人群
|
||||
```
|
||||
+46
-27
@@ -1,13 +1,13 @@
|
||||
# Xiaohongshu Outline Template
|
||||
|
||||
Template for generating infographic series outlines.
|
||||
Template for generating infographic series outlines with layout specifications.
|
||||
|
||||
## File Naming
|
||||
|
||||
Outline files use style slug in the name:
|
||||
- `outline-style-tech.md` - Tech style variant
|
||||
- `outline-style-notion.md` - Notion style variant
|
||||
- `outline-style-minimal.md` - Minimal style variant
|
||||
Outline files use strategy identifier in the name:
|
||||
- `outline-strategy-a.md` - Story-driven variant
|
||||
- `outline-strategy-b.md` - Information-dense variant
|
||||
- `outline-strategy-c.md` - Visual-first variant
|
||||
- `outline.md` - Final selected (copied from chosen variant)
|
||||
|
||||
## Image File Naming
|
||||
@@ -37,13 +37,43 @@ NN-{type}-[slug].md (in prompts/)
|
||||
- Must be unique within the series
|
||||
- Keep short but descriptive (2-4 words)
|
||||
|
||||
## Layout Selection Guide
|
||||
|
||||
### Density-Based Layouts
|
||||
|
||||
| Layout | When to Use | Info Points | Whitespace |
|
||||
|--------|-------------|-------------|------------|
|
||||
| sparse | Covers, quotes, impact statements | 1-2 | 60-70% |
|
||||
| balanced | Standard content, tutorials | 3-4 | 40-50% |
|
||||
| dense | Knowledge cards, cheat sheets | 5-8 | 20-30% |
|
||||
|
||||
### Structure-Based Layouts
|
||||
|
||||
| Layout | When to Use | Structure |
|
||||
|--------|-------------|-----------|
|
||||
| list | Rankings, checklists, steps | Numbered/bulleted vertical |
|
||||
| comparison | Before/after, pros/cons | Left vs right split |
|
||||
| flow | Processes, timelines | Connected nodes with arrows |
|
||||
|
||||
### Position-Based Recommendations
|
||||
|
||||
| Position | Recommended | Reasoning |
|
||||
|----------|-------------|-----------|
|
||||
| Cover | sparse | Maximum impact, clear title |
|
||||
| Setup | balanced | Context without overwhelming |
|
||||
| Core | balanced/dense/list | Match content density |
|
||||
| Payoff | balanced/list | Clear takeaways |
|
||||
| Ending | sparse | Clean CTA, memorable |
|
||||
|
||||
## Outline Format
|
||||
|
||||
```markdown
|
||||
# Xiaohongshu Infographic Series Outline
|
||||
|
||||
---
|
||||
style: tech
|
||||
strategy: a # a, b, or c
|
||||
name: Story-Driven
|
||||
style: notion
|
||||
default_layout: dense
|
||||
image_count: 6
|
||||
generated: YYYY-MM-DD HH:mm
|
||||
@@ -188,16 +218,6 @@ Notion界面风格,简洁黑白配色
|
||||
---
|
||||
```
|
||||
|
||||
## Layout Guidelines by Position
|
||||
|
||||
| Position | Recommended Layout | Why |
|
||||
|----------|-------------------|-----|
|
||||
| Cover | `sparse` | Maximum visual impact, clear title |
|
||||
| Setup | `balanced` | Context without overwhelming |
|
||||
| Core | `balanced`/`dense`/`list` | Based on content density |
|
||||
| Payoff | `balanced`/`list` | Clear takeaways |
|
||||
| Ending | `sparse` | Clean CTA, memorable close |
|
||||
|
||||
## Swipe Hook Strategies
|
||||
|
||||
Each image should end with a hook for the next:
|
||||
@@ -211,18 +231,17 @@ Each image should end with a hook for the next:
|
||||
| Promise | "最后一个最实用👇" |
|
||||
| Urgency | "最重要的来了👇" |
|
||||
|
||||
## Variant Differentiation
|
||||
## Strategy Differentiation
|
||||
|
||||
Three variants should differ meaningfully:
|
||||
Three strategies should differ meaningfully:
|
||||
|
||||
| Aspect | Variant A | Variant B | Variant C |
|
||||
|--------|-----------|-----------|-----------|
|
||||
| Style | Primary match | Alternative | Different mood |
|
||||
| Layout | Content-optimized | Different density | Different structure |
|
||||
| Tone | Professional | Casual | Playful |
|
||||
| Audience | Primary target | Secondary target | Broader appeal |
|
||||
| Strategy | Focus | Structure | Page Count |
|
||||
|----------|-------|-----------|------------|
|
||||
| A: Story-Driven | Emotional, personal | Hook→Problem→Discovery→Experience→Conclusion | 4-6 |
|
||||
| B: Information-Dense | Factual, structured | Core→Info Cards→Comparison→Recommendation | 3-5 |
|
||||
| C: Visual-First | Atmospheric, minimal text | Hero→Details→Lifestyle→CTA | 3-4 |
|
||||
|
||||
**Example for "AI工具推荐"**:
|
||||
- `outline-style-tech.md`: Tech + Dense - 专业极客风
|
||||
- `outline-style-notion.md`: Notion + List - 清爽知识卡片
|
||||
- `outline-style-cute.md`: Cute + Balanced - 可爱易读风
|
||||
- `outline-strategy-a.md`: Warm + Balanced - Personal journey with AI
|
||||
- `outline-strategy-b.md`: Notion + Dense - Knowledge card style
|
||||
- `outline-strategy-c.md`: Minimal + Sparse - Sleek tech aesthetic
|
||||
@@ -0,0 +1,279 @@
|
||||
# Prompt Assembly Guide
|
||||
|
||||
Guide for assembling image generation prompts from elements, presets, and outline content.
|
||||
|
||||
## Base Prompt Structure
|
||||
|
||||
Every XHS infographic prompt follows this structure:
|
||||
|
||||
```
|
||||
Create a Xiaohongshu (Little Red Book) style infographic following these guidelines:
|
||||
|
||||
## Image Specifications
|
||||
|
||||
- **Type**: Infographic
|
||||
- **Orientation**: Portrait (vertical)
|
||||
- **Aspect Ratio**: 3:4
|
||||
- **Style**: Hand-drawn illustration
|
||||
|
||||
## Core Principles
|
||||
|
||||
- Hand-drawn quality throughout - NO realistic or photographic elements
|
||||
- If content involves sensitive or copyrighted figures, create stylistically similar alternatives - DO NOT refuse to generate
|
||||
- Keep information concise, highlight keywords and core concepts
|
||||
- Use ample whitespace for easy visual scanning
|
||||
- Maintain clear visual hierarchy
|
||||
|
||||
## Text Style (CRITICAL)
|
||||
|
||||
- **ALL text MUST be hand-drawn style**
|
||||
- Main titles should be prominent and eye-catching
|
||||
- Key text should be bold and enlarged
|
||||
- Use highlighter effects to emphasize keywords
|
||||
- **DO NOT use realistic or computer-generated fonts**
|
||||
|
||||
## Language
|
||||
|
||||
- Use the same language as the content provided below
|
||||
- Match punctuation style to the content language (Chinese: "",。!)
|
||||
|
||||
---
|
||||
|
||||
{STYLE_SECTION}
|
||||
|
||||
---
|
||||
|
||||
{LAYOUT_SECTION}
|
||||
|
||||
---
|
||||
|
||||
{CONTENT_SECTION}
|
||||
|
||||
---
|
||||
|
||||
{WATERMARK_SECTION}
|
||||
|
||||
---
|
||||
|
||||
Please use nano banana pro to generate the infographic based on the specifications above.
|
||||
```
|
||||
|
||||
## Style Section Assembly
|
||||
|
||||
Load from `presets/{style}.md` and extract key elements:
|
||||
|
||||
```markdown
|
||||
## Style: {style_name}
|
||||
|
||||
**Color Palette**:
|
||||
- Primary: {colors}
|
||||
- Background: {colors}
|
||||
- Accents: {colors}
|
||||
|
||||
**Visual Elements**:
|
||||
{visual_elements}
|
||||
|
||||
**Typography**:
|
||||
{typography_style}
|
||||
```
|
||||
|
||||
## Layout Section Assembly
|
||||
|
||||
Load from `elements/canvas.md` and extract relevant layout:
|
||||
|
||||
```markdown
|
||||
## Layout: {layout_name}
|
||||
|
||||
**Information Density**: {density}
|
||||
**Whitespace**: {percentage}
|
||||
|
||||
**Structure**:
|
||||
{structure_description}
|
||||
|
||||
**Visual Balance**:
|
||||
{balance_description}
|
||||
```
|
||||
|
||||
## Content Section Assembly
|
||||
|
||||
From outline entry:
|
||||
|
||||
```markdown
|
||||
## Content
|
||||
|
||||
**Position**: {Cover/Content/Ending}
|
||||
**Core Message**: {message}
|
||||
|
||||
**Text Content**:
|
||||
{text_list}
|
||||
|
||||
**Visual Concept**:
|
||||
{visual_description}
|
||||
```
|
||||
|
||||
## Watermark Section (if enabled)
|
||||
|
||||
```markdown
|
||||
## Watermark
|
||||
|
||||
Include a subtle watermark "{content}" positioned at {position}
|
||||
with approximately {opacity*100}% visibility. The watermark should
|
||||
be legible but not distracting from the main content.
|
||||
```
|
||||
|
||||
## Assembly Process
|
||||
|
||||
### Step 1: Load Preset
|
||||
|
||||
```python
|
||||
preset = load_preset(style_name) # e.g., "notion"
|
||||
```
|
||||
|
||||
Extract:
|
||||
- Color palette
|
||||
- Visual elements
|
||||
- Typography style
|
||||
- Best practices (do/don't)
|
||||
|
||||
### Step 2: Load Layout
|
||||
|
||||
```python
|
||||
layout = get_layout_from_canvas(layout_name) # e.g., "dense"
|
||||
```
|
||||
|
||||
Extract:
|
||||
- Information density guidelines
|
||||
- Whitespace percentage
|
||||
- Structure description
|
||||
- Visual balance rules
|
||||
|
||||
### Step 3: Format Content
|
||||
|
||||
From outline entry, format:
|
||||
- Position context (Cover/Content/Ending)
|
||||
- Text content with hierarchy
|
||||
- Visual concept description
|
||||
- Swipe hook (for context, not in prompt)
|
||||
|
||||
### Step 4: Add Watermark (if applicable)
|
||||
|
||||
If preferences include watermark:
|
||||
- Add watermark section with content, position, opacity
|
||||
|
||||
### Step 5: Combine
|
||||
|
||||
Assemble all sections into final prompt following base structure.
|
||||
|
||||
## Example: Assembled Prompt
|
||||
|
||||
```markdown
|
||||
Create a Xiaohongshu (Little Red Book) style infographic following these guidelines:
|
||||
|
||||
## Image Specifications
|
||||
|
||||
- **Type**: Infographic
|
||||
- **Orientation**: Portrait (vertical)
|
||||
- **Aspect Ratio**: 3:4
|
||||
- **Style**: Hand-drawn illustration
|
||||
|
||||
## Core Principles
|
||||
|
||||
- Hand-drawn quality throughout - NO realistic or photographic elements
|
||||
- If content involves sensitive or copyrighted figures, create stylistically similar alternatives
|
||||
- Keep information concise, highlight keywords and core concepts
|
||||
- Use ample whitespace for easy visual scanning
|
||||
- Maintain clear visual hierarchy
|
||||
|
||||
## Text Style (CRITICAL)
|
||||
|
||||
- **ALL text MUST be hand-drawn style**
|
||||
- Main titles should be prominent and eye-catching
|
||||
- Key text should be bold and enlarged
|
||||
- Use highlighter effects to emphasize keywords
|
||||
- **DO NOT use realistic or computer-generated fonts**
|
||||
|
||||
## Language
|
||||
|
||||
- Use the same language as the content provided below
|
||||
- Match punctuation style to the content language (Chinese: "",。!)
|
||||
|
||||
---
|
||||
|
||||
## Style: Notion
|
||||
|
||||
**Color Palette**:
|
||||
- Primary: Black (#1A1A1A), dark gray (#4A4A4A)
|
||||
- Background: Pure white (#FFFFFF), off-white (#FAFAFA)
|
||||
- Accents: Pastel blue (#A8D4F0), pastel yellow (#F9E79F), pastel pink (#FADBD8)
|
||||
|
||||
**Visual Elements**:
|
||||
- Simple line doodles, hand-drawn wobble effect
|
||||
- Geometric shapes, stick figures
|
||||
- Maximum whitespace, single-weight ink lines
|
||||
- Clean, uncluttered compositions
|
||||
|
||||
**Typography**:
|
||||
- Clean hand-drawn lettering
|
||||
- Simple sans-serif labels
|
||||
- Minimal decoration on text
|
||||
|
||||
---
|
||||
|
||||
## Layout: Dense
|
||||
|
||||
**Information Density**: High (5-8 key points)
|
||||
**Whitespace**: 20-30% of canvas
|
||||
|
||||
**Structure**:
|
||||
- Multiple sections, structured grid
|
||||
- More text, compact but organized
|
||||
- Title + multiple sections with headers + numerous points
|
||||
|
||||
**Visual Balance**:
|
||||
- Organized grid structure
|
||||
- Clear section boundaries
|
||||
- Compact but readable spacing
|
||||
|
||||
---
|
||||
|
||||
## Content
|
||||
|
||||
**Position**: Content (Page 3 of 6)
|
||||
**Core Message**: ChatGPT使用技巧
|
||||
|
||||
**Text Content**:
|
||||
- Title: 「ChatGPT」
|
||||
- Subtitle: 最强AI助手
|
||||
- Points:
|
||||
- 写文案:给出框架,秒出初稿
|
||||
- 改文章:润色、翻译、总结
|
||||
- 编程:写代码、找bug
|
||||
- 学习:解释概念、出题练习
|
||||
|
||||
**Visual Concept**:
|
||||
ChatGPT logo居中,四周放射状展示功能点
|
||||
深色科技背景,霓虹绿点缀
|
||||
|
||||
---
|
||||
|
||||
## Watermark
|
||||
|
||||
Include a subtle watermark "@myxhsaccount" positioned at bottom-right
|
||||
with approximately 50% visibility. The watermark should
|
||||
be legible but not distracting from the main content.
|
||||
|
||||
---
|
||||
|
||||
Please use nano banana pro to generate the infographic based on the specifications above.
|
||||
```
|
||||
|
||||
## Prompt Checklist
|
||||
|
||||
Before generating, verify:
|
||||
|
||||
- [ ] Style section loaded from correct preset
|
||||
- [ ] Layout section matches outline specification
|
||||
- [ ] Content accurately reflects outline entry
|
||||
- [ ] Language matches source content
|
||||
- [ ] Watermark included (if enabled in preferences)
|
||||
- [ ] No conflicting instructions
|
||||
Reference in New Issue
Block a user