mirror of
https://github.com/JimLiu/baoyu-skills.git
synced 2026-07-11 05:31:33 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| db7eaa2847 | |||
| e3d2f5d03f | |||
| da920bb830 | |||
| f49acb9983 | |||
| 3fddcc0e6a | |||
| d4070b19d5 | |||
| 6430c67efe |
@@ -6,7 +6,7 @@
|
||||
},
|
||||
"metadata": {
|
||||
"description": "Skills shared by Baoyu for improving daily work efficiency",
|
||||
"version": "0.3.0"
|
||||
"version": "0.4.2"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
@@ -15,13 +15,13 @@
|
||||
"source": "./",
|
||||
"strict": false,
|
||||
"skills": [
|
||||
"./skills/gemini-web",
|
||||
"./skills/xhs-images",
|
||||
"./skills/post-to-x",
|
||||
"./skills/post-to-wechat",
|
||||
"./skills/article-illustrator",
|
||||
"./skills/cover-image",
|
||||
"./skills/slide-deck"
|
||||
"./skills/baoyu-gemini-web",
|
||||
"./skills/baoyu-xhs-images",
|
||||
"./skills/baoyu-post-to-x",
|
||||
"./skills/baoyu-post-to-wechat",
|
||||
"./skills/baoyu-article-illustrator",
|
||||
"./skills/baoyu-cover-image",
|
||||
"./skills/baoyu-slide-deck"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -139,3 +139,4 @@ vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
tests-data/
|
||||
|
||||
.DS_Store
|
||||
|
||||
@@ -10,12 +10,13 @@ Claude Code marketplace plugin providing AI-powered content generation skills. S
|
||||
|
||||
```
|
||||
skills/
|
||||
├── gemini-web/ # Core: Gemini API wrapper (text + image gen)
|
||||
├── xhs-images/ # Xiaohongshu infographic series (1-10 images)
|
||||
├── cover-image/ # Article cover images (2.35:1 aspect)
|
||||
├── slide-deck/ # Presentation slides with outlines
|
||||
├── article-illustrator/ # Smart illustration placement
|
||||
└── post-to-x/ # X/Twitter posting automation
|
||||
├── baoyu-gemini-web/ # Core: Gemini API wrapper (text + image gen)
|
||||
├── baoyu-xhs-images/ # Xiaohongshu infographic series (1-10 images)
|
||||
├── baoyu-cover-image/ # Article cover images (2.35:1 aspect)
|
||||
├── baoyu-slide-deck/ # Presentation slides with outlines
|
||||
├── baoyu-article-illustrator/ # Smart illustration placement
|
||||
├── baoyu-post-to-x/ # X/Twitter posting automation
|
||||
└── baoyu-post-to-wechat/ # WeChat Official Account posting
|
||||
```
|
||||
|
||||
Each skill contains:
|
||||
@@ -34,24 +35,24 @@ npx -y bun skills/<skill>/scripts/main.ts [options]
|
||||
Examples:
|
||||
```bash
|
||||
# Text generation
|
||||
npx -y bun skills/gemini-web/scripts/main.ts "Hello"
|
||||
npx -y bun skills/baoyu-gemini-web/scripts/main.ts "Hello"
|
||||
|
||||
# Image generation
|
||||
npx -y bun skills/gemini-web/scripts/main.ts --prompt "A cat" --image cat.png
|
||||
npx -y bun skills/baoyu-gemini-web/scripts/main.ts --prompt "A cat" --image cat.png
|
||||
|
||||
# From prompt files
|
||||
npx -y bun skills/gemini-web/scripts/main.ts --promptfiles system.md content.md --image out.png
|
||||
npx -y bun skills/baoyu-gemini-web/scripts/main.ts --promptfiles system.md content.md --image out.png
|
||||
```
|
||||
|
||||
## Key Dependencies
|
||||
|
||||
- **Bun**: TypeScript runtime (via `npx -y bun`)
|
||||
- **Chrome**: Required for `gemini-web` auth and `post-to-x` automation
|
||||
- **Chrome**: Required for `baoyu-gemini-web` auth and `baoyu-post-to-x` automation
|
||||
- **No npm packages**: Self-contained TypeScript, no external dependencies
|
||||
|
||||
## Authentication
|
||||
|
||||
`gemini-web` uses browser cookies for Google auth:
|
||||
`baoyu-gemini-web` uses browser cookies for Google auth:
|
||||
- First run opens Chrome for login
|
||||
- Cookies cached in data directory
|
||||
- Force refresh: `--login` flag
|
||||
@@ -62,10 +63,14 @@ npx -y bun skills/gemini-web/scripts/main.ts --promptfiles system.md content.md
|
||||
|
||||
## Adding New Skills
|
||||
|
||||
1. Create `skills/<name>/SKILL.md` with YAML front matter
|
||||
2. Add TypeScript in `skills/<name>/scripts/`
|
||||
3. Add prompt templates in `skills/<name>/prompts/` if needed
|
||||
4. Register in `marketplace.json` plugins[0].skills array
|
||||
**IMPORTANT**: All skills MUST use `baoyu-` prefix to avoid conflicts when users import this plugin.
|
||||
|
||||
1. Create `skills/baoyu-<name>/SKILL.md` with YAML front matter
|
||||
- Directory name: `baoyu-<name>`
|
||||
- SKILL.md `name` field: `baoyu-<name>`
|
||||
2. Add TypeScript in `skills/baoyu-<name>/scripts/`
|
||||
3. Add prompt templates in `skills/baoyu-<name>/prompts/` if needed
|
||||
4. Register in `marketplace.json` plugins[0].skills array as `./skills/baoyu-<name>`
|
||||
|
||||
## Code Style
|
||||
|
||||
|
||||
@@ -34,6 +34,25 @@ Run the following command in Claude Code:
|
||||
/plugin install content-skills@baoyu-skills
|
||||
```
|
||||
|
||||
**Option 3: Ask the Agent**
|
||||
|
||||
Simply tell Claude Code:
|
||||
|
||||
> Please install Skills from github.com/JimLiu/baoyu-skills
|
||||
|
||||
## Update Skills
|
||||
|
||||
To update skills to the latest version:
|
||||
|
||||
1. Run `/plugin` in Claude Code
|
||||
2. Switch to **Marketplaces** tab (use arrow keys or Tab)
|
||||
3. Select **baoyu-skills**
|
||||
4. Choose **Update marketplace**
|
||||
|
||||
You can also **Enable auto-update** to get the latest versions automatically.
|
||||
|
||||

|
||||
|
||||
## Available Skills
|
||||
|
||||
### gemini-web
|
||||
@@ -56,16 +75,37 @@ Interacts with Gemini Web to generate text and images.
|
||||
|
||||
### xhs-images
|
||||
|
||||
Xiaohongshu (RedNote) infographic series generator. Breaks down content into 1-10 cartoon-style infographics.
|
||||
Xiaohongshu (RedNote) infographic series generator. Breaks down content into 1-10 cartoon-style infographics with **Style × Layout** two-dimensional system.
|
||||
|
||||
```bash
|
||||
# Specify article path
|
||||
# Auto-select style and layout
|
||||
/xhs-images posts/ai-future/article.md
|
||||
|
||||
# Specify style
|
||||
/xhs-images posts/ai-future/article.md --style notion
|
||||
|
||||
# Specify layout
|
||||
/xhs-images posts/ai-future/article.md --layout dense
|
||||
|
||||
# Combine style and layout
|
||||
/xhs-images posts/ai-future/article.md --style tech --layout list
|
||||
|
||||
# Direct content input
|
||||
/xhs-images 今日星座运势
|
||||
```
|
||||
|
||||
**Styles** (visual aesthetics): `cute` (default), `fresh`, `tech`, `warm`, `bold`, `minimal`, `retro`, `pop`, `notion`
|
||||
|
||||
**Layouts** (information density):
|
||||
| Layout | Density | Best for |
|
||||
|--------|---------|----------|
|
||||
| `sparse` | 1-2 pts | Covers, quotes |
|
||||
| `balanced` | 3-4 pts | Regular content |
|
||||
| `dense` | 5-8 pts | Knowledge cards, cheat sheets |
|
||||
| `list` | 4-7 items | Checklists, rankings |
|
||||
| `comparison` | 2 sides | Before/after, pros/cons |
|
||||
| `flow` | 3-6 steps | Processes, timelines |
|
||||
|
||||
### cover-image
|
||||
|
||||
Generate hand-drawn style cover images for articles with multiple style options.
|
||||
@@ -103,7 +143,7 @@ Generate professional slide deck images from content. Creates comprehensive outl
|
||||
/slide-deck path/to/article.md --lang zh
|
||||
```
|
||||
|
||||
Available styles: `editorial` (default), `corporate`, `technical`, `playful`, `minimal`, `storytelling`, `warm`, `retro-flat`
|
||||
Available styles: `editorial` (default), `corporate`, `technical`, `playful`, `minimal`, `storytelling`, `warm`, `retro-flat`, `notion`
|
||||
|
||||
### post-to-wechat
|
||||
|
||||
|
||||
+43
-3
@@ -34,6 +34,25 @@
|
||||
/plugin install content-skills@baoyu-skills
|
||||
```
|
||||
|
||||
**方式三:告诉 Agent**
|
||||
|
||||
直接告诉 Claude Code:
|
||||
|
||||
> 请帮我安装 github.com/JimLiu/baoyu-skills 中的 Skills
|
||||
|
||||
## 更新技能
|
||||
|
||||
更新技能到最新版本:
|
||||
|
||||
1. 在 Claude Code 中运行 `/plugin`
|
||||
2. 切换到 **Marketplaces** 标签页(使用方向键或 Tab)
|
||||
3. 选择 **baoyu-skills**
|
||||
4. 选择 **Update marketplace**
|
||||
|
||||
也可以选择 **Enable auto-update** 启用自动更新,每次启动时自动获取最新版本。
|
||||
|
||||

|
||||
|
||||
## 可用技能
|
||||
|
||||
### gemini-web
|
||||
@@ -56,16 +75,37 @@
|
||||
|
||||
### xhs-images
|
||||
|
||||
小红书信息图系列生成器。将内容拆解为 1-10 张卡通风格信息图。
|
||||
小红书信息图系列生成器。将内容拆解为 1-10 张卡通风格信息图,支持 **风格 × 布局** 二维系统。
|
||||
|
||||
```bash
|
||||
# 指定文章路径
|
||||
# 自动选择风格和布局
|
||||
/xhs-images posts/ai-future/article.md
|
||||
|
||||
# 指定风格
|
||||
/xhs-images posts/ai-future/article.md --style notion
|
||||
|
||||
# 指定布局
|
||||
/xhs-images posts/ai-future/article.md --layout dense
|
||||
|
||||
# 组合风格和布局
|
||||
/xhs-images posts/ai-future/article.md --style tech --layout list
|
||||
|
||||
# 直接输入内容
|
||||
/xhs-images 今日星座运势
|
||||
```
|
||||
|
||||
**风格**(视觉美学):`cute`(默认)、`fresh`、`tech`、`warm`、`bold`、`minimal`、`retro`、`pop`、`notion`
|
||||
|
||||
**布局**(信息密度):
|
||||
| 布局 | 密度 | 适用场景 |
|
||||
|------|------|----------|
|
||||
| `sparse` | 1-2 点 | 封面、金句 |
|
||||
| `balanced` | 3-4 点 | 常规内容 |
|
||||
| `dense` | 5-8 点 | 知识卡片、干货总结 |
|
||||
| `list` | 4-7 项 | 清单、排行 |
|
||||
| `comparison` | 双栏 | 对比、优劣 |
|
||||
| `flow` | 3-6 步 | 流程、时间线 |
|
||||
|
||||
### cover-image
|
||||
|
||||
为文章生成手绘风格封面图,支持多种风格选项。
|
||||
@@ -103,7 +143,7 @@
|
||||
/slide-deck path/to/article.md --lang zh
|
||||
```
|
||||
|
||||
可用风格:`editorial`(默认)、`corporate`、`technical`、`playful`、`minimal`、`storytelling`、`warm`、`retro-flat`
|
||||
可用风格:`editorial`(默认)、`corporate`、`technical`、`playful`、`minimal`、`storytelling`、`warm`、`retro-flat`、`notion`
|
||||
|
||||
### post-to-wechat
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 113 KiB |
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: article-illustrator
|
||||
name: baoyu-article-illustrator
|
||||
description: Smart article illustration skill. Analyzes article content and generates illustrations at positions requiring visual aids with multiple style options. Use when user asks to "add illustrations to article", "generate images for article", or "illustrate article".
|
||||
---
|
||||
|
||||
@@ -11,15 +11,15 @@ Analyze article structure and content, identify positions requiring visual aids,
|
||||
|
||||
```bash
|
||||
# Auto-select style based on content
|
||||
/article-illustrator path/to/article.md
|
||||
/baoyu-article-illustrator path/to/article.md
|
||||
|
||||
# Specify a style
|
||||
/article-illustrator path/to/article.md --style tech
|
||||
/article-illustrator path/to/article.md --style warm
|
||||
/article-illustrator path/to/article.md --style minimal
|
||||
/baoyu-article-illustrator path/to/article.md --style tech
|
||||
/baoyu-article-illustrator path/to/article.md --style warm
|
||||
/baoyu-article-illustrator path/to/article.md --style minimal
|
||||
|
||||
# Combine with other options
|
||||
/article-illustrator path/to/article.md --style playful
|
||||
/baoyu-article-illustrator path/to/article.md --style playful
|
||||
```
|
||||
|
||||
## Options
|
||||
@@ -30,7 +30,7 @@ Analyze article structure and content, identify positions requiring visual aids,
|
||||
|
||||
## Style Gallery
|
||||
|
||||
### 1. `elegant` (Default)
|
||||
### 1. `elegant`
|
||||
Refined, sophisticated, professional
|
||||
- **Colors**: Soft coral, muted teal, dusty rose, cream background
|
||||
- **Elements**: Delicate line work, subtle icons, balanced composition
|
||||
@@ -78,6 +78,12 @@ Raw, authentic, notebook-style
|
||||
- **Elements**: Rough lines, sketch marks, handwritten notes, arrows
|
||||
- **Best for**: Ideas in progress, brainstorming, thought processes
|
||||
|
||||
### 9. `notion` (Default)
|
||||
Minimalist hand-drawn line art, intellectual
|
||||
- **Colors**: Black outlines, white background, 1-2 pastel accents
|
||||
- **Elements**: Simple line doodles, geometric shapes, hand-drawn wobble, maximum whitespace
|
||||
- **Best for**: Knowledge sharing, concept explanations, SaaS content, productivity articles
|
||||
|
||||
## Auto Style Selection
|
||||
|
||||
When no `--style` is specified, analyze content to select the best style:
|
||||
@@ -92,6 +98,7 @@ When no `--style` is specified, analyze content to select the best style:
|
||||
| Nature, eco, wellness, health, organic, green | `nature` |
|
||||
| Idea, thought, concept, draft, brainstorm | `sketch` |
|
||||
| Business, professional, strategy, analysis | `elegant` |
|
||||
| Knowledge, concept, productivity, SaaS, notion | `notion` |
|
||||
|
||||
## File Management
|
||||
|
||||
@@ -194,17 +201,16 @@ Style notes: [specific style characteristics]
|
||||
|
||||
### Step 5: Generate Images
|
||||
|
||||
For each illustration, call:
|
||||
**Image Generation Skill Selection**:
|
||||
1. Check available image generation skills
|
||||
2. If multiple skills available, ask user to choose
|
||||
|
||||
```bash
|
||||
/gemini-web --promptfiles [SKILL_ROOT]/skills/article-illustrator/prompts/system.md [ARTICLE_DIR]/imgs/prompts/illustration-[slug].md --image [ARTICLE_DIR]/imgs/illustration-[slug].png
|
||||
```
|
||||
|
||||
Generation flow:
|
||||
1. Generate images sequentially
|
||||
2. After each image, output progress: "Generated X/N"
|
||||
3. On failure, auto-retry once
|
||||
4. If retry fails, log reason, continue to next
|
||||
**Generation Flow**:
|
||||
1. Call selected image generation skill with prompt file and output path
|
||||
2. Generate images sequentially
|
||||
3. After each image, output progress: "Generated X/N"
|
||||
4. On failure, auto-retry once
|
||||
5. If retry fails, log reason, continue to next
|
||||
|
||||
### Step 6: Update Article
|
||||
|
||||
@@ -304,6 +310,15 @@ Accents: Single highlight color (blue, red, or yellow)
|
||||
Elements: Rough sketch lines, arrows, handwritten labels, crossed-out marks
|
||||
```
|
||||
|
||||
### notion
|
||||
```
|
||||
Colors: Black (#1A1A1A), dark gray (#4A4A4A)
|
||||
Background: Pure white (#FFFFFF), off-white (#FAFAFA)
|
||||
Accents: Pastel blue (#A8D4F0), pastel yellow (#F9E79F), pastel pink (#FADBD8)
|
||||
Elements: Simple line doodles, hand-drawn wobble effect, geometric shapes, stick figures, maximum whitespace
|
||||
Typography: Clean hand-drawn lettering, simple sans-serif labels
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Illustrations serve the content: supplement information, visualize concepts
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: cover-image
|
||||
name: baoyu-cover-image
|
||||
description: Generate elegant cover images for articles. Analyzes content and creates eye-catching hand-drawn style cover images with multiple style options. Use when user asks to "generate cover image", "create article cover", or "make a cover for article".
|
||||
---
|
||||
|
||||
@@ -11,25 +11,25 @@ Generate hand-drawn style cover images for articles with multiple style options.
|
||||
|
||||
```bash
|
||||
# From markdown file (auto-select style based on content)
|
||||
/cover-image path/to/article.md
|
||||
/baoyu-cover-image path/to/article.md
|
||||
|
||||
# Specify a style
|
||||
/cover-image path/to/article.md --style tech
|
||||
/cover-image path/to/article.md --style warm
|
||||
/cover-image path/to/article.md --style bold
|
||||
/baoyu-cover-image path/to/article.md --style tech
|
||||
/baoyu-cover-image path/to/article.md --style warm
|
||||
/baoyu-cover-image path/to/article.md --style bold
|
||||
|
||||
# Without title text
|
||||
/cover-image path/to/article.md --no-title
|
||||
/baoyu-cover-image path/to/article.md --no-title
|
||||
|
||||
# Combine options
|
||||
/cover-image path/to/article.md --style minimal --no-title
|
||||
/baoyu-cover-image path/to/article.md --style minimal --no-title
|
||||
|
||||
# From direct text input
|
||||
/cover-image
|
||||
/baoyu-cover-image
|
||||
[paste content or describe the topic]
|
||||
|
||||
# Direct input with style
|
||||
/cover-image --style playful
|
||||
/baoyu-cover-image --style playful
|
||||
[paste content]
|
||||
```
|
||||
|
||||
@@ -191,11 +191,12 @@ Note: No title text, pure visual illustration only.
|
||||
|
||||
### Step 5: Generate Image
|
||||
|
||||
Call gemini-web to generate the cover:
|
||||
**Image Generation Skill Selection**:
|
||||
1. Check available image generation skills
|
||||
2. If multiple skills available, ask user to choose
|
||||
|
||||
```bash
|
||||
/gemini-web --promptfiles [SKILL_ROOT]/skills/cover-image/prompts/system.md [PROMPT_PATH] --image [OUTPUT_PATH]
|
||||
```
|
||||
**Generation**:
|
||||
Call selected image generation skill with prompt file and output path.
|
||||
|
||||
### Step 6: Output Summary
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: gemini-web
|
||||
description: Interacts with Gemini Web to generate text and images. Use when the user needs AI-generated content via Gemini, including text responses and image generation.
|
||||
name: baoyu-gemini-web
|
||||
description: Image generation skill using Gemini Web. Generates images from text prompts via Google Gemini. Also supports text generation. Use as the image generation backend for other skills like cover-image, xhs-images, article-illustrator.
|
||||
---
|
||||
|
||||
# Gemini Web Client
|
||||
@@ -100,7 +100,7 @@ export async function loadGeminiCookies(
|
||||
}
|
||||
|
||||
log?.(
|
||||
'[gemini-web] Missing Gemini auth cookies. Run `npx -y bun skills/gemini-web/scripts/main.ts --login` to sign in and refresh cookies.',
|
||||
'[gemini-web] Missing Gemini auth cookies. Run `npx -y bun skills/baoyu-gemini-web/scripts/main.ts --login` to sign in and refresh cookies.',
|
||||
);
|
||||
return merged;
|
||||
}
|
||||
@@ -124,7 +124,7 @@ export function createGeminiWebExecutor(
|
||||
const cookieMap = await loadGeminiCookies(runOptions.config, log);
|
||||
if (!hasRequiredGeminiCookies(cookieMap)) {
|
||||
throw new Error(
|
||||
'Gemini browser mode requires auth cookies (missing __Secure-1PSID/__Secure-1PSIDTS). Run `npx -y bun skills/gemini-web/scripts/main.ts --login` to sign in and save cookies.',
|
||||
'Gemini browser mode requires auth cookies (missing __Secure-1PSID/__Secure-1PSIDTS). Run `npx -y bun skills/baoyu-gemini-web/scripts/main.ts --login` to sign in and save cookies.',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ function printUsage(exitCode = 0): never {
|
||||
const profileDir = resolveGeminiWebChromeProfileDir();
|
||||
|
||||
console.log(`Usage:
|
||||
npx -y bun skills/gemini-web/scripts/main.ts --prompt "Hello"
|
||||
npx -y bun skills/gemini-web/scripts/main.ts "Hello"
|
||||
npx -y bun skills/gemini-web/scripts/main.ts --prompt "A cute cat" --image generated.png
|
||||
npx -y bun skills/gemini-web/scripts/main.ts --promptfiles system.md content.md --image out.png
|
||||
npx -y bun skills/baoyu-gemini-web/scripts/main.ts --prompt "Hello"
|
||||
npx -y bun skills/baoyu-gemini-web/scripts/main.ts "Hello"
|
||||
npx -y bun skills/baoyu-gemini-web/scripts/main.ts --prompt "A cute cat" --image generated.png
|
||||
npx -y bun skills/baoyu-gemini-web/scripts/main.ts --promptfiles system.md content.md --image out.png
|
||||
|
||||
Options:
|
||||
-p, --prompt <text> Prompt text
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: post-to-wechat
|
||||
name: baoyu-post-to-wechat
|
||||
description: Post content to WeChat Official Account (微信公众号). Supports both article posting (文章) and image-text posting (图文).
|
||||
---
|
||||
|
||||
@@ -7,25 +7,45 @@ description: Post content to WeChat Official Account (微信公众号). Supports
|
||||
|
||||
Post content to WeChat Official Account using Chrome CDP automation.
|
||||
|
||||
## 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/wechat-browser.ts` | Image-text posts (图文) |
|
||||
| `scripts/wechat-article.ts` | Full article posting (文章) |
|
||||
| `scripts/md-to-wechat.ts` | Markdown → WeChat HTML conversion |
|
||||
| `scripts/copy-to-clipboard.ts` | Copy content to clipboard |
|
||||
| `scripts/paste-from-clipboard.ts` | Send real paste keystroke |
|
||||
|
||||
## Quick Usage
|
||||
|
||||
### Image-Text (图文) - Multiple images with title/content
|
||||
|
||||
```bash
|
||||
# From markdown file and image directory
|
||||
npx -y bun ./scripts/wechat-browser.ts --markdown article.md --images ./images/
|
||||
npx -y bun ${SKILL_DIR}/scripts/wechat-browser.ts --markdown article.md --images ./images/
|
||||
|
||||
# With explicit parameters
|
||||
npx -y bun ./scripts/wechat-browser.ts --title "标题" --content "内容" --image img1.png --image img2.png --submit
|
||||
npx -y bun ${SKILL_DIR}/scripts/wechat-browser.ts --title "标题" --content "内容" --image img1.png --image img2.png --submit
|
||||
```
|
||||
|
||||
### Article (文章) - Full markdown with formatting
|
||||
|
||||
```bash
|
||||
# Post markdown article
|
||||
npx -y bun ./scripts/wechat-article.ts --markdown article.md --theme grace
|
||||
npx -y bun ${SKILL_DIR}/scripts/wechat-article.ts --markdown article.md --theme grace
|
||||
```
|
||||
|
||||
> **Note**: `${SKILL_DIR}` represents this skill's installation directory. Agent replaces with actual path at runtime.
|
||||
|
||||
## References
|
||||
|
||||
- **Image-Text Posting**: See `references/image-text-posting.md` for detailed image-text posting guide
|
||||
@@ -0,0 +1,194 @@
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import process from 'node:process';
|
||||
|
||||
function printUsage(exitCode = 0): never {
|
||||
console.log(`Send real paste keystroke (Cmd+V / Ctrl+V) to the frontmost application
|
||||
|
||||
This bypasses CDP's synthetic events which websites can detect and ignore.
|
||||
|
||||
Usage:
|
||||
npx -y bun paste-from-clipboard.ts [options]
|
||||
|
||||
Options:
|
||||
--retries <n> Number of retry attempts (default: 3)
|
||||
--delay <ms> Delay between retries in ms (default: 500)
|
||||
--app <name> Target application to activate first (macOS only)
|
||||
--help Show this help
|
||||
|
||||
Examples:
|
||||
# Simple paste
|
||||
npx -y bun paste-from-clipboard.ts
|
||||
|
||||
# Paste to Chrome with retries
|
||||
npx -y bun paste-from-clipboard.ts --app "Google Chrome" --retries 5
|
||||
|
||||
# Quick paste with shorter delay
|
||||
npx -y bun paste-from-clipboard.ts --delay 200
|
||||
`);
|
||||
process.exit(exitCode);
|
||||
}
|
||||
|
||||
function sleepSync(ms: number): void {
|
||||
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
||||
}
|
||||
|
||||
function activateApp(appName: string): boolean {
|
||||
if (process.platform !== 'darwin') return false;
|
||||
|
||||
// Activate and wait for app to be frontmost
|
||||
const script = `
|
||||
tell application "${appName}"
|
||||
activate
|
||||
delay 0.5
|
||||
end tell
|
||||
|
||||
-- Verify app is frontmost
|
||||
tell application "System Events"
|
||||
set frontApp to name of first application process whose frontmost is true
|
||||
if frontApp is not "${appName}" then
|
||||
tell application "${appName}" to activate
|
||||
delay 0.3
|
||||
end if
|
||||
end tell
|
||||
`;
|
||||
const result = spawnSync('osascript', ['-e', script], { stdio: 'pipe' });
|
||||
return result.status === 0;
|
||||
}
|
||||
|
||||
function pasteMac(retries: number, delayMs: number, targetApp?: string): boolean {
|
||||
for (let i = 0; i < retries; i++) {
|
||||
// Build script that activates app (if specified) and sends keystroke in one atomic operation
|
||||
const script = targetApp
|
||||
? `
|
||||
tell application "${targetApp}"
|
||||
activate
|
||||
end tell
|
||||
delay 0.3
|
||||
tell application "System Events"
|
||||
keystroke "v" using command down
|
||||
end tell
|
||||
`
|
||||
: `
|
||||
tell application "System Events"
|
||||
keystroke "v" using command down
|
||||
end tell
|
||||
`;
|
||||
|
||||
const result = spawnSync('osascript', ['-e', script], { stdio: 'pipe' });
|
||||
if (result.status === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const stderr = result.stderr?.toString().trim();
|
||||
if (stderr) {
|
||||
console.error(`[paste] osascript error: ${stderr}`);
|
||||
}
|
||||
|
||||
if (i < retries - 1) {
|
||||
console.error(`[paste] Attempt ${i + 1}/${retries} failed, retrying in ${delayMs}ms...`);
|
||||
sleepSync(delayMs);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function pasteLinux(retries: number, delayMs: number): boolean {
|
||||
// Try xdotool first (X11), then ydotool (Wayland)
|
||||
const tools = [
|
||||
{ cmd: 'xdotool', args: ['key', 'ctrl+v'] },
|
||||
{ cmd: 'ydotool', args: ['key', '29:1', '47:1', '47:0', '29:0'] }, // Ctrl down, V down, V up, Ctrl up
|
||||
];
|
||||
|
||||
for (const tool of tools) {
|
||||
const which = spawnSync('which', [tool.cmd], { stdio: 'pipe' });
|
||||
if (which.status !== 0) continue;
|
||||
|
||||
for (let i = 0; i < retries; i++) {
|
||||
const result = spawnSync(tool.cmd, tool.args, { stdio: 'pipe' });
|
||||
if (result.status === 0) {
|
||||
return true;
|
||||
}
|
||||
if (i < retries - 1) {
|
||||
console.error(`[paste] Attempt ${i + 1}/${retries} failed, retrying in ${delayMs}ms...`);
|
||||
sleepSync(delayMs);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
console.error('[paste] No supported tool found. Install xdotool (X11) or ydotool (Wayland).');
|
||||
return false;
|
||||
}
|
||||
|
||||
function pasteWindows(retries: number, delayMs: number): boolean {
|
||||
const ps = `
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
[System.Windows.Forms.SendKeys]::SendWait("^v")
|
||||
`;
|
||||
|
||||
for (let i = 0; i < retries; i++) {
|
||||
const result = spawnSync('powershell.exe', ['-NoProfile', '-Command', ps], { stdio: 'pipe' });
|
||||
if (result.status === 0) {
|
||||
return true;
|
||||
}
|
||||
if (i < retries - 1) {
|
||||
console.error(`[paste] Attempt ${i + 1}/${retries} failed, retrying in ${delayMs}ms...`);
|
||||
sleepSync(delayMs);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function paste(retries: number, delayMs: number, targetApp?: string): boolean {
|
||||
switch (process.platform) {
|
||||
case 'darwin':
|
||||
return pasteMac(retries, delayMs, targetApp);
|
||||
case 'linux':
|
||||
return pasteLinux(retries, delayMs);
|
||||
case 'win32':
|
||||
return pasteWindows(retries, delayMs);
|
||||
default:
|
||||
console.error(`[paste] Unsupported platform: ${process.platform}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
let retries = 3;
|
||||
let delayMs = 500;
|
||||
let targetApp: string | undefined;
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i] ?? '';
|
||||
if (arg === '--help' || arg === '-h') {
|
||||
printUsage(0);
|
||||
}
|
||||
if (arg === '--retries' && args[i + 1]) {
|
||||
retries = parseInt(args[++i]!, 10) || 3;
|
||||
} else if (arg === '--delay' && args[i + 1]) {
|
||||
delayMs = parseInt(args[++i]!, 10) || 500;
|
||||
} else if (arg === '--app' && args[i + 1]) {
|
||||
targetApp = args[++i];
|
||||
} else if (arg.startsWith('-')) {
|
||||
console.error(`Unknown option: ${arg}`);
|
||||
printUsage(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetApp) {
|
||||
console.log(`[paste] Target app: ${targetApp}`);
|
||||
}
|
||||
console.log(`[paste] Sending paste keystroke (retries=${retries}, delay=${delayMs}ms)...`);
|
||||
const success = paste(retries, delayMs, targetApp);
|
||||
|
||||
if (success) {
|
||||
console.log('[paste] Paste keystroke sent successfully');
|
||||
} else {
|
||||
console.error('[paste] Failed to send paste keystroke');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
await main();
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
name: baoyu-post-to-x
|
||||
description: Post content and articles to X (Twitter). Supports regular posts with images and X Articles (long-form Markdown). Uses real Chrome with CDP to bypass anti-automation.
|
||||
---
|
||||
|
||||
# Post to X (Twitter)
|
||||
|
||||
Post content, images, and long-form articles to X using real Chrome browser (bypasses anti-bot detection).
|
||||
|
||||
## 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/x-browser.ts` | Regular posts (text + images) |
|
||||
| `scripts/x-article.ts` | Long-form article publishing (Markdown) |
|
||||
| `scripts/md-to-html.ts` | Markdown → HTML conversion |
|
||||
| `scripts/copy-to-clipboard.ts` | Copy content to clipboard |
|
||||
| `scripts/paste-from-clipboard.ts` | Send real paste keystroke |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Google Chrome or Chromium installed
|
||||
- `bun` installed (for running scripts)
|
||||
- First run: log in to X in the opened browser window
|
||||
|
||||
## References
|
||||
|
||||
- **Regular Posts**: See `references/regular-posts.md` for manual workflow, troubleshooting, and technical details
|
||||
- **X Articles**: See `references/articles.md` for long-form article publishing guide
|
||||
|
||||
---
|
||||
|
||||
## Regular Posts
|
||||
|
||||
Text + up to 4 images.
|
||||
|
||||
```bash
|
||||
# Preview mode (doesn't post)
|
||||
npx -y bun ${SKILL_DIR}/scripts/x-browser.ts "Hello from Claude!" --image ./screenshot.png
|
||||
|
||||
# Actually post
|
||||
npx -y bun ${SKILL_DIR}/scripts/x-browser.ts "Hello!" --image ./photo.png --submit
|
||||
```
|
||||
|
||||
> **Note**: `${SKILL_DIR}` represents this skill's installation directory. Agent replaces with actual path at runtime.
|
||||
|
||||
**Parameters**:
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `<text>` | Post content (positional argument) |
|
||||
| `--image <path>` | Image file path (can be repeated, max 4) |
|
||||
| `--submit` | Actually post (default: preview only) |
|
||||
| `--profile <dir>` | Custom Chrome profile directory |
|
||||
|
||||
---
|
||||
|
||||
## X Articles
|
||||
|
||||
Long-form Markdown articles (requires X Premium).
|
||||
|
||||
```bash
|
||||
# Preview mode
|
||||
npx -y bun ${SKILL_DIR}/scripts/x-article.ts article.md
|
||||
|
||||
# With cover image
|
||||
npx -y bun ${SKILL_DIR}/scripts/x-article.ts article.md --cover ./cover.jpg
|
||||
|
||||
# Publish
|
||||
npx -y bun ${SKILL_DIR}/scripts/x-article.ts article.md --submit
|
||||
```
|
||||
|
||||
**Parameters**:
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `<markdown>` | Markdown file path (positional argument) |
|
||||
| `--cover <path>` | Cover image path |
|
||||
| `--title <text>` | Override article title |
|
||||
| `--submit` | Actually publish (default: preview only) |
|
||||
|
||||
**Frontmatter** (optional):
|
||||
```yaml
|
||||
---
|
||||
title: My Article Title
|
||||
cover_image: /path/to/cover.jpg
|
||||
---
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- First run requires manual login (session is saved)
|
||||
- Always preview before using `--submit`
|
||||
- Browser closes automatically after operation
|
||||
- Supports macOS, Linux, and Windows
|
||||
@@ -0,0 +1,176 @@
|
||||
# X Articles - Detailed Guide
|
||||
|
||||
Publish Markdown articles to X Articles editor with rich text formatting and images.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- X Premium subscription (required for Articles)
|
||||
- Google Chrome installed
|
||||
- `bun` installed
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Publish markdown article (preview mode)
|
||||
npx -y bun ${SKILL_DIR}/scripts/x-article.ts article.md
|
||||
|
||||
# With custom cover image
|
||||
npx -y bun ${SKILL_DIR}/scripts/x-article.ts article.md --cover ./cover.jpg
|
||||
|
||||
# Actually publish
|
||||
npx -y bun ${SKILL_DIR}/scripts/x-article.ts article.md --submit
|
||||
```
|
||||
|
||||
## Markdown Format
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: My Article Title
|
||||
cover_image: /path/to/cover.jpg
|
||||
---
|
||||
|
||||
# Title (becomes article title)
|
||||
|
||||
Regular paragraph text with **bold** and *italic*.
|
||||
|
||||
## Section Header
|
||||
|
||||
More content here.
|
||||
|
||||

|
||||
|
||||
- List item 1
|
||||
- List item 2
|
||||
|
||||
1. Numbered item
|
||||
2. Another item
|
||||
|
||||
> Blockquote text
|
||||
|
||||
[Link text](https://example.com)
|
||||
|
||||
\`\`\`
|
||||
Code blocks become blockquotes (X doesn't support code)
|
||||
\`\`\`
|
||||
```
|
||||
|
||||
## Frontmatter Fields
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `title` | Article title (or uses first H1) |
|
||||
| `cover_image` | Cover image path or URL |
|
||||
| `cover` | Alias for cover_image |
|
||||
| `image` | Alias for cover_image |
|
||||
|
||||
## Image Handling
|
||||
|
||||
1. **Cover Image**: First image or `cover_image` from frontmatter
|
||||
2. **Remote Images**: Automatically downloaded to temp directory
|
||||
3. **Placeholders**: Images in content use `[[IMAGE_PLACEHOLDER_N]]` format
|
||||
4. **Insertion**: Placeholders are found, selected, and replaced with actual images
|
||||
|
||||
## Markdown to HTML Script
|
||||
|
||||
Convert markdown and inspect structure:
|
||||
|
||||
```bash
|
||||
# Get JSON with all metadata
|
||||
npx -y bun ${SKILL_DIR}/scripts/md-to-html.ts article.md
|
||||
|
||||
# Output HTML only
|
||||
npx -y bun ${SKILL_DIR}/scripts/md-to-html.ts article.md --html-only
|
||||
|
||||
# Save HTML to file
|
||||
npx -y bun ${SKILL_DIR}/scripts/md-to-html.ts article.md --save-html /tmp/article.html
|
||||
```
|
||||
|
||||
JSON output:
|
||||
```json
|
||||
{
|
||||
"title": "Article Title",
|
||||
"coverImage": "/path/to/cover.jpg",
|
||||
"contentImages": [
|
||||
{
|
||||
"placeholder": "[[IMAGE_PLACEHOLDER_1]]",
|
||||
"localPath": "/tmp/x-article-images/img.png",
|
||||
"blockIndex": 5
|
||||
}
|
||||
],
|
||||
"html": "<p>Content...</p>",
|
||||
"totalBlocks": 20
|
||||
}
|
||||
```
|
||||
|
||||
## Supported Formatting
|
||||
|
||||
| Markdown | HTML Output |
|
||||
|----------|-------------|
|
||||
| `# H1` | Title only (not in body) |
|
||||
| `## H2` - `###### H6` | `<h2>` |
|
||||
| `**bold**` | `<strong>` |
|
||||
| `*italic*` | `<em>` |
|
||||
| `[text](url)` | `<a href>` |
|
||||
| `> quote` | `<blockquote>` |
|
||||
| `` `code` `` | `<code>` |
|
||||
| ```` ``` ```` | `<blockquote>` (X limitation) |
|
||||
| `- item` | `<ul><li>` |
|
||||
| `1. item` | `<ol><li>` |
|
||||
| `` | Image placeholder |
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Parse Markdown**: Extract title, cover, content images, generate HTML
|
||||
2. **Launch Chrome**: Real browser with CDP, persistent login
|
||||
3. **Navigate**: Open `x.com/compose/articles`
|
||||
4. **Create Article**: Click create button if on list page
|
||||
5. **Upload Cover**: Use file input for cover image
|
||||
6. **Fill Title**: Type title into title field
|
||||
7. **Paste Content**: Copy HTML to clipboard, paste into editor
|
||||
8. **Insert Images**: For each placeholder (reverse order):
|
||||
- Find placeholder text in editor
|
||||
- Select the placeholder
|
||||
- Copy image to clipboard
|
||||
- Paste to replace selection
|
||||
9. **Review**: Browser stays open for 60s preview
|
||||
10. **Publish**: Only with `--submit` flag
|
||||
|
||||
## Example Session
|
||||
|
||||
```
|
||||
User: /post-to-x article ./blog/my-post.md --cover ./thumbnail.png
|
||||
|
||||
Claude:
|
||||
1. Parses markdown: title="My Post", 3 content images
|
||||
2. Launches Chrome with CDP
|
||||
3. Navigates to x.com/compose/articles
|
||||
4. Clicks create button
|
||||
5. Uploads thumbnail.png as cover
|
||||
6. Fills title "My Post"
|
||||
7. Pastes HTML content
|
||||
8. Inserts 3 images at placeholder positions
|
||||
9. Reports: "Article composed. Review and use --submit to publish."
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **No create button**: Ensure X Premium subscription is active
|
||||
- **Cover upload fails**: Check file path and format (PNG, JPEG)
|
||||
- **Images not inserting**: Verify placeholders exist in pasted content
|
||||
- **Content not pasting**: Check HTML clipboard: `npx -y bun ${SKILL_DIR}/scripts/copy-to-clipboard.ts html --file /tmp/test.html`
|
||||
|
||||
## How It Works
|
||||
|
||||
1. `md-to-html.ts` converts Markdown to HTML:
|
||||
- Extracts frontmatter (title, cover)
|
||||
- Converts markdown to HTML
|
||||
- Replaces images with unique placeholders
|
||||
- Downloads remote images locally
|
||||
- Returns structured JSON
|
||||
|
||||
2. `x-article.ts` publishes via CDP:
|
||||
- Launches real Chrome (bypasses detection)
|
||||
- Uses persistent profile (saved login)
|
||||
- Navigates and fills editor via DOM manipulation
|
||||
- Pastes HTML from system clipboard
|
||||
- Finds/selects/replaces each image placeholder
|
||||
@@ -0,0 +1,100 @@
|
||||
# Regular Posts - Detailed Guide
|
||||
|
||||
Detailed documentation for posting text and images to X.
|
||||
|
||||
## Manual Workflow
|
||||
|
||||
If you prefer step-by-step control:
|
||||
|
||||
### Step 1: Copy Image to Clipboard
|
||||
|
||||
```bash
|
||||
npx -y bun ${SKILL_DIR}/scripts/copy-to-clipboard.ts image /path/to/image.png
|
||||
```
|
||||
|
||||
### Step 2: Paste from Clipboard
|
||||
|
||||
```bash
|
||||
# Simple paste to frontmost app
|
||||
npx -y bun ${SKILL_DIR}/scripts/paste-from-clipboard.ts
|
||||
|
||||
# Paste to Chrome with retries
|
||||
npx -y bun ${SKILL_DIR}/scripts/paste-from-clipboard.ts --app "Google Chrome" --retries 5
|
||||
|
||||
# Quick paste with shorter delay
|
||||
npx -y bun ${SKILL_DIR}/scripts/paste-from-clipboard.ts --delay 200
|
||||
```
|
||||
|
||||
### Step 3: Use Playwright MCP (if Chrome session available)
|
||||
|
||||
```bash
|
||||
# Navigate
|
||||
mcp__playwright__browser_navigate url="https://x.com/compose/post"
|
||||
|
||||
# Get element refs
|
||||
mcp__playwright__browser_snapshot
|
||||
|
||||
# Type text
|
||||
mcp__playwright__browser_click element="editor" ref="<ref>"
|
||||
mcp__playwright__browser_type element="editor" ref="<ref>" text="Your content"
|
||||
|
||||
# Paste image (after copying to clipboard)
|
||||
mcp__playwright__browser_press_key key="Meta+v" # macOS
|
||||
# or
|
||||
mcp__playwright__browser_press_key key="Control+v" # Windows/Linux
|
||||
|
||||
# Screenshot to verify
|
||||
mcp__playwright__browser_take_screenshot filename="preview.png"
|
||||
```
|
||||
|
||||
## Image Support
|
||||
|
||||
- Formats: PNG, JPEG, GIF, WebP
|
||||
- Max 4 images per post
|
||||
- Images copied to system clipboard, then pasted via keyboard shortcut
|
||||
|
||||
## Example Session
|
||||
|
||||
```
|
||||
User: /post-to-x "Hello from Claude!" --image ./screenshot.png
|
||||
|
||||
Claude:
|
||||
1. Runs: npx -y bun ${SKILL_DIR}/scripts/x-browser.ts "Hello from Claude!" --image ./screenshot.png
|
||||
2. Chrome opens with X compose page
|
||||
3. Text is typed into editor
|
||||
4. Image is copied to clipboard and pasted
|
||||
5. Browser stays open 30s for preview
|
||||
6. Reports: "Post composed. Use --submit to post."
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Chrome not found**: Set `X_BROWSER_CHROME_PATH` environment variable
|
||||
- **Not logged in**: First run opens Chrome - log in manually, cookies are saved
|
||||
- **Image paste fails**:
|
||||
- Verify clipboard script: `npx -y bun ${SKILL_DIR}/scripts/copy-to-clipboard.ts image <path>`
|
||||
- On macOS, grant "Accessibility" permission to Terminal/iTerm in System Settings > Privacy & Security > Accessibility
|
||||
- Keep Chrome window visible and in front during paste operations
|
||||
- **osascript permission denied**: Grant Terminal accessibility permissions in System Preferences
|
||||
- **Rate limited**: Wait a few minutes before retrying
|
||||
|
||||
## How It Works
|
||||
|
||||
The `x-browser.ts` script uses Chrome DevTools Protocol (CDP) to:
|
||||
1. Launch real Chrome (not Playwright) with `--disable-blink-features=AutomationControlled`
|
||||
2. Use persistent profile directory for saved login sessions
|
||||
3. Interact with X via CDP commands (Runtime.evaluate, Input.dispatchKeyEvent)
|
||||
4. **Paste images using osascript** (macOS): Sends real Cmd+V keystroke to Chrome, bypassing CDP's synthetic events that X can detect
|
||||
|
||||
This approach bypasses X's anti-automation detection that blocks Playwright/Puppeteer.
|
||||
|
||||
### Image Paste Mechanism (macOS)
|
||||
|
||||
CDP's `Input.dispatchKeyEvent` sends "synthetic" keyboard events that websites can detect. X ignores synthetic paste events for security. The solution:
|
||||
|
||||
1. Copy image to system clipboard via Swift/AppKit (`copy-to-clipboard.ts`)
|
||||
2. Bring Chrome to front via `osascript`
|
||||
3. Send real Cmd+V keystroke via `osascript` and System Events
|
||||
4. Wait for upload to complete
|
||||
|
||||
This requires Terminal to have "Accessibility" permission in System Settings.
|
||||
+10
-1
@@ -303,6 +303,7 @@ export async function parseMarkdown(
|
||||
// Resolve image paths (download remote, resolve relative)
|
||||
const contentImages: ImageInfo[] = [];
|
||||
let isFirstImage = true;
|
||||
let coverPlaceholder: string | null = null;
|
||||
|
||||
for (let i = 0; i < images.length; i++) {
|
||||
const img = images[i]!;
|
||||
@@ -311,6 +312,7 @@ export async function parseMarkdown(
|
||||
// First image becomes cover if no cover specified
|
||||
if (isFirstImage && !coverImagePath) {
|
||||
coverImagePath = localPath;
|
||||
coverPlaceholder = `[[IMAGE_PLACEHOLDER_${i + 1}]]`;
|
||||
isFirstImage = false;
|
||||
// Don't add to contentImages, it's the cover
|
||||
continue;
|
||||
@@ -325,6 +327,13 @@ export async function parseMarkdown(
|
||||
});
|
||||
}
|
||||
|
||||
// Remove cover placeholder from HTML if first image was used as cover
|
||||
let finalHtml = html;
|
||||
if (coverPlaceholder) {
|
||||
// Remove the placeholder and its containing <p> tag
|
||||
finalHtml = finalHtml.replace(new RegExp(`<p>${coverPlaceholder.replace(/[[\]]/g, '\\$&')}</p>\\n?`, 'g'), '');
|
||||
}
|
||||
|
||||
// Resolve cover image path
|
||||
let resolvedCoverImage: string | null = null;
|
||||
if (coverImagePath) {
|
||||
@@ -335,7 +344,7 @@ export async function parseMarkdown(
|
||||
title,
|
||||
coverImage: resolvedCoverImage,
|
||||
contentImages,
|
||||
html,
|
||||
html: finalHtml,
|
||||
totalBlocks,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import process from 'node:process';
|
||||
|
||||
function printUsage(exitCode = 0): never {
|
||||
console.log(`Send real paste keystroke (Cmd+V / Ctrl+V) to the frontmost application
|
||||
|
||||
This bypasses CDP's synthetic events which websites can detect and ignore.
|
||||
|
||||
Usage:
|
||||
npx -y bun paste-from-clipboard.ts [options]
|
||||
|
||||
Options:
|
||||
--retries <n> Number of retry attempts (default: 3)
|
||||
--delay <ms> Delay between retries in ms (default: 500)
|
||||
--app <name> Target application to activate first (macOS only)
|
||||
--help Show this help
|
||||
|
||||
Examples:
|
||||
# Simple paste
|
||||
npx -y bun paste-from-clipboard.ts
|
||||
|
||||
# Paste to Chrome with retries
|
||||
npx -y bun paste-from-clipboard.ts --app "Google Chrome" --retries 5
|
||||
|
||||
# Quick paste with shorter delay
|
||||
npx -y bun paste-from-clipboard.ts --delay 200
|
||||
`);
|
||||
process.exit(exitCode);
|
||||
}
|
||||
|
||||
function sleepSync(ms: number): void {
|
||||
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
||||
}
|
||||
|
||||
function activateApp(appName: string): boolean {
|
||||
if (process.platform !== 'darwin') return false;
|
||||
|
||||
// Activate and wait for app to be frontmost
|
||||
const script = `
|
||||
tell application "${appName}"
|
||||
activate
|
||||
delay 0.5
|
||||
end tell
|
||||
|
||||
-- Verify app is frontmost
|
||||
tell application "System Events"
|
||||
set frontApp to name of first application process whose frontmost is true
|
||||
if frontApp is not "${appName}" then
|
||||
tell application "${appName}" to activate
|
||||
delay 0.3
|
||||
end if
|
||||
end tell
|
||||
`;
|
||||
const result = spawnSync('osascript', ['-e', script], { stdio: 'pipe' });
|
||||
return result.status === 0;
|
||||
}
|
||||
|
||||
function pasteMac(retries: number, delayMs: number, targetApp?: string): boolean {
|
||||
for (let i = 0; i < retries; i++) {
|
||||
// Build script that activates app (if specified) and sends keystroke in one atomic operation
|
||||
const script = targetApp
|
||||
? `
|
||||
tell application "${targetApp}"
|
||||
activate
|
||||
end tell
|
||||
delay 0.3
|
||||
tell application "System Events"
|
||||
keystroke "v" using command down
|
||||
end tell
|
||||
`
|
||||
: `
|
||||
tell application "System Events"
|
||||
keystroke "v" using command down
|
||||
end tell
|
||||
`;
|
||||
|
||||
const result = spawnSync('osascript', ['-e', script], { stdio: 'pipe' });
|
||||
if (result.status === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const stderr = result.stderr?.toString().trim();
|
||||
if (stderr) {
|
||||
console.error(`[paste] osascript error: ${stderr}`);
|
||||
}
|
||||
|
||||
if (i < retries - 1) {
|
||||
console.error(`[paste] Attempt ${i + 1}/${retries} failed, retrying in ${delayMs}ms...`);
|
||||
sleepSync(delayMs);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function pasteLinux(retries: number, delayMs: number): boolean {
|
||||
// Try xdotool first (X11), then ydotool (Wayland)
|
||||
const tools = [
|
||||
{ cmd: 'xdotool', args: ['key', 'ctrl+v'] },
|
||||
{ cmd: 'ydotool', args: ['key', '29:1', '47:1', '47:0', '29:0'] }, // Ctrl down, V down, V up, Ctrl up
|
||||
];
|
||||
|
||||
for (const tool of tools) {
|
||||
const which = spawnSync('which', [tool.cmd], { stdio: 'pipe' });
|
||||
if (which.status !== 0) continue;
|
||||
|
||||
for (let i = 0; i < retries; i++) {
|
||||
const result = spawnSync(tool.cmd, tool.args, { stdio: 'pipe' });
|
||||
if (result.status === 0) {
|
||||
return true;
|
||||
}
|
||||
if (i < retries - 1) {
|
||||
console.error(`[paste] Attempt ${i + 1}/${retries} failed, retrying in ${delayMs}ms...`);
|
||||
sleepSync(delayMs);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
console.error('[paste] No supported tool found. Install xdotool (X11) or ydotool (Wayland).');
|
||||
return false;
|
||||
}
|
||||
|
||||
function pasteWindows(retries: number, delayMs: number): boolean {
|
||||
const ps = `
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
[System.Windows.Forms.SendKeys]::SendWait("^v")
|
||||
`;
|
||||
|
||||
for (let i = 0; i < retries; i++) {
|
||||
const result = spawnSync('powershell.exe', ['-NoProfile', '-Command', ps], { stdio: 'pipe' });
|
||||
if (result.status === 0) {
|
||||
return true;
|
||||
}
|
||||
if (i < retries - 1) {
|
||||
console.error(`[paste] Attempt ${i + 1}/${retries} failed, retrying in ${delayMs}ms...`);
|
||||
sleepSync(delayMs);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function paste(retries: number, delayMs: number, targetApp?: string): boolean {
|
||||
switch (process.platform) {
|
||||
case 'darwin':
|
||||
return pasteMac(retries, delayMs, targetApp);
|
||||
case 'linux':
|
||||
return pasteLinux(retries, delayMs);
|
||||
case 'win32':
|
||||
return pasteWindows(retries, delayMs);
|
||||
default:
|
||||
console.error(`[paste] Unsupported platform: ${process.platform}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
let retries = 3;
|
||||
let delayMs = 500;
|
||||
let targetApp: string | undefined;
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i] ?? '';
|
||||
if (arg === '--help' || arg === '-h') {
|
||||
printUsage(0);
|
||||
}
|
||||
if (arg === '--retries' && args[i + 1]) {
|
||||
retries = parseInt(args[++i]!, 10) || 3;
|
||||
} else if (arg === '--delay' && args[i + 1]) {
|
||||
delayMs = parseInt(args[++i]!, 10) || 500;
|
||||
} else if (arg === '--app' && args[i + 1]) {
|
||||
targetApp = args[++i];
|
||||
} else if (arg.startsWith('-')) {
|
||||
console.error(`Unknown option: ${arg}`);
|
||||
printUsage(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetApp) {
|
||||
console.log(`[paste] Target app: ${targetApp}`);
|
||||
}
|
||||
console.log(`[paste] Sending paste keystroke (retries=${retries}, delay=${delayMs}ms)...`);
|
||||
const success = paste(retries, delayMs, targetApp);
|
||||
|
||||
if (success) {
|
||||
console.log('[paste] Paste keystroke sent successfully');
|
||||
} else {
|
||||
console.error('[paste] Failed to send paste keystroke');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
await main();
|
||||
+24
-44
@@ -141,44 +141,30 @@ class CdpConnection {
|
||||
}
|
||||
}
|
||||
|
||||
function getScriptDir(): string {
|
||||
return path.dirname(new URL(import.meta.url).pathname);
|
||||
}
|
||||
|
||||
function copyImageToClipboard(imagePath: string): boolean {
|
||||
const scriptDir = path.dirname(new URL(import.meta.url).pathname);
|
||||
const copyScript = path.join(scriptDir, 'copy-to-clipboard.ts');
|
||||
const copyScript = path.join(getScriptDir(), 'copy-to-clipboard.ts');
|
||||
const result = spawnSync('npx', ['-y', 'bun', copyScript, 'image', imagePath], { stdio: 'inherit' });
|
||||
return result.status === 0;
|
||||
}
|
||||
|
||||
function copyHtmlToClipboard(htmlPath: string): boolean {
|
||||
const scriptDir = path.dirname(new URL(import.meta.url).pathname);
|
||||
const copyScript = path.join(scriptDir, 'copy-to-clipboard.ts');
|
||||
const copyScript = path.join(getScriptDir(), 'copy-to-clipboard.ts');
|
||||
const result = spawnSync('npx', ['-y', 'bun', copyScript, 'html', '--file', htmlPath], { stdio: 'inherit' });
|
||||
return result.status === 0;
|
||||
}
|
||||
|
||||
function sendRealPasteKeystroke(retries = 3): boolean {
|
||||
if (process.platform !== 'darwin') {
|
||||
console.log('[x-article] Real keystroke only supported on macOS');
|
||||
return false;
|
||||
function pasteFromClipboard(targetApp?: string, retries = 3, delayMs = 500): boolean {
|
||||
const pasteScript = path.join(getScriptDir(), 'paste-from-clipboard.ts');
|
||||
const args = ['npx', '-y', 'bun', pasteScript, '--retries', String(retries), '--delay', String(delayMs)];
|
||||
if (targetApp) {
|
||||
args.push('--app', targetApp);
|
||||
}
|
||||
|
||||
// Use osascript to send Cmd+V to frontmost application (Chrome)
|
||||
const script = `
|
||||
tell application "System Events"
|
||||
keystroke "v" using command down
|
||||
end tell
|
||||
`;
|
||||
|
||||
for (let i = 0; i < retries; i++) {
|
||||
const result = spawnSync('osascript', ['-e', script], { stdio: 'pipe' });
|
||||
if (result.status === 0) {
|
||||
return true;
|
||||
}
|
||||
// Wait a bit before retry
|
||||
if (i < retries - 1) {
|
||||
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 500);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
const result = spawnSync(args[0]!, args.slice(1), { stdio: 'inherit' });
|
||||
return result.status === 0;
|
||||
}
|
||||
|
||||
interface ArticleOptions {
|
||||
@@ -300,11 +286,6 @@ export async function publishArticle(options: ArticleOptions): Promise<void> {
|
||||
}, { sessionId });
|
||||
};
|
||||
|
||||
const pasteFromClipboard = async (): Promise<void> => {
|
||||
const modifiers = process.platform === 'darwin' ? 4 : 2; // Meta or Ctrl
|
||||
await pressKey('v', modifiers);
|
||||
};
|
||||
|
||||
// Check if we're on the articles list page (has Write button)
|
||||
console.log('[x-article] Looking for Write button...');
|
||||
const writeButtonFound = await waitForElement('[data-testid="empty_state_button_text"]', 10_000);
|
||||
@@ -538,7 +519,7 @@ export async function publishArticle(options: ArticleOptions): Promise<void> {
|
||||
}, { sessionId });
|
||||
|
||||
// Wait for scroll animation
|
||||
await sleep(300);
|
||||
await sleep(500);
|
||||
|
||||
if (!placeholderFound.result.value) {
|
||||
console.warn(`[x-article] Placeholder not found in DOM: ${img.placeholder}`);
|
||||
@@ -553,25 +534,26 @@ export async function publishArticle(options: ArticleOptions): Promise<void> {
|
||||
continue;
|
||||
}
|
||||
|
||||
await sleep(300);
|
||||
// Wait for clipboard to be fully ready
|
||||
await sleep(800);
|
||||
|
||||
// Delete placeholder by pressing Enter (placeholder is already selected)
|
||||
console.log(`[x-article] Deleting placeholder with Enter...`);
|
||||
await cdp.send('Input.dispatchKeyEvent', { type: 'keyDown', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13 }, { sessionId });
|
||||
await cdp.send('Input.dispatchKeyEvent', { type: 'keyUp', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13 }, { sessionId });
|
||||
await sleep(200);
|
||||
await sleep(300);
|
||||
|
||||
// Paste image
|
||||
// Paste image using paste script (activates Chrome, sends real keystroke)
|
||||
console.log(`[x-article] Pasting image...`);
|
||||
if (sendRealPasteKeystroke()) {
|
||||
if (pasteFromClipboard('Google Chrome', 5, 800)) {
|
||||
console.log(`[x-article] Image pasted: ${path.basename(img.localPath)}`);
|
||||
} else {
|
||||
console.warn(`[x-article] Failed to paste image`);
|
||||
console.warn(`[x-article] Failed to paste image after retries`);
|
||||
}
|
||||
|
||||
// Wait for image to upload
|
||||
console.log(`[x-article] Waiting for upload...`);
|
||||
await sleep(4000);
|
||||
await sleep(5000);
|
||||
}
|
||||
|
||||
console.log('[x-article] All images processed.');
|
||||
@@ -633,17 +615,15 @@ export async function publishArticle(options: ArticleOptions): Promise<void> {
|
||||
console.log('[x-article] Article published!');
|
||||
} else {
|
||||
console.log('[x-article] Article composed (draft mode).');
|
||||
console.log('[x-article] Browser will stay open for 60 seconds for review...');
|
||||
await sleep(60_000);
|
||||
console.log('[x-article] Browser remains open for manual review.');
|
||||
}
|
||||
|
||||
} finally {
|
||||
// Disconnect CDP but keep browser open
|
||||
if (cdp) {
|
||||
try { await cdp.send('Browser.close', {}, { timeoutMs: 5_000 }); } catch {}
|
||||
cdp.close();
|
||||
}
|
||||
setTimeout(() => { if (!chrome.killed) try { chrome.kill('SIGKILL'); } catch {} }, 2_000).unref?.();
|
||||
try { chrome.kill('SIGTERM'); } catch {}
|
||||
// Don't kill Chrome - let user review and close manually
|
||||
}
|
||||
}
|
||||
|
||||
+50
-21
@@ -8,6 +8,26 @@ import process from 'node:process';
|
||||
|
||||
const X_COMPOSE_URL = 'https://x.com/compose/post';
|
||||
|
||||
function getScriptDir(): string {
|
||||
return path.dirname(new URL(import.meta.url).pathname);
|
||||
}
|
||||
|
||||
function copyImageToClipboard(imagePath: string): boolean {
|
||||
const copyScript = path.join(getScriptDir(), 'copy-to-clipboard.ts');
|
||||
const result = spawnSync('npx', ['-y', 'bun', copyScript, 'image', imagePath], { stdio: 'inherit' });
|
||||
return result.status === 0;
|
||||
}
|
||||
|
||||
function pasteFromClipboard(targetApp?: string, retries = 3, delayMs = 500): boolean {
|
||||
const pasteScript = path.join(getScriptDir(), 'paste-from-clipboard.ts');
|
||||
const args = ['npx', '-y', 'bun', pasteScript, '--retries', String(retries), '--delay', String(delayMs)];
|
||||
if (targetApp) {
|
||||
args.push('--app', targetApp);
|
||||
}
|
||||
const result = spawnSync(args[0]!, args.slice(1), { stdio: 'inherit' });
|
||||
return result.status === 0;
|
||||
}
|
||||
|
||||
function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
@@ -274,37 +294,46 @@ export async function postToX(options: XBrowserOptions): Promise<void> {
|
||||
|
||||
console.log(`[x-browser] Pasting image: ${imagePath}`);
|
||||
|
||||
const scriptDir = path.dirname(new URL(import.meta.url).pathname);
|
||||
const copyScript = path.join(scriptDir, 'copy-to-clipboard.ts');
|
||||
|
||||
const result = spawnSync('npx', ['-y', 'bun', copyScript, 'image', imagePath], { stdio: 'inherit' });
|
||||
if (result.status !== 0) {
|
||||
if (!copyImageToClipboard(imagePath)) {
|
||||
console.warn(`[x-browser] Failed to copy image to clipboard: ${imagePath}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wait for clipboard to be ready
|
||||
await sleep(500);
|
||||
|
||||
// Focus the editor
|
||||
await cdp.send('Runtime.evaluate', {
|
||||
expression: `document.querySelector('[data-testid="tweetTextarea_0"]')?.focus()`,
|
||||
}, { sessionId });
|
||||
await sleep(200);
|
||||
|
||||
const modifiers = process.platform === 'darwin' ? 4 : 2;
|
||||
await cdp.send('Input.dispatchKeyEvent', {
|
||||
type: 'keyDown',
|
||||
key: 'v',
|
||||
code: 'KeyV',
|
||||
modifiers,
|
||||
windowsVirtualKeyCode: 86,
|
||||
}, { sessionId });
|
||||
await cdp.send('Input.dispatchKeyEvent', {
|
||||
type: 'keyUp',
|
||||
key: 'v',
|
||||
code: 'KeyV',
|
||||
modifiers,
|
||||
windowsVirtualKeyCode: 86,
|
||||
}, { sessionId });
|
||||
// Use paste script (handles platform differences, activates Chrome)
|
||||
console.log('[x-browser] Pasting from clipboard...');
|
||||
const pasteSuccess = pasteFromClipboard('Google Chrome', 5, 500);
|
||||
|
||||
if (!pasteSuccess) {
|
||||
// Fallback to CDP (may not work for images on X)
|
||||
console.log('[x-browser] Paste script failed, trying CDP fallback...');
|
||||
const modifiers = process.platform === 'darwin' ? 4 : 2;
|
||||
await cdp.send('Input.dispatchKeyEvent', {
|
||||
type: 'keyDown',
|
||||
key: 'v',
|
||||
code: 'KeyV',
|
||||
modifiers,
|
||||
windowsVirtualKeyCode: 86,
|
||||
}, { sessionId });
|
||||
await cdp.send('Input.dispatchKeyEvent', {
|
||||
type: 'keyUp',
|
||||
key: 'v',
|
||||
code: 'KeyV',
|
||||
modifiers,
|
||||
windowsVirtualKeyCode: 86,
|
||||
}, { sessionId });
|
||||
}
|
||||
|
||||
console.log('[x-browser] Waiting for image upload...');
|
||||
await sleep(3000);
|
||||
await sleep(4000);
|
||||
}
|
||||
|
||||
if (submit) {
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: slide-deck
|
||||
name: baoyu-slide-deck
|
||||
description: Generate professional slide deck images from content. Creates comprehensive outlines with style instructions, then generates individual slide images. Use when user asks to "create slides", "make a presentation", "generate deck", or "slide deck".
|
||||
---
|
||||
|
||||
@@ -11,26 +11,26 @@ Transform content into professional slide deck with comprehensive outlines and g
|
||||
|
||||
```bash
|
||||
# From markdown file
|
||||
/slide-deck path/to/article.md
|
||||
/baoyu-slide-deck path/to/article.md
|
||||
|
||||
# With style preference
|
||||
/slide-deck path/to/article.md --style corporate
|
||||
/slide-deck path/to/article.md --style playful
|
||||
/slide-deck path/to/article.md --style technical
|
||||
/baoyu-slide-deck path/to/article.md --style corporate
|
||||
/baoyu-slide-deck path/to/article.md --style playful
|
||||
/baoyu-slide-deck path/to/article.md --style technical
|
||||
|
||||
# With audience specification
|
||||
/slide-deck path/to/article.md --audience beginners
|
||||
/slide-deck path/to/article.md --audience executives
|
||||
/baoyu-slide-deck path/to/article.md --audience beginners
|
||||
/baoyu-slide-deck path/to/article.md --audience executives
|
||||
|
||||
# With language
|
||||
/slide-deck path/to/article.md --lang zh
|
||||
/slide-deck path/to/article.md --lang en
|
||||
/baoyu-slide-deck path/to/article.md --lang zh
|
||||
/baoyu-slide-deck path/to/article.md --lang en
|
||||
|
||||
# Outline only (no image generation)
|
||||
/slide-deck path/to/article.md --outline-only
|
||||
/baoyu-slide-deck path/to/article.md --outline-only
|
||||
|
||||
# Direct content input
|
||||
/slide-deck
|
||||
/baoyu-slide-deck
|
||||
[paste content]
|
||||
```
|
||||
|
||||
@@ -94,6 +94,12 @@ Flat vector illustration with retro palette
|
||||
- **Colors**: Retro muted palette - dusty pink (#E8B4B8), sage green (#A8C686), mustard yellow (#E8B84A), off-white background (#F5F0E6)
|
||||
- **Best for**: Tutorials, explainers, product introductions, educational content
|
||||
|
||||
### 9. `notion`
|
||||
Minimalist hand-drawn line art, intellectual
|
||||
- **Aesthetic**: Simple line doodles with hand-drawn wobble, geometric shapes, maximum whitespace, SaaS product feel
|
||||
- **Colors**: Black outlines (#1A1A1A), white background (#FFFFFF), 1-2 pastel accents (blue #A8D4F0, yellow #F9E79F)
|
||||
- **Best for**: Knowledge sharing, concept explanations, productivity content, SaaS presentations
|
||||
|
||||
## Audience Presets
|
||||
|
||||
| Audience | Approach |
|
||||
@@ -125,7 +131,7 @@ path/to/
|
||||
### Without Article Path
|
||||
|
||||
```
|
||||
./slide-deck-outputs/YYYY-MM-DD/[topic-slug]/
|
||||
./baoyu-slide-deck-outputs/YYYY-MM-DD/[topic-slug]/
|
||||
├── outline.md
|
||||
├── prompts/
|
||||
│ ├── 01-cover.md
|
||||
@@ -152,6 +158,7 @@ path/to/
|
||||
| Research, analysis, thought leadership | `editorial` |
|
||||
| Wellness, healing, cozy, self-care, lifestyle, comfort | `warm` |
|
||||
| Tutorial, explainer, how-to, beginner, product, guide | `retro-flat` |
|
||||
| Knowledge, concept, productivity, SaaS, notion, intellectual | `notion` |
|
||||
|
||||
4. Extract key information:
|
||||
- Core narrative and key messages
|
||||
@@ -265,7 +272,7 @@ Style notes: [specific style characteristics to emphasize]
|
||||
For each slide, generate using:
|
||||
|
||||
```bash
|
||||
/gemini-web --promptfiles [SKILL_ROOT]/skills/slide-deck/prompts/system.md [TARGET_DIR]/prompts/01-cover.md --image [TARGET_DIR]/01-cover.png
|
||||
/baoyu-gemini-web --promptfiles [SKILL_ROOT]/skills/baoyu-slide-deck/prompts/system.md [TARGET_DIR]/prompts/01-cover.md --image [TARGET_DIR]/01-cover.png
|
||||
```
|
||||
|
||||
Generation flow:
|
||||
@@ -389,6 +396,18 @@ Visual Elements: Clear black monoline outlines (uniform width), flat color fills
|
||||
Style Rules: MUST use clear black outlines on all elements, NO 3D effects, NO gradients, simple flat color blocks only
|
||||
```
|
||||
|
||||
### notion
|
||||
```
|
||||
Design Aesthetic: Minimalist hand-drawn line art with intellectual SaaS product feel, Notion-style doodles
|
||||
Background Color: Pure white #FFFFFF, off-white #FAFAFA
|
||||
Primary Font: Clean hand-drawn lettering, simple sans-serif
|
||||
Secondary Font: Simple sans-serif labels
|
||||
Primary Text Color: Black #1A1A1A, dark gray #4A4A4A
|
||||
Primary Accent Color: Pastel blue #A8D4F0, Pastel yellow #F9E79F, Pastel pink #FADBD8
|
||||
Visual Elements: Simple line doodles with hand-drawn wobble effect, geometric shapes, stick figures, maximum whitespace, single-weight ink lines
|
||||
Style Rules: Single color lines (black/dark gray), 1-2 pastel accents only, NO complex gradients, NO heavy shadows, imperfect hand-drawn feel
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
### Design Philosophy
|
||||
@@ -0,0 +1,533 @@
|
||||
---
|
||||
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".
|
||||
---
|
||||
|
||||
# Xiaohongshu Infographic Series Generator
|
||||
|
||||
Break down complex content into eye-catching infographic series for Xiaohongshu with multiple style options.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Auto-select style and layout based on content
|
||||
/baoyu-xhs-images posts/ai-future/article.md
|
||||
|
||||
# Specify style
|
||||
/baoyu-xhs-images posts/ai-future/article.md --style notion
|
||||
|
||||
# Specify layout
|
||||
/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
|
||||
|
||||
# Direct content input
|
||||
/baoyu-xhs-images
|
||||
[paste content]
|
||||
|
||||
# Direct input with options
|
||||
/baoyu-xhs-images --style bold --layout comparison
|
||||
[paste content]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--style <name>` | Visual style (see Style Gallery) |
|
||||
| `--layout <name>` | Information layout (see Layout Gallery) |
|
||||
|
||||
## Two Dimensions
|
||||
|
||||
| Dimension | Controls | Options |
|
||||
|-----------|----------|---------|
|
||||
| **Style** | Visual aesthetics: colors, lines, decorations | cute, fresh, tech, warm, bold, minimal, retro, pop, notion |
|
||||
| **Layout** | Information structure: density, arrangement | sparse, balanced, dense, list, comparison, flow |
|
||||
|
||||
Style × Layout can be freely combined. Example: `--style notion --layout dense` creates an intellectual-looking knowledge card with high information density.
|
||||
|
||||
## Style Gallery
|
||||
|
||||
### 1. `cute` (Default)
|
||||
Sweet, adorable, girly - classic Xiaohongshu aesthetic
|
||||
- **Colors**: Pink, peach, mint, lavender, cream background
|
||||
- **Elements**: Cute stickers, emoji icons, hearts, stars, sparkles
|
||||
- **Best for**: Lifestyle, beauty, fashion, daily tips
|
||||
|
||||
### 2. `fresh`
|
||||
Clean, refreshing, natural
|
||||
- **Colors**: Mint green, sky blue, white, light yellow
|
||||
- **Elements**: Plant icons, clouds, simple shapes, breathing room
|
||||
- **Best for**: Health, wellness, minimalist lifestyle, self-care
|
||||
|
||||
### 3. `tech`
|
||||
Modern, smart, digital
|
||||
- **Colors**: Deep blue, purple, cyan, dark backgrounds with neon accents
|
||||
- **Elements**: Geometric shapes, data icons, circuit patterns, glowing effects
|
||||
- **Best for**: Tech tutorials, AI content, digital tools, productivity
|
||||
|
||||
### 4. `warm`
|
||||
Cozy, friendly, approachable
|
||||
- **Colors**: Warm orange, golden yellow, brown, cream
|
||||
- **Elements**: Sun motifs, coffee cups, cozy illustrations, warm lighting
|
||||
- **Best for**: Personal stories, life lessons, emotional content
|
||||
|
||||
### 5. `bold`
|
||||
High impact, attention-grabbing
|
||||
- **Colors**: Red, orange, black, yellow accents
|
||||
- **Elements**: Strong typography, exclamation marks, arrows, contrast
|
||||
- **Best for**: Important tips, warnings, must-know content
|
||||
|
||||
### 6. `minimal`
|
||||
Ultra-clean, sophisticated
|
||||
- **Colors**: Black, white, single accent color
|
||||
- **Elements**: Maximum whitespace, simple icons, clean lines
|
||||
- **Best for**: Professional content, serious topics, elegant presentations
|
||||
|
||||
### 7. `retro`
|
||||
Vintage, nostalgic, trendy
|
||||
- **Colors**: Muted pastels, sepia, faded tones
|
||||
- **Elements**: Vintage badges, halftone dots, classic typography
|
||||
- **Best for**: Throwback content, classic tips, timeless advice
|
||||
|
||||
### 8. `pop`
|
||||
Vibrant, energetic, eye-catching
|
||||
- **Colors**: Bright primary colors, neon accents, white
|
||||
- **Elements**: Bold shapes, comic-style elements, dynamic compositions
|
||||
- **Best for**: Exciting announcements, fun facts, engaging tutorials
|
||||
|
||||
### 9. `notion`
|
||||
Minimalist hand-drawn line art, intellectual
|
||||
- **Colors**: Black outlines, white background, 1-2 pastel accents
|
||||
- **Elements**: Simple line doodles, geometric shapes, hand-drawn wobble, maximum whitespace
|
||||
- **Best for**: Knowledge sharing, concept explanations, SaaS content, productivity tips
|
||||
|
||||
## Layout Gallery
|
||||
|
||||
### 1. `sparse` (Default)
|
||||
Minimal information, maximum impact
|
||||
- **Density**: 1-2 key points per image
|
||||
- **Whitespace**: 60-70% of canvas
|
||||
- **Structure**: Single focal point, one core message
|
||||
- **Best for**: Covers, quotes, impactful statements, emotional content
|
||||
|
||||
### 2. `balanced`
|
||||
Standard content layout
|
||||
- **Density**: 3-4 key points per image
|
||||
- **Whitespace**: 40-50% of canvas
|
||||
- **Structure**: Title + 3-4 bullet points or sections
|
||||
- **Best for**: Regular content pages, tutorials, explanations
|
||||
|
||||
### 3. `dense`
|
||||
High information density, knowledge card style
|
||||
- **Density**: 5-8 key points per image
|
||||
- **Whitespace**: 20-30% of canvas
|
||||
- **Structure**: Multiple sections, structured grid, more text
|
||||
- **Best for**: Summary cards, cheat sheets, comprehensive guides, 干货总结
|
||||
|
||||
### 4. `list`
|
||||
Enumeration and ranking format
|
||||
- **Density**: 4-7 items
|
||||
- **Whitespace**: 30-40% of canvas
|
||||
- **Structure**: Numbered or bulleted vertical list, consistent item format
|
||||
- **Best for**: Top N lists, checklists, step-by-step guides, rankings
|
||||
|
||||
### 5. `comparison`
|
||||
Side-by-side contrast layout
|
||||
- **Density**: 2 main sections with 2-4 points each
|
||||
- **Whitespace**: 30-40% of canvas
|
||||
- **Structure**: Left vs Right, Before/After, Pros/Cons
|
||||
- **Best for**: Comparisons, transformations, decision helpers, 对比图
|
||||
|
||||
### 6. `flow`
|
||||
Process and timeline layout
|
||||
- **Density**: 3-6 steps/stages
|
||||
- **Whitespace**: 30-40% of canvas
|
||||
- **Structure**: Connected nodes with arrows, sequential flow
|
||||
- **Best for**: Processes, timelines, cause-effect chains, workflows
|
||||
|
||||
## Auto Style Selection
|
||||
|
||||
When no `--style` is specified, analyze content to select:
|
||||
|
||||
| Content Signals | Selected Style |
|
||||
|----------------|----------------|
|
||||
| Beauty, fashion, cute, girl, pink | `cute` |
|
||||
| Health, nature, clean, fresh, organic | `fresh` |
|
||||
| Tech, AI, code, digital, app, tool | `tech` |
|
||||
| Life, story, emotion, feeling, warm | `warm` |
|
||||
| Warning, important, must, critical | `bold` |
|
||||
| Professional, business, elegant, simple | `minimal` |
|
||||
| Classic, vintage, old, traditional | `retro` |
|
||||
| Fun, exciting, wow, amazing | `pop` |
|
||||
| Knowledge, concept, productivity, SaaS, notion | `notion` |
|
||||
|
||||
## Auto Layout Selection
|
||||
|
||||
When no `--layout` is specified, analyze content structure to select:
|
||||
|
||||
| Content Signals | Selected Layout |
|
||||
|----------------|-----------------|
|
||||
| Single quote, one key point, cover | `sparse` |
|
||||
| 3-4 points, explanation, tutorial | `balanced` |
|
||||
| 5+ points, summary, cheat sheet, 干货 | `dense` |
|
||||
| Numbered items, top N, checklist, steps | `list` |
|
||||
| vs, compare, before/after, pros/cons | `comparison` |
|
||||
| Process, flow, timeline, steps with order | `flow` |
|
||||
|
||||
**Layout by Position**:
|
||||
| Position | Recommended Layout |
|
||||
|----------|-------------------|
|
||||
| Cover | `sparse` |
|
||||
| Content | `balanced` or content-appropriate |
|
||||
| Ending | `sparse` or `balanced` |
|
||||
|
||||
## File Management
|
||||
|
||||
### With Article Path
|
||||
|
||||
Save to `xhs-images/` subdirectory in the same folder as the article:
|
||||
|
||||
```
|
||||
posts/ai-future/
|
||||
├── article.md
|
||||
└── xhs-images/
|
||||
├── outline.md
|
||||
├── prompts/
|
||||
│ ├── 01-cover.md
|
||||
│ ├── 02-content-1.md
|
||||
│ └── ...
|
||||
├── 01-cover.png
|
||||
├── 02-content-1.png
|
||||
└── 03-ending.png
|
||||
```
|
||||
|
||||
### Without Article Path
|
||||
|
||||
Save to `xhs-outputs/YYYY-MM-DD/[topic-slug]/`:
|
||||
|
||||
```
|
||||
xhs-outputs/
|
||||
└── 2026-01-13/
|
||||
└── ai-agent-guide/
|
||||
├── outline.md
|
||||
├── prompts/
|
||||
│ ├── 01-cover.md
|
||||
│ └── ...
|
||||
├── 01-cover.png
|
||||
└── 02-ending.png
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1: Analyze Content & Select Style/Layout
|
||||
|
||||
1. Read content
|
||||
2. If `--style` specified, use that style; otherwise auto-select
|
||||
3. If `--layout` specified, use that layout; otherwise auto-select per image
|
||||
4. Determine image count based on content complexity:
|
||||
|
||||
| Content Type | Image Count |
|
||||
|-------------|-------------|
|
||||
| Simple opinion / single topic | 2-3 |
|
||||
| Medium complexity / tutorial | 4-6 |
|
||||
| Deep dive / multi-dimensional | 7-10 |
|
||||
|
||||
**Note**: Layout can vary per image in a series. Cover typically uses `sparse`, content pages use `balanced`/`dense`/`list` as appropriate.
|
||||
|
||||
### Step 2: Generate Outline
|
||||
|
||||
Plan for each image with style and layout specifications:
|
||||
|
||||
```markdown
|
||||
# Xiaohongshu Infographic Series Outline
|
||||
|
||||
**Topic**: [topic description]
|
||||
**Style**: [selected style]
|
||||
**Default Layout**: [selected layout or "varies"]
|
||||
**Image Count**: N
|
||||
**Generated**: YYYY-MM-DD HH:mm
|
||||
|
||||
---
|
||||
|
||||
## Image 1 of N
|
||||
|
||||
**Position**: Cover
|
||||
**Layout**: sparse
|
||||
**Core Message**: [one-liner]
|
||||
**Filename**: 01-cover.png
|
||||
|
||||
**Text Content**:
|
||||
- Title: xxx
|
||||
- Subtitle: xxx
|
||||
|
||||
**Visual Concept**: [style + layout appropriate description]
|
||||
|
||||
---
|
||||
|
||||
## Image 2 of N
|
||||
|
||||
**Position**: Content
|
||||
**Layout**: [balanced/dense/list/comparison/flow]
|
||||
**Core Message**: [one-liner]
|
||||
**Filename**: 02-xxx.png
|
||||
|
||||
**Text Content**:
|
||||
- Title: xxx
|
||||
- Points: [list based on layout density]
|
||||
|
||||
**Visual Concept**: [description matching style + layout]
|
||||
|
||||
---
|
||||
...
|
||||
```
|
||||
|
||||
### Step 3: Save Outline
|
||||
|
||||
Save outline as `outline.md`.
|
||||
|
||||
### Step 4: Generate Images One by One
|
||||
|
||||
For each image, create a prompt file with style and layout specifications.
|
||||
|
||||
**Prompt Format**:
|
||||
|
||||
```markdown
|
||||
Infographic theme: [topic]
|
||||
Style: [style name]
|
||||
Layout: [layout name]
|
||||
Position: [cover/content/ending]
|
||||
|
||||
Visual composition:
|
||||
- Main visual: [style-appropriate description]
|
||||
- Arrangement: [layout-specific structure]
|
||||
- Decorative elements: [style-specific decorations]
|
||||
|
||||
Color scheme:
|
||||
- Primary: [style primary color]
|
||||
- Background: [style background color]
|
||||
- Accent: [style accent color]
|
||||
|
||||
Text content:
|
||||
- Title: 「xxx」(large, prominent)
|
||||
- Key points: [based on layout density]
|
||||
|
||||
Layout instructions: [layout-specific guidance]
|
||||
Style notes: [style-specific characteristics]
|
||||
```
|
||||
|
||||
**Layout-Specific Instructions**:
|
||||
|
||||
| Layout | Arrangement Instructions |
|
||||
|--------|-------------------------|
|
||||
| `sparse` | Single focal point centered, 1-2 text elements, maximum breathing room |
|
||||
| `balanced` | Title at top, 3-4 points in clear sections, moderate spacing |
|
||||
| `dense` | Grid or multi-section layout, 5-8 points, compact but organized |
|
||||
| `list` | Vertical numbered/bulleted list, consistent item spacing, clear hierarchy |
|
||||
| `comparison` | Two-column split, clear divider, mirrored structure left/right |
|
||||
| `flow` | Horizontal or vertical flow with arrows, connected nodes/steps |
|
||||
|
||||
**Image Generation Skill Selection**:
|
||||
1. Check available image generation skills
|
||||
2. If multiple skills available, ask user to choose
|
||||
|
||||
**Generation Flow**:
|
||||
1. Call selected image generation skill with prompt file and output path
|
||||
2. Confirm generation success
|
||||
3. Report progress: "Generated X/N"
|
||||
4. Continue to next
|
||||
|
||||
### Step 5: Completion Report
|
||||
|
||||
```
|
||||
Xiaohongshu Infographic Series Complete!
|
||||
|
||||
Topic: [topic]
|
||||
Style: [style name]
|
||||
Layout: [layout name or "varies"]
|
||||
Location: [directory path]
|
||||
Images: N total
|
||||
|
||||
- 01-cover.png ✓ Cover (sparse)
|
||||
- 02-content-1.png ✓ Content (balanced)
|
||||
- 03-content-2.png ✓ Content (dense)
|
||||
- 04-ending.png ✓ Ending (sparse)
|
||||
|
||||
Outline: outline.md
|
||||
```
|
||||
|
||||
## Style Reference Details
|
||||
|
||||
### cute
|
||||
```
|
||||
Colors: Pink (#FED7E2), peach (#FEEBC8), mint (#C6F6D5), lavender (#E9D8FD)
|
||||
Background: Cream (#FFFAF0), soft pink (#FFF5F7)
|
||||
Accents: Hot pink, coral
|
||||
Elements: Hearts, stars, sparkles, cute faces, ribbon decorations, sticker-style
|
||||
Typography: Rounded, bubbly hand lettering
|
||||
```
|
||||
|
||||
### fresh
|
||||
```
|
||||
Colors: Mint green (#9AE6B4), sky blue (#90CDF4), light yellow (#FAF089)
|
||||
Background: Pure white (#FFFFFF), soft mint (#F0FFF4)
|
||||
Accents: Leaf green, water blue
|
||||
Elements: Plant leaves, clouds, water drops, simple geometric shapes
|
||||
Typography: Clean, light hand lettering with breathing room
|
||||
```
|
||||
|
||||
### tech
|
||||
```
|
||||
Colors: Deep blue (#1A365D), purple (#6B46C1), cyan (#00D4FF)
|
||||
Background: Dark gray (#1A202C), near-black (#0D1117)
|
||||
Accents: Neon green (#00FF88), electric blue
|
||||
Elements: Circuit patterns, data icons, geometric grids, glowing effects
|
||||
Typography: Monospace-style hand lettering, subtle glow
|
||||
```
|
||||
|
||||
### warm
|
||||
```
|
||||
Colors: Warm orange (#ED8936), golden yellow (#F6AD55), terracotta (#C05621)
|
||||
Background: Cream (#FFFAF0), soft peach (#FED7AA)
|
||||
Accents: Deep brown (#744210), soft red
|
||||
Elements: Sun rays, coffee cups, cozy items, warm lighting effects
|
||||
Typography: Friendly, rounded hand lettering
|
||||
```
|
||||
|
||||
### bold
|
||||
```
|
||||
Colors: Vibrant red (#E53E3E), orange (#DD6B20), yellow (#F6E05E)
|
||||
Background: Deep black (#000000), dark charcoal
|
||||
Accents: White, neon yellow
|
||||
Elements: Exclamation marks, arrows, warning icons, strong shapes
|
||||
Typography: Bold, impactful hand lettering with shadows
|
||||
```
|
||||
|
||||
### minimal
|
||||
```
|
||||
Colors: Black (#000000), white (#FFFFFF)
|
||||
Background: Off-white (#FAFAFA), pure white
|
||||
Accents: Single color (content-derived - blue, green, or coral)
|
||||
Elements: Single focal point, thin lines, maximum whitespace
|
||||
Typography: Clean, simple hand lettering
|
||||
```
|
||||
|
||||
### retro
|
||||
```
|
||||
Colors: Muted orange, dusty pink (#FED7E2 at 70%), faded teal
|
||||
Background: Aged paper (#F5E6D3), sepia tones
|
||||
Accents: Faded red, vintage gold
|
||||
Elements: Halftone dots, vintage badges, classic icons, tape effects
|
||||
Typography: Vintage-style hand lettering, classic feel
|
||||
```
|
||||
|
||||
### pop
|
||||
```
|
||||
Colors: Bright red (#F56565), yellow (#ECC94B), blue (#4299E1), green (#48BB78)
|
||||
Background: White (#FFFFFF), light gray
|
||||
Accents: Neon pink, electric purple
|
||||
Elements: Bold shapes, speech bubbles, comic-style effects, starburst
|
||||
Typography: Dynamic, energetic hand lettering with outlines
|
||||
```
|
||||
|
||||
### notion
|
||||
```
|
||||
Colors: Black (#1A1A1A), dark gray (#4A4A4A)
|
||||
Background: Pure white (#FFFFFF), off-white (#FAFAFA)
|
||||
Accents: Pastel blue (#A8D4F0), pastel yellow (#F9E79F), pastel pink (#FADBD8)
|
||||
Elements: Simple line doodles, hand-drawn wobble effect, geometric shapes, stick figures, maximum whitespace
|
||||
Typography: Clean hand-drawn lettering, simple sans-serif labels
|
||||
```
|
||||
|
||||
## Layout Reference Details
|
||||
|
||||
### sparse
|
||||
```
|
||||
Information Density: Very Low (1-2 points)
|
||||
Whitespace: 60-70%
|
||||
Structure: Single centered focal point
|
||||
Text Elements: Title only, or title + one subtitle/tagline
|
||||
Visual Balance: Centered, symmetrical, breathing room on all sides
|
||||
Best Pairing: Any style, especially effective with bold, minimal, notion
|
||||
```
|
||||
|
||||
### balanced
|
||||
```
|
||||
Information Density: Medium (3-4 points)
|
||||
Whitespace: 40-50%
|
||||
Structure: Title at top, content sections below
|
||||
Text Elements: Title + 3-4 bullet points or key messages
|
||||
Visual Balance: Top-weighted title, evenly distributed content below
|
||||
Best Pairing: All styles work well
|
||||
```
|
||||
|
||||
### dense
|
||||
```
|
||||
Information Density: High (5-8 points)
|
||||
Whitespace: 20-30%
|
||||
Structure: Multi-section grid or stacked blocks
|
||||
Text Elements: Title + multiple sections with headers + numerous points
|
||||
Visual Balance: Organized chaos, clear section boundaries, compact spacing
|
||||
Best Pairing: tech, notion, minimal (clean styles prevent visual overload)
|
||||
```
|
||||
|
||||
### list
|
||||
```
|
||||
Information Density: Medium-High (4-7 items)
|
||||
Whitespace: 30-40%
|
||||
Structure: Vertical enumeration with numbers or bullets
|
||||
Text Elements: Title + numbered/bulleted items, consistent format per item
|
||||
Visual Balance: Left-aligned list, clear number/bullet hierarchy
|
||||
Best Pairing: All styles, especially cute (checklist), bold (rankings)
|
||||
```
|
||||
|
||||
### comparison
|
||||
```
|
||||
Information Density: Medium (2×2-4 points)
|
||||
Whitespace: 30-40%
|
||||
Structure: Two-column split with center divider
|
||||
Text Elements: Title + left label + right label + mirrored points
|
||||
Visual Balance: Symmetrical left/right, clear visual contrast
|
||||
Best Pairing: bold (dramatic contrast), tech (data comparison), warm (before/after stories)
|
||||
```
|
||||
|
||||
### flow
|
||||
```
|
||||
Information Density: Medium (3-6 steps)
|
||||
Whitespace: 30-40%
|
||||
Structure: Connected nodes with directional arrows
|
||||
Text Elements: Title + step labels + optional descriptions per step
|
||||
Visual Balance: Directional flow (top→bottom or left→right), clear progression
|
||||
Best Pairing: tech (process diagrams), notion (simple flows), fresh (organic flows)
|
||||
```
|
||||
|
||||
## Content Breakdown Principles
|
||||
|
||||
1. **Cover (Image 1)**: Strong visual impact, core title, attention hook → `sparse` layout
|
||||
2. **Content (Middle)**: Core points per image, density varies by content → `balanced`/`dense`/`list`/`comparison`/`flow`
|
||||
3. **Ending (Last)**: Summary / call-to-action / memorable quote → `sparse` or `balanced`
|
||||
|
||||
**Style × Layout Matrix** (recommended combinations):
|
||||
|
||||
| | sparse | balanced | dense | list | comparison | flow |
|
||||
|---|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
| cute | ✓✓ | ✓✓ | ✓ | ✓✓ | ✓ | ✓ |
|
||||
| fresh | ✓✓ | ✓✓ | ✓ | ✓ | ✓ | ✓✓ |
|
||||
| tech | ✓ | ✓✓ | ✓✓ | ✓✓ | ✓✓ | ✓✓ |
|
||||
| warm | ✓✓ | ✓✓ | ✓ | ✓ | ✓✓ | ✓ |
|
||||
| bold | ✓✓ | ✓ | ✓ | ✓✓ | ✓✓ | ✓ |
|
||||
| minimal | ✓✓ | ✓✓ | ✓✓ | ✓ | ✓ | ✓ |
|
||||
| retro | ✓✓ | ✓✓ | ✓ | ✓✓ | ✓ | ✓ |
|
||||
| pop | ✓✓ | ✓✓ | ✓ | ✓✓ | ✓✓ | ✓ |
|
||||
| notion | ✓✓ | ✓✓ | ✓✓ | ✓✓ | ✓✓ | ✓✓ |
|
||||
|
||||
✓✓ = highly recommended, ✓ = works well
|
||||
|
||||
## Notes
|
||||
|
||||
- Image generation typically takes 10-30 seconds per image
|
||||
- Auto-retry once on generation failure
|
||||
- Use cartoon alternatives for sensitive public figures
|
||||
- Output language matches input content language
|
||||
- Maintain selected style consistency across all images in series
|
||||
@@ -1,339 +0,0 @@
|
||||
---
|
||||
name: post-to-x
|
||||
description: Post content and articles to X (Twitter). Supports regular posts with images and X Articles (long-form Markdown). Uses real Chrome with CDP to bypass anti-automation.
|
||||
---
|
||||
|
||||
# Post to X (Twitter)
|
||||
|
||||
Post content, images, and long-form articles to X using real Chrome browser (bypasses anti-bot detection).
|
||||
|
||||
## Features
|
||||
|
||||
- **Regular Posts**: Text + up to 4 images
|
||||
- **X Articles**: Publish Markdown files with rich formatting and images (requires X Premium)
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Post text only
|
||||
/post-to-x "Your post content here"
|
||||
|
||||
# Post with image
|
||||
/post-to-x "Your post content" --image /path/to/image.png
|
||||
|
||||
# Post with multiple images (up to 4)
|
||||
/post-to-x "Your post content" --image img1.png --image img2.png
|
||||
|
||||
# Actually submit the post
|
||||
/post-to-x "Your post content" --submit
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Google Chrome or Chromium installed
|
||||
- `bun` installed (for running scripts)
|
||||
- First run: log in to X in the opened browser window
|
||||
|
||||
## Quick Start (Recommended)
|
||||
|
||||
Use the `x-browser.ts` script directly:
|
||||
|
||||
```bash
|
||||
# Preview mode (doesn't post)
|
||||
npx -y bun ./scripts/x-browser.ts "Hello from Claude!" --image ./screenshot.png
|
||||
|
||||
# Actually post
|
||||
npx -y bun ./scripts/x-browser.ts "Hello!" --image ./photo.png --submit
|
||||
```
|
||||
|
||||
The script:
|
||||
1. Launches real Chrome with anti-detection disabled
|
||||
2. Uses persistent profile (only need to log in once)
|
||||
3. Types text and pastes images via CDP
|
||||
4. Waits 30s for preview (or posts immediately with `--submit`)
|
||||
|
||||
## Manual Workflow
|
||||
|
||||
If you prefer step-by-step control:
|
||||
|
||||
### Step 1: Copy Image to Clipboard
|
||||
|
||||
```bash
|
||||
npx -y bun ./scripts/copy-to-clipboard.ts image /path/to/image.png
|
||||
```
|
||||
|
||||
### Step 2: Use Playwright MCP (if Chrome session available)
|
||||
|
||||
```bash
|
||||
# Navigate
|
||||
mcp__playwright__browser_navigate url="https://x.com/compose/post"
|
||||
|
||||
# Get element refs
|
||||
mcp__playwright__browser_snapshot
|
||||
|
||||
# Type text
|
||||
mcp__playwright__browser_click element="editor" ref="<ref>"
|
||||
mcp__playwright__browser_type element="editor" ref="<ref>" text="Your content"
|
||||
|
||||
# Paste image (after copying to clipboard)
|
||||
mcp__playwright__browser_press_key key="Meta+v" # macOS
|
||||
# or
|
||||
mcp__playwright__browser_press_key key="Control+v" # Windows/Linux
|
||||
|
||||
# Screenshot to verify
|
||||
mcp__playwright__browser_take_screenshot filename="preview.png"
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `<text>` | Post content (positional argument) |
|
||||
| `--image <path>` | Image file path (can be repeated, max 4) |
|
||||
| `--submit` | Actually post (default: preview only) |
|
||||
| `--profile <dir>` | Custom Chrome profile directory |
|
||||
|
||||
## Image Support
|
||||
|
||||
- Formats: PNG, JPEG, GIF, WebP
|
||||
- Max 4 images per post
|
||||
- Images copied to system clipboard, then pasted via keyboard shortcut
|
||||
|
||||
## Example Session
|
||||
|
||||
```
|
||||
User: /post-to-x "Hello from Claude!" --image ./screenshot.png
|
||||
|
||||
Claude:
|
||||
1. Runs: npx -y bun ./scripts/x-browser.ts "Hello from Claude!" --image ./screenshot.png
|
||||
2. Chrome opens with X compose page
|
||||
3. Text is typed into editor
|
||||
4. Image is copied to clipboard and pasted
|
||||
5. Browser stays open 30s for preview
|
||||
6. Reports: "Post composed. Use --submit to post."
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Chrome not found**: Set `X_BROWSER_CHROME_PATH` environment variable
|
||||
- **Not logged in**: First run opens Chrome - log in manually, cookies are saved
|
||||
- **Image paste fails**: Verify clipboard script: `npx -y bun ./scripts/copy-to-clipboard.ts image <path>`
|
||||
- **Rate limited**: Wait a few minutes before retrying
|
||||
|
||||
## How It Works
|
||||
|
||||
The `x-browser.ts` script uses Chrome DevTools Protocol (CDP) to:
|
||||
1. Launch real Chrome (not Playwright) with `--disable-blink-features=AutomationControlled`
|
||||
2. Use persistent profile directory for saved login sessions
|
||||
3. Interact with X via CDP commands (Runtime.evaluate, Input.dispatchKeyEvent)
|
||||
4. Paste images from system clipboard
|
||||
|
||||
This approach bypasses X's anti-automation detection that blocks Playwright/Puppeteer.
|
||||
|
||||
## Notes
|
||||
|
||||
- First run requires manual login (session is saved)
|
||||
- Always preview before using `--submit`
|
||||
- Browser closes automatically after operation
|
||||
- Supports macOS, Linux, and Windows
|
||||
|
||||
---
|
||||
|
||||
# X Articles (Long-form Publishing)
|
||||
|
||||
Publish Markdown articles to X Articles editor with rich text formatting and images.
|
||||
|
||||
## X Article Usage
|
||||
|
||||
```bash
|
||||
# Publish markdown article (preview mode)
|
||||
/post-to-x article /path/to/article.md
|
||||
|
||||
# With custom cover image
|
||||
/post-to-x article article.md --cover ./hero.png
|
||||
|
||||
# With custom title
|
||||
/post-to-x article article.md --title "My Custom Title"
|
||||
|
||||
# Actually publish (not just draft)
|
||||
/post-to-x article article.md --submit
|
||||
```
|
||||
|
||||
## Prerequisites for Articles
|
||||
|
||||
- X Premium subscription (required for Articles)
|
||||
- Google Chrome installed
|
||||
- `bun` installed
|
||||
|
||||
## Article Script
|
||||
|
||||
Use `x-article.ts` directly:
|
||||
|
||||
```bash
|
||||
npx -y bun ./scripts/x-article.ts article.md
|
||||
npx -y bun ./scripts/x-article.ts article.md --cover ./cover.jpg
|
||||
npx -y bun ./scripts/x-article.ts article.md --submit
|
||||
```
|
||||
|
||||
## Markdown Format
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: My Article Title
|
||||
cover_image: /path/to/cover.jpg
|
||||
---
|
||||
|
||||
# Title (becomes article title)
|
||||
|
||||
Regular paragraph text with **bold** and *italic*.
|
||||
|
||||
## Section Header
|
||||
|
||||
More content here.
|
||||
|
||||

|
||||
|
||||
- List item 1
|
||||
- List item 2
|
||||
|
||||
1. Numbered item
|
||||
2. Another item
|
||||
|
||||
> Blockquote text
|
||||
|
||||
[Link text](https://example.com)
|
||||
|
||||
\`\`\`
|
||||
Code blocks become blockquotes (X doesn't support code)
|
||||
\`\`\`
|
||||
```
|
||||
|
||||
## Frontmatter Fields
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `title` | Article title (or uses first H1) |
|
||||
| `cover_image` | Cover image path or URL |
|
||||
| `cover` | Alias for cover_image |
|
||||
| `image` | Alias for cover_image |
|
||||
|
||||
## Image Handling
|
||||
|
||||
1. **Cover Image**: First image or `cover_image` from frontmatter
|
||||
2. **Remote Images**: Automatically downloaded to temp directory
|
||||
3. **Placeholders**: Images in content use `[[IMAGE_PLACEHOLDER_N]]` format
|
||||
4. **Insertion**: Placeholders are found, selected, and replaced with actual images
|
||||
|
||||
## Markdown to HTML Script
|
||||
|
||||
Convert markdown and inspect structure:
|
||||
|
||||
```bash
|
||||
# Get JSON with all metadata
|
||||
npx -y bun ./scripts/md-to-html.ts article.md
|
||||
|
||||
# Output HTML only
|
||||
npx -y bun ./scripts/md-to-html.ts article.md --html-only
|
||||
|
||||
# Save HTML to file
|
||||
npx -y bun ./scripts/md-to-html.ts article.md --save-html /tmp/article.html
|
||||
```
|
||||
|
||||
JSON output:
|
||||
```json
|
||||
{
|
||||
"title": "Article Title",
|
||||
"coverImage": "/path/to/cover.jpg",
|
||||
"contentImages": [
|
||||
{
|
||||
"placeholder": "[[IMAGE_PLACEHOLDER_1]]",
|
||||
"localPath": "/tmp/x-article-images/img.png",
|
||||
"blockIndex": 5
|
||||
}
|
||||
],
|
||||
"html": "<p>Content...</p>",
|
||||
"totalBlocks": 20
|
||||
}
|
||||
```
|
||||
|
||||
## Supported Formatting
|
||||
|
||||
| Markdown | HTML Output |
|
||||
|----------|-------------|
|
||||
| `# H1` | Title only (not in body) |
|
||||
| `## H2` - `###### H6` | `<h2>` |
|
||||
| `**bold**` | `<strong>` |
|
||||
| `*italic*` | `<em>` |
|
||||
| `[text](url)` | `<a href>` |
|
||||
| `> quote` | `<blockquote>` |
|
||||
| `` `code` `` | `<code>` |
|
||||
| ```` ``` ```` | `<blockquote>` (X limitation) |
|
||||
| `- item` | `<ul><li>` |
|
||||
| `1. item` | `<ol><li>` |
|
||||
| `` | Image placeholder |
|
||||
|
||||
## Article Workflow
|
||||
|
||||
1. **Parse Markdown**: Extract title, cover, content images, generate HTML
|
||||
2. **Launch Chrome**: Real browser with CDP, persistent login
|
||||
3. **Navigate**: Open `x.com/compose/articles`
|
||||
4. **Create Article**: Click create button if on list page
|
||||
5. **Upload Cover**: Use file input for cover image
|
||||
6. **Fill Title**: Type title into title field
|
||||
7. **Paste Content**: Copy HTML to clipboard, paste into editor
|
||||
8. **Insert Images**: For each placeholder (reverse order):
|
||||
- Find placeholder text in editor
|
||||
- Select the placeholder
|
||||
- Copy image to clipboard
|
||||
- Paste to replace selection
|
||||
9. **Review**: Browser stays open for 60s preview
|
||||
10. **Publish**: Only with `--submit` flag
|
||||
|
||||
## Article Example Session
|
||||
|
||||
```
|
||||
User: /post-to-x article ./blog/my-post.md --cover ./thumbnail.png
|
||||
|
||||
Claude:
|
||||
1. Parses markdown: title="My Post", 3 content images
|
||||
2. Launches Chrome with CDP
|
||||
3. Navigates to x.com/compose/articles
|
||||
4. Clicks create button
|
||||
5. Uploads thumbnail.png as cover
|
||||
6. Fills title "My Post"
|
||||
7. Pastes HTML content
|
||||
8. Inserts 3 images at placeholder positions
|
||||
9. Reports: "Article composed. Review and use --submit to publish."
|
||||
```
|
||||
|
||||
## Article Troubleshooting
|
||||
|
||||
- **No create button**: Ensure X Premium subscription is active
|
||||
- **Cover upload fails**: Check file path and format (PNG, JPEG)
|
||||
- **Images not inserting**: Verify placeholders exist in pasted content
|
||||
- **Content not pasting**: Check HTML clipboard: `npx -y bun ./scripts/copy-to-clipboard.ts html --file /tmp/test.html`
|
||||
|
||||
## How Article Publishing Works
|
||||
|
||||
1. `md-to-html.ts` converts Markdown to HTML:
|
||||
- Extracts frontmatter (title, cover)
|
||||
- Converts markdown to HTML
|
||||
- Replaces images with unique placeholders
|
||||
- Downloads remote images locally
|
||||
- Returns structured JSON
|
||||
|
||||
2. `x-article.ts` publishes via CDP:
|
||||
- Launches real Chrome (bypasses detection)
|
||||
- Uses persistent profile (saved login)
|
||||
- Navigates and fills editor via DOM manipulation
|
||||
- Pastes HTML from system clipboard
|
||||
- Finds/selects/replaces each image placeholder
|
||||
|
||||
## Scripts Reference
|
||||
|
||||
| Script | Purpose |
|
||||
|--------|---------|
|
||||
| `x-browser.ts` | Regular posts (text + images) |
|
||||
| `x-article.ts` | Article publishing (Markdown) |
|
||||
| `md-to-html.ts` | Markdown → HTML conversion |
|
||||
| `copy-to-clipboard.ts` | Copy image/HTML to clipboard |
|
||||
@@ -1,331 +0,0 @@
|
||||
---
|
||||
name: 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".
|
||||
---
|
||||
|
||||
# Xiaohongshu Infographic Series Generator
|
||||
|
||||
Break down complex content into eye-catching infographic series for Xiaohongshu with multiple style options.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Auto-select style based on content
|
||||
/xhs-images posts/ai-future/article.md
|
||||
|
||||
# Specify a style
|
||||
/xhs-images posts/ai-future/article.md --style cute
|
||||
/xhs-images posts/ai-future/article.md --style tech
|
||||
/xhs-images posts/ai-future/article.md --style minimal
|
||||
|
||||
# Direct content input
|
||||
/xhs-images
|
||||
[paste content]
|
||||
|
||||
# Direct input with style
|
||||
/xhs-images --style bold
|
||||
[paste content]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--style <name>` | Specify infographic style (see Style Gallery below) |
|
||||
|
||||
## Style Gallery
|
||||
|
||||
### 1. `cute` (Default)
|
||||
Sweet, adorable, girly - classic Xiaohongshu aesthetic
|
||||
- **Colors**: Pink, peach, mint, lavender, cream background
|
||||
- **Elements**: Cute stickers, emoji icons, hearts, stars, sparkles
|
||||
- **Best for**: Lifestyle, beauty, fashion, daily tips
|
||||
|
||||
### 2. `fresh`
|
||||
Clean, refreshing, natural
|
||||
- **Colors**: Mint green, sky blue, white, light yellow
|
||||
- **Elements**: Plant icons, clouds, simple shapes, breathing room
|
||||
- **Best for**: Health, wellness, minimalist lifestyle, self-care
|
||||
|
||||
### 3. `tech`
|
||||
Modern, smart, digital
|
||||
- **Colors**: Deep blue, purple, cyan, dark backgrounds with neon accents
|
||||
- **Elements**: Geometric shapes, data icons, circuit patterns, glowing effects
|
||||
- **Best for**: Tech tutorials, AI content, digital tools, productivity
|
||||
|
||||
### 4. `warm`
|
||||
Cozy, friendly, approachable
|
||||
- **Colors**: Warm orange, golden yellow, brown, cream
|
||||
- **Elements**: Sun motifs, coffee cups, cozy illustrations, warm lighting
|
||||
- **Best for**: Personal stories, life lessons, emotional content
|
||||
|
||||
### 5. `bold`
|
||||
High impact, attention-grabbing
|
||||
- **Colors**: Red, orange, black, yellow accents
|
||||
- **Elements**: Strong typography, exclamation marks, arrows, contrast
|
||||
- **Best for**: Important tips, warnings, must-know content
|
||||
|
||||
### 6. `minimal`
|
||||
Ultra-clean, sophisticated
|
||||
- **Colors**: Black, white, single accent color
|
||||
- **Elements**: Maximum whitespace, simple icons, clean lines
|
||||
- **Best for**: Professional content, serious topics, elegant presentations
|
||||
|
||||
### 7. `retro`
|
||||
Vintage, nostalgic, trendy
|
||||
- **Colors**: Muted pastels, sepia, faded tones
|
||||
- **Elements**: Vintage badges, halftone dots, classic typography
|
||||
- **Best for**: Throwback content, classic tips, timeless advice
|
||||
|
||||
### 8. `pop`
|
||||
Vibrant, energetic, eye-catching
|
||||
- **Colors**: Bright primary colors, neon accents, white
|
||||
- **Elements**: Bold shapes, comic-style elements, dynamic compositions
|
||||
- **Best for**: Exciting announcements, fun facts, engaging tutorials
|
||||
|
||||
## Auto Style Selection
|
||||
|
||||
When no `--style` is specified, analyze content to select:
|
||||
|
||||
| Content Signals | Selected Style |
|
||||
|----------------|----------------|
|
||||
| Beauty, fashion, cute, girl, pink | `cute` |
|
||||
| Health, nature, clean, fresh, organic | `fresh` |
|
||||
| Tech, AI, code, digital, app, tool | `tech` |
|
||||
| Life, story, emotion, feeling, warm | `warm` |
|
||||
| Warning, important, must, critical | `bold` |
|
||||
| Professional, business, elegant, simple | `minimal` |
|
||||
| Classic, vintage, old, traditional | `retro` |
|
||||
| Fun, exciting, wow, amazing | `pop` |
|
||||
|
||||
## File Management
|
||||
|
||||
### With Article Path
|
||||
|
||||
Save to `xhs-images/` subdirectory in the same folder as the article:
|
||||
|
||||
```
|
||||
posts/ai-future/
|
||||
├── article.md
|
||||
└── xhs-images/
|
||||
├── outline.md
|
||||
├── prompts/
|
||||
│ ├── 01-cover.md
|
||||
│ ├── 02-content-1.md
|
||||
│ └── ...
|
||||
├── 01-cover.png
|
||||
├── 02-content-1.png
|
||||
└── 03-ending.png
|
||||
```
|
||||
|
||||
### Without Article Path
|
||||
|
||||
Save to `xhs-outputs/YYYY-MM-DD/[topic-slug]/`:
|
||||
|
||||
```
|
||||
xhs-outputs/
|
||||
└── 2026-01-13/
|
||||
└── ai-agent-guide/
|
||||
├── outline.md
|
||||
├── prompts/
|
||||
│ ├── 01-cover.md
|
||||
│ └── ...
|
||||
├── 01-cover.png
|
||||
└── 02-ending.png
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1: Analyze Content & Select Style
|
||||
|
||||
1. Read content
|
||||
2. If `--style` specified, use that style
|
||||
3. Otherwise, scan for style signals and auto-select
|
||||
4. Determine image count based on content complexity:
|
||||
|
||||
| Content Type | Image Count |
|
||||
|-------------|-------------|
|
||||
| Simple opinion / single topic | 2-3 |
|
||||
| Medium complexity / tutorial | 4-6 |
|
||||
| Deep dive / multi-dimensional | 7-10 |
|
||||
|
||||
### Step 2: Generate Outline
|
||||
|
||||
Plan for each image with style-specific approach:
|
||||
|
||||
```markdown
|
||||
# Xiaohongshu Infographic Series Outline
|
||||
|
||||
**Topic**: [topic description]
|
||||
**Style**: [selected style]
|
||||
**Image Count**: N
|
||||
**Generated**: YYYY-MM-DD HH:mm
|
||||
|
||||
---
|
||||
|
||||
## Image 1 of N
|
||||
|
||||
**Position**: Cover
|
||||
**Core Message**: [one-liner]
|
||||
**Filename**: 01-cover.png
|
||||
|
||||
**Text Content**:
|
||||
- Title: xxx
|
||||
- Subtitle: xxx
|
||||
|
||||
**Visual Concept**: [style-appropriate description]
|
||||
|
||||
---
|
||||
|
||||
## Image 2 of N
|
||||
...
|
||||
```
|
||||
|
||||
### Step 3: Save Outline
|
||||
|
||||
Save outline as `outline.md`.
|
||||
|
||||
### Step 4: Generate Images One by One
|
||||
|
||||
For each image, create a style-specific prompt file.
|
||||
|
||||
**Prompt Format**:
|
||||
|
||||
```markdown
|
||||
Infographic theme: [topic]
|
||||
Style: [style name]
|
||||
Position: [cover/content/ending]
|
||||
|
||||
Visual composition:
|
||||
- Main visual: [style-appropriate description]
|
||||
- Layout: [element positioning for 3:4 vertical format]
|
||||
- Decorative elements: [style-specific decorations]
|
||||
|
||||
Color scheme:
|
||||
- Primary: [style primary color]
|
||||
- Background: [style background color]
|
||||
- Accent: [style accent color]
|
||||
|
||||
Text content:
|
||||
- Title: 「xxx」(large, prominent)
|
||||
- Key points: 「xxx」「xxx」
|
||||
|
||||
Style notes: [specific style characteristics]
|
||||
```
|
||||
|
||||
Then generate using:
|
||||
|
||||
```bash
|
||||
/gemini-web --promptfiles [SKILL_ROOT]/skills/xhs-images/prompts/system.md [TARGET_DIR]/prompts/01-cover.md --image [TARGET_DIR]/01-cover.png
|
||||
```
|
||||
|
||||
After each image:
|
||||
1. Confirm generation success
|
||||
2. Report progress: "Generated X/N"
|
||||
3. Continue to next
|
||||
|
||||
### Step 5: Completion Report
|
||||
|
||||
```
|
||||
Xiaohongshu Infographic Series Complete!
|
||||
|
||||
Topic: [topic]
|
||||
Style: [style name]
|
||||
Location: [directory path]
|
||||
Images: N total
|
||||
|
||||
- 01-cover.png ✓ Cover
|
||||
- 02-content-1.png ✓ Content
|
||||
- 03-content-2.png ✓ Content
|
||||
- 04-ending.png ✓ Ending
|
||||
|
||||
Outline: outline.md
|
||||
```
|
||||
|
||||
## Style Reference Details
|
||||
|
||||
### cute
|
||||
```
|
||||
Colors: Pink (#FED7E2), peach (#FEEBC8), mint (#C6F6D5), lavender (#E9D8FD)
|
||||
Background: Cream (#FFFAF0), soft pink (#FFF5F7)
|
||||
Accents: Hot pink, coral
|
||||
Elements: Hearts, stars, sparkles, cute faces, ribbon decorations, sticker-style
|
||||
Typography: Rounded, bubbly hand lettering
|
||||
```
|
||||
|
||||
### fresh
|
||||
```
|
||||
Colors: Mint green (#9AE6B4), sky blue (#90CDF4), light yellow (#FAF089)
|
||||
Background: Pure white (#FFFFFF), soft mint (#F0FFF4)
|
||||
Accents: Leaf green, water blue
|
||||
Elements: Plant leaves, clouds, water drops, simple geometric shapes
|
||||
Typography: Clean, light hand lettering with breathing room
|
||||
```
|
||||
|
||||
### tech
|
||||
```
|
||||
Colors: Deep blue (#1A365D), purple (#6B46C1), cyan (#00D4FF)
|
||||
Background: Dark gray (#1A202C), near-black (#0D1117)
|
||||
Accents: Neon green (#00FF88), electric blue
|
||||
Elements: Circuit patterns, data icons, geometric grids, glowing effects
|
||||
Typography: Monospace-style hand lettering, subtle glow
|
||||
```
|
||||
|
||||
### warm
|
||||
```
|
||||
Colors: Warm orange (#ED8936), golden yellow (#F6AD55), terracotta (#C05621)
|
||||
Background: Cream (#FFFAF0), soft peach (#FED7AA)
|
||||
Accents: Deep brown (#744210), soft red
|
||||
Elements: Sun rays, coffee cups, cozy items, warm lighting effects
|
||||
Typography: Friendly, rounded hand lettering
|
||||
```
|
||||
|
||||
### bold
|
||||
```
|
||||
Colors: Vibrant red (#E53E3E), orange (#DD6B20), yellow (#F6E05E)
|
||||
Background: Deep black (#000000), dark charcoal
|
||||
Accents: White, neon yellow
|
||||
Elements: Exclamation marks, arrows, warning icons, strong shapes
|
||||
Typography: Bold, impactful hand lettering with shadows
|
||||
```
|
||||
|
||||
### minimal
|
||||
```
|
||||
Colors: Black (#000000), white (#FFFFFF)
|
||||
Background: Off-white (#FAFAFA), pure white
|
||||
Accents: Single color (content-derived - blue, green, or coral)
|
||||
Elements: Single focal point, thin lines, maximum whitespace
|
||||
Typography: Clean, simple hand lettering
|
||||
```
|
||||
|
||||
### retro
|
||||
```
|
||||
Colors: Muted orange, dusty pink (#FED7E2 at 70%), faded teal
|
||||
Background: Aged paper (#F5E6D3), sepia tones
|
||||
Accents: Faded red, vintage gold
|
||||
Elements: Halftone dots, vintage badges, classic icons, tape effects
|
||||
Typography: Vintage-style hand lettering, classic feel
|
||||
```
|
||||
|
||||
### pop
|
||||
```
|
||||
Colors: Bright red (#F56565), yellow (#ECC94B), blue (#4299E1), green (#48BB78)
|
||||
Background: White (#FFFFFF), light gray
|
||||
Accents: Neon pink, electric purple
|
||||
Elements: Bold shapes, speech bubbles, comic-style effects, starburst
|
||||
Typography: Dynamic, energetic hand lettering with outlines
|
||||
```
|
||||
|
||||
## Content Breakdown Principles
|
||||
|
||||
1. **Cover (Image 1)**: Strong visual impact, core title, attention hook
|
||||
2. **Content (Middle)**: One core point per image, moderate information density
|
||||
3. **Ending (Last)**: Summary / call-to-action / memorable quote
|
||||
|
||||
## Notes
|
||||
|
||||
- Image generation typically takes 10-30 seconds per image
|
||||
- Auto-retry once on generation failure
|
||||
- Use cartoon alternatives for sensitive public figures
|
||||
- Output language matches input content language
|
||||
- Maintain selected style consistency across all images in series
|
||||
Reference in New Issue
Block a user