
Xiaohongshu Images
- 1.9k installs
- 6 repo stars
- Updated February 5, 2026
- iamzifei/xiaohongshu-images-skill
xiaohongshu-images is an agent skill that Transform markdown/HTML into styled 3:4 ratio images for Xiaohongshu.
About
This skill transforms markdown HTML or text content into beautifully styled HTML pages with AI generated cover images then captures them as sequential screenshots at 3 4 ratio for Xiaohongshu posting The skill performs the following workflow 1 Accept Content Receives markdown HTML or txt format content from the user 2 Load Prompt Template Reads the prompt template from prompts default md in this skill s directory 3 Determine Output Account Determines which account folder to use see Account Folder Resolution below 4 Generate Cover Image Uses baoyu cover image skill to generate a cover image based on the article content 5 Generate HTML Creates a beautifully styled HTML page following the prompt template specifications 6 Save Output Saves the HTML to Dev obsidian account_folder articles date title xhs preview html 7 Capture Screenshots Takes sequential 3 4 ratio screenshots of the entire page without cutting text The skill determines the output account folder using the following priority Priority 1 Explicit account Parameter
- description: Transform markdown/HTML into styled 3:4 ratio images for Xiaohongshu
- This skill transforms markdown, HTML, or text content into beautifully styled HTML pages with AI-generated cover images,
- The skill performs the following workflow:
- Follow xiaohongshu-images SKILL.md steps and documented constraints.
- Follow xiaohongshu-images SKILL.md steps and documented constraints.
Xiaohongshu Images by the numbers
- 1,886 all-time installs (skills.sh)
- +27 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #673 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Security screen: HIGH risk (skills.sh audit)
- Data as of Aug 4, 2026 (Skillselion catalog sync)
xiaohongshu-images capabilities & compatibility
- Capabilities
- description: transform markdown/html into styled · this skill transforms markdown, html, or text co · the skill performs the following workflow: · follow xiaohongshu images skill.md steps and doc
- Use cases
- orchestration
What xiaohongshu-images says it does
description: Transform markdown/HTML into styled 3:4 ratio images for Xiaohongshu
This skill transforms markdown, HTML, or text content into beautifully styled HTML pages with AI-generated cover images, then captures them as sequential screenshots at 3:4 ratio for Xiaohongshu posti
The skill performs the following workflow:
npx skills add https://github.com/iamzifei/xiaohongshu-images-skill --skill xiaohongshu-imagesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.9k |
|---|---|
| repo stars | ★ 6 |
| Security audit | 1 / 3 scanners passed |
| Last updated | February 5, 2026 |
| Repository | iamzifei/xiaohongshu-images-skill ↗ |
When should an agent use xiaohongshu-images and what problem does it solve?
Transform markdown/HTML into styled 3:4 ratio images for Xiaohongshu
Who is it for?
Developers invoking xiaohongshu-images as documented in the skill source.
Skip if: Skip when requirements fall outside xiaohongshu-images documented scope.
When should I use this skill?
Transform markdown/HTML into styled 3:4 ratio images for Xiaohongshu
What you get
Outputs aligned with the xiaohongshu-images SKILL.md workflow and stated deliverables.
- xhs-preview.html
- cover-xhs.png
- Sequential xhs-NN.png screenshots
By the numbers
- Requires Python 3.8+ and the baoyu-cover-image skill
- Loads prompt template from prompts/default.md
- Outputs sequential 3:4 aspect-ratio PNG screenshots
Files
Xiaohongshu Images Skill
This skill transforms markdown, HTML, or text content into beautifully styled HTML pages with AI-generated cover images, then captures them as sequential screenshots at 3:4 ratio for Xiaohongshu posting.
Overview
The skill performs the following workflow:
1. Accept Content: Receives markdown, HTML, or txt format content from the user 2. Load Prompt Template: Reads the prompt template from prompts/default.md in this skill's directory 3. Determine Output Account: Determines which account folder to use (see Account Folder Resolution below) 4. Generate Cover Image: Uses /baoyu-cover-image skill to generate a cover image based on the article content 5. Generate HTML: Creates a beautifully styled HTML page following the prompt template specifications 6. Save Output: Saves the HTML to ~/Dev/obsidian/{account_folder}/articles/<date-title>/xhs-preview.html 7. Capture Screenshots: Takes sequential 3:4 ratio screenshots of the entire page without cutting text
Account Folder Resolution
The skill determines the output account folder using the following priority:
Priority 1: Explicit --account Parameter
If the user specifies --account, use the corresponding folder:
/xiaohongshu-images <article> --account james-cn # → 10_在悉尼和稀泥
/xiaohongshu-images <article> --account james-en # → 11_BuildWithJames
/xiaohongshu-images <article> --account mom-reading-club # → 12_妈妈在读Priority 2: Infer from Input File Path
If no --account is specified, try to infer from the input file path:
Input: ~/Dev/obsidian/12_妈妈在读/articles/2026-01-20-xxx/index.md
→ Output to: ~/Dev/obsidian/12_妈妈在读/articles/2026-01-20-xxx/
Input: ~/Dev/obsidian/10_在悉尼和稀泥/articles/2026-01-20-xxx/index.md
→ Output to: ~/Dev/obsidian/10_在悉尼和稀泥/articles/2026-01-20-xxx/Priority 3: Fallback to Template Mapping
If the account cannot be determined from the path (e.g., raw content input), use template-based mapping:
| Template | Account Folder |
|---|---|
default | 10_在悉尼和稀泥 |
mom-reading-club | 12_妈妈在读 |
Account Folder Mapping Reference
| Account | Folder |
|---|---|
james-cn | 10_在悉尼和稀泥 |
james-en | 11_BuildWithJames |
mom-reading-club | 12_妈妈在读 |
Usage
When the user invokes this skill, follow these steps:
Step 1: Identify the Input
The user will provide one of the following:
- A file path to a markdown, HTML, or txt file (e.g.,
/path/to/article.md) - Raw content directly in the conversation
- A URL to fetch content from
If the input is unclear, ask the user to provide either a file path, URL, or paste the content directly.
Step 2: Read the Prompt Template
Read the prompt template from this skill's directory:
{{SKILL_DIR}}/prompts/default.mdUse the Read tool to get the prompt template content. This template defines the HTML/CSS styling specifications.
Step 3: Extract Article Title, Date, and Determine Account
From the content, extract:
- Title: The main heading (h1) or first significant title in the content
- Date: Current date in YYYY-MM-DD format
- Account Folder: Determine using the priority rules above (--account → path inference → template mapping)
Create the output folder path as: ~/Dev/obsidian/{account_folder}/articles/<date>-<sanitized-title>/
- Replace spaces with hyphens
- Remove special characters
- Keep the title reasonably short (max 50 characters)
- All images go in
_attachments/subfolder
Step 4: Generate Cover Image with baoyu-cover-image Skill
⚠️ COMPLIANCE CHECK: Before generating, ensure the image concept complies with Xiaohongshu community guidelines (Section 11 of the prompt template). The image must:
- Be age-appropriate with no revealing clothing or suggestive poses
- Avoid political symbols, violence, gambling, smoking, or alcohol abuse
- Convey positive, constructive messages
- Be culturally sensitive and original
Use the /baoyu-cover-image skill to generate the cover image:
1. Invoke the skill with the article content:
/baoyu-cover-image ~/Dev/obsidian/{account_folder}/articles/<date>-<title>/index.md --style <auto-or-specified> --no-titleOr if the content is not yet saved, pass the content directly to the skill.
2. Style Selection:
- Let baoyu-cover-image auto-select based on content signals, OR
- Specify a style that matches the article tone:
tech- AI, coding, digital topicswarm- Personal stories, emotional contentbold- Controversial, attention-grabbing topicsminimal- Simple, zen-like contentplayful- Fun, casual, beginner-friendly contentnature- Wellness, health, organic topicsretro- History, vintage, traditional topicselegant- Business, professional content (default)
Special: Mom Reading Club Template
When using the mom-reading-club template, override the default cover style with calligraphy & ink-wash illustration (书法水墨风):
/baoyu-cover-image <article> --style minimal --no-title --custom-prompt "Chinese calligraphy and ink-wash illustration style (书法水墨风). Zen-like simplicity with generous white space (留白). Include subtle ink-wash brush strokes as background texture. Minimalist botanical elements (bamboo, plum blossoms, orchids, lotus) when appropriate. Color palette: ink black (#1a1a1a), warm gray (#666666), subtle gold accents (#C9A962), warm off-white background (#F5F3EE). If human figures are included, depict an elegant woman aged 30-45 with a contemplative, refined demeanor. NO TEXT on the cover."3. Use `--no-title` flag since Xiaohongshu covers typically use visual-only images without embedded text.
4. Move the generated image to the correct location:
- baoyu-cover-image saves to
imgs/cover.pngrelative to the article - Move/copy to
~/Dev/obsidian/{account_folder}/articles/<date>-<title>/_attachments/cover-xhs.png
mv ~/Dev/obsidian/{account_folder}/articles/<date>-<title>/imgs/cover.png ~/Dev/obsidian/{account_folder}/articles/<date>-<title>/_attachments/cover-xhs.pngStep 5: Generate HTML
⚠️ COMPLIANCE CHECK: Before generating HTML, review the text content for compliance:
- No absolute/superlative claims (最好、第一、国家级、最高级、全网最低价)
- No exaggerated effect claims (一分钟见效、吃完就变白)
- No false or unverified medical/financial advice
- No defamatory or offensive language
- If health/investment topics are involved, add disclaimer text
Using the prompt template and the user's content:
1. Parse the content to identify:
- Title (h1)
- Subtitles (h2-h6)
- Paragraphs
- Lists
- Code blocks
- Links
- Emphasis/bold text
- Blockquotes
2. Generate complete HTML following the template specifications:
- Dark gradient background
- 600px × 800px cream-colored card
- Proper typography with Google Fonts (Noto Serif SC, Inter, JetBrains Mono)
- Cover image at the top
- All specified styling for text, links, lists, code blocks, etc.
- Responsive design for mobile
3. Important HTML Structure:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Article Title</title>
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@700&family=Inter:wght@300;400;700;800&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
<style>
/* All CSS styles inline */
</style>
</head>
<body>
<div class="container">
<img src="_attachments/cover-xhs.png" class="cover-image" alt="Cover">
<div class="content">
<!-- Article content -->
</div>
</div>
</body>
</html>4. Save the HTML to ~/Dev/obsidian/{account_folder}/articles/<date>-<title>/xhs-preview.html
Step 6: Take Screenshots
After generating the HTML, capture sequential screenshots of the .container element at exact 3:4 aspect ratio:
Screenshot Specifications:
- Container viewport: 600px × 800px (3:4 ratio)
- Output resolution: 1200px × 1600px (2x device scale factor)
- Each screenshot captures exactly the
.containerelement, not the full page
Capture Process:
1. Open the HTML page using Playwright browser with viewport larger than container 2. Configure browser context:
- Viewport: 800px × 1000px (larger than container to ensure full visibility)
- Device scale factor: 2x for high-resolution output
3. Scroll within the container:
- The
.containerelement hasoverflow-y: auto, making it internally scrollable - Start from
scrollTop = 0and increment through the content - Each scroll position captures one 3:4 ratio screenshot
4. Smart text boundary detection:
- Before each screenshot, analyze visible block elements (p, h1-h6, li, blockquote, pre, img)
- If an element would be cut at the bottom boundary, end the current screenshot before that element
- Add whitespace mask to cover partial content, maintaining clean 3:4 frame
- Next screenshot starts with the cut element at the top
5. Capture the complete `.container` content:
- Use
container.screenshot()to capture only the container element (excludes page background) - Continue until all content is captured (scrollTop reaches scrollHeight - clientHeight)
6. Save screenshots to ~/Dev/obsidian/{account_folder}/articles/<date>-<title>/_attachments/:
- Sequential naming:
xhs-01.png,xhs-02.png,xhs-03.png, etc.
Use the screenshot script:
cd {{SKILL_DIR}} && python scripts/screenshot.py ~/Dev/obsidian/{account_folder}/articles/<date>-<title>/xhs-preview.htmlScript Output:
- Each screenshot: exactly 1200×1600 pixels (3:4 ratio at 2x scale)
- Only the cream-colored card content is captured
- No text is cut off between screenshots
Step 7: Report Results
After completion, report to the user:
- HTML file location
- Number of screenshots generated
- Screenshots folder location
- Preview of the first screenshot (if possible)
Directory Structure
{{SKILL_DIR}}/
├── SKILL.md # This file
├── prompts/
│ └── default.md # Default HTML/CSS styling prompt
│ └── mom-reading-club.md # Mom Reading Club styling prompt
├── scripts/
│ └── screenshot.py # Screenshot capture script
└── .gitignore
Output directory (outside skill folder):
~/Dev/obsidian/{account_folder}/articles/<date>-<title>/
├── xhs-preview.html # Styled HTML preview page
├── imgs/ # Created by baoyu-cover-image
│ ├── prompts/
│ │ └── cover.md # Cover image prompt
│ └── cover.png # Generated cover (moved to _attachments/)
└── _attachments/ # Obsidian-style attachments folder
├── cover-xhs.png # Cover image (moved from imgs/cover.png)
├── xhs-01.png # Screenshot page 1 (1200×1600)
├── xhs-02.png # Screenshot page 2
└── ...
Account folder mapping:
- james-cn → 10_在悉尼和稀泥
- james-en → 11_BuildWithJames
- mom-reading-club → 12_妈妈在读Dependencies
This skill depends on:
/baoyu-cover-imageskill for cover image generation (must be installed in~/.claude/skills/)
Example Workflow
User: Create a styled article page from this markdown:
# My Article Title
This is the introduction paragraph...
## Section 1
Content for section 1...Assistant Actions: 1. Read prompt template from prompts/default.md 2. Extract title: "My Article Title" 3. Determine account folder (no --account specified, no path to infer from, using default template → 10_在悉尼和稀泥) 4. Create output folder: ~/Dev/obsidian/10_在悉尼和稀泥/articles/2024-01-14-my-article-title/ 5. Invoke /baoyu-cover-image skill with --no-title flag to generate cover image 6. Move generated cover from imgs/cover.png to _attachments/cover-xhs.png 7. Generate styled HTML following template specifications 8. Save to ~/Dev/obsidian/10_在悉尼和稀泥/articles/2024-01-14-my-article-title/xhs-preview.html 9. Open in browser and take 3:4 ratio screenshots 10. Save screenshots to ~/Dev/obsidian/10_在悉尼和稀泥/articles/2024-01-14-my-article-title/_attachments/xhs-01.png, etc. 11. Report completion with file locations
Example with --account parameter:
/xiaohongshu-images ~/path/to/article.md --account mom-reading-club --template mom-reading-clubAssistant Actions: 1. --account mom-reading-club specified → use 12_妈妈在读 2. Output to: ~/Dev/obsidian/12_妈妈在读/articles/2024-01-14-article-title/
Example with path inference:
/xiaohongshu-images ~/Dev/obsidian/12_妈妈在读/articles/2024-01-14-xxx/index.mdAssistant Actions: 1. No --account specified 2. Input path contains 12_妈妈在读 → infer account folder 3. Output to same folder: ~/Dev/obsidian/12_妈妈在读/articles/2024-01-14-xxx/
Custom Prompt Templates
Users can provide custom prompt templates by: 1. Placing a .md file in the prompts/ directory 2. Specifying the template name when invoking the skill
Example: "Use the xiaohongshu-style template for this article"
Available Templates
| Template | Description | Best For |
|---|---|---|
default | Standard style with New Yorker-style illustrations | General articles |
mom-reading-club | Calligraphy & ink-wash style with TsangerJinKai02 font | Mom Reading Club (妈妈读书会) brand content |
Mom Reading Club Template
Use this template for all "Mom Reading Club" branded content:
/xiaohongshu-images <article> --template mom-reading-clubFeatures:
- Font: TsangerJinKai02 (仓耳今楷02) for titles - requires local installation
- Cover style: Chinese calligraphy & ink-wash illustration (书法水墨风)
- Aesthetic: Zen simplicity, elegant restraint, generous white space
- Color accent: Subtle gold (#C9A962)
- Target audience: Cultured mothers aged 30-45
Error Handling
If the /baoyu-cover-image skill fails: 1. Display the error message to the user 2. Offer to retry or proceed without cover image 3. If proceeding without image, use a placeholder or omit the cover
If screenshot capture fails: 1. Verify the HTML file exists and is valid 2. Check browser dependencies 3. Report the specific error to the user
System Requirements
This skill requires:
- Python 3.8+
- Playwright for screenshot capture (installed via pip:
pip install playwright && playwright install chromium) /baoyu-cover-imageskill installed in~/.claude/skills/
Install dependencies:
pip install playwright
playwright install chromiumNotes
- The skill preserves all original content exactly as provided
- No modifications, simplifications, or deletions to the content
- The cover image is generated based on the article's main theme
- Screenshots are optimized for Xiaohongshu's 3:4 aspect ratio
- Text is never cut off in screenshots - boundaries are adjusted intelligently
Community Compliance (社区规范合规)
IMPORTANT: All generated content must comply with Xiaohongshu community guidelines.
Quick Reference - Prohibited Content:
| Category | Examples | Action |
|---|---|---|
| Absolute claims | 最好、最佳、第一、国家级 | Remove or rephrase |
| Exaggerated effects | 一分钟见效、立刻瘦10斤 | Remove or add disclaimers |
| Medical/Financial advice | Health tips, investment suggestions | Add disclaimer: "本内容不构成医疗/投资建议" |
| Inappropriate imagery | Nudity, violence, political symbols | Regenerate with appropriate content |
| False information | Pseudoscience, unverified claims | Verify or remove |
| Defamatory content | Attacks on brands/individuals | Remove entirely |
Official Guidelines:
- 社区规范: https://www.xiaohongshu.com/crown/community/rules
- 社区公约: https://www.xiaohongshu.com/crown/community/agreement
Compliance Workflow:
1. Before image generation: Review theme for appropriateness 2. Before HTML generation: Scan text for prohibited phrases 3. Before final output: Run through compliance checklist in prompt template (Section 11.5)
# Environment variables (contains API keys, should not be committed)
.env
.env.local
.env.*.local
# Output directory (generated content)
output/
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# Virtual environments
venv/
ENV/
env/
.venv/
# IDE and editors
.idea/
.vscode/
*.swp
*.swo
*.sublime-workspace
*.sublime-project
# macOS
.DS_Store
.AppleDouble
.LSOverride
._*
# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
# Playwright
.playwright-mcp/
# Temporary files
*.tmp
*.temp
*.log
# Package artifacts
*.skill
HTML/CSS Article Image Expert Prompt
You are a frontend development and web layout expert proficient in HTML/CSS.
Task Objective
Please carefully read the article link or article content provided by the user, and generate a complete HTML page according to the following style specifications. The page should be presented as a cream-colored card on a dark background, with a modern feel and good reading experience.
---
1. Overall Layout
1.1 Page Background
- Dark gradient background
background: linear-gradient(135deg, #1e1e2e 0%, #2d2b55 50%, #3e3a5f 100%);
background-attachment: fixed;- Layout method: Use Flexbox to achieve vertical and horizontal centering
1.2 Main Container (Cream-colored Card)
- Dimensions: 600px × 800px
- Background color:
#F9F9F6 - border-radius: 0px (card has no rounded corners, rectangular with right angles)
- 3D shadow (three layers):
box-shadow:
0 25px 50px rgba(0, 0, 0, 0.4),
0 10px 30px rgba(0, 10, 20, 0.3),
0 5px 15px rgba(0, 5, 15, 0.25);1.3 Content Area
- Content area scope: Cover image, title, and body text. Note: Cover is part of the content area and scrolls with the content; NEVER use
position: fixedorposition: stickyto make the cover image hover. - Padding:
20px 50px 50px 50px(top, right, bottom, left - top padding reduced to 20px) - Scrolling: Vertical scrolling enabled
- Custom scrollbar: Fully transparent scrollbar or no scrollbar display
- CSS Implementation Key Points:
.containersetoverflow-y: auto.contentonly setspadding, no scrolling- Cover image as direct child element of
.container, positioned before.content
---
2. Font System
2.1 Import Fonts
Import the following fonts from Google Fonts:
- Noto Serif SC (Source Han Serif):
weight: 700 - Inter:
weight: 300, 400, 700, 800 - JetBrains Mono:
weight: 400, 700
2.2 Font Application Rules
| Content Type | Font |
|---|---|
| Body default | System font stack (-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, etc.) |
| H1 Main title | Noto Serif SC (Source Han Serif) |
| H2 Subtitle | Times New Roman |
| English titles | Inter |
| Code | JetBrains Mono |
---
3. Text Style Specifications
3.1 Cover Image
- Dimensions: 600px × 350px
- Image uses: object-fit: cover to ensure no compression
- Generate a hand-drawn illustration/comic based on the content's main theme, in a style similar to The New Yorker editorial cartoons. (The comic reflects the article's meaning)
- Character defaults: When the illustration includes human figures and the content does not specify gender or age, default to depicting women aged 25-40 years old as the primary characters.
3.2 Title Hierarchy
| Element | Font | Size | Color | Weight | Line Height | Margin |
|---|---|---|---|---|---|---|
h1 | Noto Serif SC | 42px | #000000 | 700 | 1.3 | margin-bottom: 30px |
h2 | Times New Roman | 26px | #000000 | 700 | - | margin: 40px 0 20px |
h3 | Default | 22px | #2c3e50 | 600 | - | margin: 30px 0 15px |
h4 | Default | 20px | #5a6c7d | 600 | - | margin: 25px 0 12px |
3.3 Body Text
- Font size:
20px - Color:
#333333 - Line height:
2 - Paragraph spacing:
margin-bottom: 20px
3.4 Special Text Classes
English title (.en-title)
- Font: Inter
- Size: 18px
- Color:
#888888 - Weight: 300
Metadata (.metadata)
- Size: 14px
- Color:
#888888
---
4. Emphasis and Markers
4.1 Links (<a>)
- Color:
#4a9eff(blue) - Default no underline
- Show underline on hover
- Transition effect:
transition: 0.2s ease
4.2 Emphasis (<em>)
- Color:
#000000(black) - Font style:
normal(not italic) - Usage: Text that needs emphasis but not highlighting
4.3 Bold (<strong>)
- Usage: Important keywords
4.4 Highlight marker (<mark>)
- Background color:
#fffde7(light yellow, subtle) - Text color:
#000000 - Weight:
bold - Bottom border:
1px solid #ffc107(yellow underline) - Border radius:
2px - Padding:
2px 4px - Usage: For memorable quotes, core viewpoints, assertions, and other shareable short phrases that readers might want to highlight or share. Apply this style to impactful, quotable sentences that capture the essence of the content.
---
5. Lists and Quotes
5.1 Lists (<ul>, <ol>)
- Font size:
20px - Left padding:
20px - Bottom margin:
margin-bottom: 20px
5.2 List items (<li>)
- Item spacing:
margin-bottom: 8px
5.3 Blockquote (<blockquote>)
- Left border:
4px solid #4a9eff(blue vertical line) - Left padding:
20px - Font style: italic
- Top/bottom margin:
margin: 20px 0
---
6. Code Styles
6.1 Code block (<pre><code>)
- Font: JetBrains Mono
- Size:
17px - Background color:
#f5f5f5 - Border:
1px solid #e0e0e0 - Border radius:
6px - Padding:
20px - Line height:
1.6 - Horizontal scrolling enabled
6.2 Inline code (<code>)
- Font: JetBrains Mono
- Size: inherit, slightly smaller
- Background color:
#f5f5f5 - Padding:
2px 6px - Border radius:
4px
---
7. Responsive Design
Breakpoint: 650px and below
| Element | Desktop | Mobile |
|---|---|---|
| Body padding | 20px | 10px |
| Body font size | 20px | 20px |
| Container width | 600px | 100% |
| Container height | 800px | auto (min 80vh) |
| Content area padding | 50px | 30px |
| H1 font size | 42px | 36px |
| H2 font size | 26px | 24px |
| List font size | 20px | 20px |
| Code block font size | 17px | 15px |
| Code block padding | 20px | 15px |
---
8. Output Requirements
1. Generate complete HTML5 document with <!DOCTYPE>, <html>, <head>, <body> tags 2. All styles inline in `<style>` tag, no external CSS file needed 3. Correctly import Google Fonts 4. Ensure semantic HTML structure 5. Clean code formatting with proper indentation 6. Include viewport meta tag for responsive support 7. Set page character encoding to UTF-8 8. Strictly follow the original content obtained, do not modify, simplify, or delete on your own.
---
9. Usage
User will provide article content in <user_content> tags, which may contain:
- Cover image
- Titles (h1-h6)
- Paragraph text
- Lists (ordered/unordered)
- Code blocks
- Links
- Emphasis/highlight text
- Blockquotes
Please convert these contents into a beautifully formatted HTML page according to the above specifications.
Important: When processing the article content, proactively identify and apply <mark> tags to:
- Memorable quotes and golden sentences (金句)
- Core viewpoints and key insights
- Bold assertions and thought-provoking statements
- Shareable phrases that capture the essence of the content
These highlighted elements help readers quickly identify the most impactful parts of the article.
---
10. Special Requirements
Please strictly follow the provided original content, do not modify, delete, or re-polish on your own. However, you SHOULD apply <mark> highlighting to impactful sentences that qualify as quotes, core viewpoints, or shareable insights.
---
11. Xiaohongshu Community Compliance Guidelines (小红书社区规范)
CRITICAL: All generated content (text and images) MUST comply with Xiaohongshu community rules and community agreement. Before generating any content, ensure it adheres to the following requirements:
11.1 Prohibited Content (禁止内容)
Do NOT include any of the following:
1. Sexual/Nudity Content: No nudity, sexual content, or suggestive imagery. Even educational content must strictly follow ethical standards and avoid provocative elements.
2. Violence & Horror: No violent, bloody, terroristic, or disturbing content.
3. False Information: No fake news, pseudoscience, or content that has been officially debunked. Do not publish unverified health, medical, or investment advice.
4. Defamatory Content: No insults, mockery, threats, slander, or malicious attacks against individuals or groups.
5. Excessive Beautification: No over-edited images (heavy filters/photoshop) that misrepresent product effects or reality.
6. Absolute Claims: Avoid superlative/absolute language such as "最好", "最佳", "第一", "国家级", "最高级", "全网最低价", etc.
7. Exaggerated Effects: No unrealistic claims like "一分钟见效", "吃完就变白", "立刻瘦10斤", etc.
8. Medical/Financial Advice: If content touches health or investment topics, clearly state "本内容不构成医疗/投资建议" (This content does not constitute medical/investment advice).
9. Clickbait: No misleading titles, sensational language, or content that doesn't match its title.
10. Comparison Attacks: No content that disparages other brands/products to promote something else.
11.2 Cover Image Requirements (封面图要求)
When generating the cover illustration:
1. Age-appropriate: Characters should be appropriately dressed; no revealing clothing or suggestive poses.
2. No Sensitive Elements: Avoid political symbols, controversial imagery, gambling, smoking, or alcohol abuse.
3. Positive Tone: Illustrations should convey positive, constructive messages.
4. Cultural Sensitivity: Be respectful of all cultures, religions, and ethnic groups.
5. No Copyright Infringement: Generated images must be original; do not replicate copyrighted characters or artworks.
11.3 Text Content Requirements (文字内容要求)
1. Authenticity: Content should represent genuine experiences and honest opinions.
2. Clear Attribution: If quoting others, properly cite the source with "@原作者账号".
3. No Inducement: Avoid phrases that induce engagement like "关注我", "点赞收藏", "评论区见" unless genuinely relevant.
4. Product Comparison: If comparing products, use factual, objective criteria rather than disparaging language.
5. Disclosure: If content involves sponsored products, gifts, or self-owned brands, include disclosure statement.
11.4 Minor Protection (未成年人保护)
1. Never generate content inappropriate for minors. 2. If content involves children, ensure it's wholesome and appropriate. 3. No content that could exploit, endanger, or sexualize minors in any way.
11.5 Compliance Checklist
Before finalizing any output, verify:
- [ ] No absolute/superlative claims
- [ ] No exaggerated product/effect claims
- [ ] No false or unverified information
- [ ] No inappropriate imagery in cover
- [ ] No offensive or discriminatory language
- [ ] Appropriate for all ages
- [ ] Genuine and authentic tone
Reference:
- 社区规范: https://www.xiaohongshu.com/crown/community/rules
- 社区公约: https://www.xiaohongshu.com/crown/community/agreement
---
Mom Reading Club - HTML/CSS Article Image Expert Prompt
You are a frontend development and web layout expert proficient in HTML/CSS.
Task Objective
Please carefully read the article link or article content provided by the user, and generate a complete HTML page according to the following style specifications. The page should be presented as a cream-colored card on a dark background, with an elegant, sophisticated feel and premium reading experience tailored for the "Mom Reading Club" (妈妈读书会) brand.
---
1. Overall Layout
1.1 Page Background
- Ink-wash dark gradient background (水墨深色渐变)
background: linear-gradient(160deg, #1a1a1a 0%, #2a2a2a 40%, #1f2020 100%);
background-attachment: fixed;- Layout method: Use Flexbox to achieve vertical and horizontal centering
1.2 Main Container (Cream-colored Card)
- Dimensions: 600px × 800px
- Background color:
#FDFCF8(warmer, more elegant cream) - border-radius: 0px (card has no rounded corners, rectangular with right angles)
- 3D shadow (refined, softer shadow for elegance):
box-shadow:
0 30px 60px rgba(0, 0, 0, 0.35),
0 15px 35px rgba(0, 0, 0, 0.2),
0 5px 15px rgba(0, 0, 0, 0.15);1.3 Content Area
- Content area scope: Cover image, title, and body text. Note: Cover is part of the content area and scrolls with the content; NEVER use
position: fixedorposition: stickyto make the cover image hover. - Padding:
20px 50px 50px 50px(top, right, bottom, left - top padding reduced to 20px) - Scrolling: Vertical scrolling enabled
- Custom scrollbar: Fully transparent scrollbar or no scrollbar display
- CSS Implementation Key Points:
.containersetoverflow-y: auto.contentonly setspadding, no scrolling- Cover image as direct child element of
.container, positioned before.content
---
2. Font System
2.1 Import Fonts
/* TsangerJinKai02 is installed locally on the system */
@font-face {
font-family: 'TsangerJinKai02';
src: local('TsangerJinKai02'), local('TsangerJinKai02-W03');
font-weight: normal;
font-style: normal;
}Import the following fonts from Google Fonts:
- Inter:
weight: 300, 400, 700, 800 - JetBrains Mono:
weight: 400, 700
2.2 Font Application Rules
| Content Type | Font |
|---|---|
| Body default | System font stack (-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, etc.) |
| H1 Main title | TsangerJinKai02 (仓耳今楷02) |
| H2 Subtitle | TsangerJinKai02 |
| H3-H6 Subtitles | System font stack |
| English titles | Inter |
| Code | JetBrains Mono |
---
3. Text Style Specifications
3.1 Cover Image - Calligraphy & Ink-wash Style (书法意境风封面)
IMPORTANT: This is the signature cover style for Mom Reading Club.
- Dimensions: 600px × 350px
- Image uses: object-fit: cover to ensure no compression
Cover Style Requirements:
- Style: Chinese calligraphy and ink-wash illustration (书法水墨风)
- Aesthetic: Zen-like simplicity, elegant restraint, generous white space (留白)
- Elements to include:
- Subtle ink-wash brush strokes as background texture
- Minimalist botanical elements (bamboo, plum blossoms, orchids, lotus) when appropriate
- Optional: silhouette of a contemplative female figure reading
- Muted, sophisticated color palette: ink black, warm gray, subtle gold accents
- Typography on cover: NONE (use
--no-titleflag) - let the visual speak - Character defaults: When the illustration includes human figures and the content does not specify gender or age, default to depicting elegant women aged 30-45 years old as the primary characters, conveying a sense of wisdom and refinement.
Color Palette for Cover:
- Primary:
#1a1a1a(ink black) - Secondary:
#666666(warm gray) - Accent:
#C9A962(subtle gold) - Background:
#F5F3EE(warm off-white)
3.2 Title Hierarchy
| Element | Font | Size | Color | Weight | Line Height | Margin |
|---|---|---|---|---|---|---|
h1 | TsangerJinKai02 | 44px | #1a1a1a | normal | 1.4 | margin-bottom: 35px |
h2 | TsangerJinKai02 | 28px | #2a2a2a | normal | 1.3 | margin: 45px 0 22px |
h3 | Default | 22px | #3a3a3a | 600 | - | margin: 32px 0 16px |
h4 | Default | 20px | #5a5a5a | 600 | - | margin: 26px 0 13px |
Special styling for h1:
h1 {
font-family: 'TsangerJinKai02', 'Noto Serif SC', 'STKaiti', 'KaiTi', serif;
letter-spacing: 0.08em;
position: relative;
}
/* Optional: subtle underline decoration */
h1::after {
content: '';
display: block;
width: 60px;
height: 2px;
background: linear-gradient(90deg, #C9A962, transparent);
margin-top: 15px;
}3.3 Body Text
- Font size:
20px - Color:
#333333 - Line height:
2 - Paragraph spacing:
margin-bottom: 22px
3.4 Special Text Classes
English title (.en-title)
- Font: Inter
- Size: 16px
- Color:
#888888 - Weight: 300
- Letter-spacing:
0.05em
Metadata (.metadata)
- Size: 14px
- Color:
#999999
---
4. Emphasis and Markers
4.1 Links (<a>)
- Color:
#8B7355(refined brown, more elegant than blue) - Default no underline
- Show underline on hover
- Transition effect:
transition: 0.2s ease
4.2 Emphasis (<em>)
- Color:
#1a1a1a(ink black) - Font style:
normal(not italic) - Usage: Text that needs emphasis but not highlighting
4.3 Bold (<strong>)
- Usage: Important keywords
4.4 Highlight marker (<mark>)
- Background color:
#FDF6E3(warm cream highlight) - Text color:
#1a1a1a - Weight:
bold - Bottom border:
1px solid #C9A962(gold underline) - Border radius:
2px - Padding:
2px 6px - Usage: For memorable quotes, core viewpoints, assertions, and other shareable short phrases that readers might want to highlight or share. Apply this style to impactful, quotable sentences that capture the essence of the content.
---
5. Lists and Quotes
5.1 Lists (<ul>, <ol>)
- Font size:
20px - Left padding:
20px - Bottom margin:
margin-bottom: 22px
5.2 List items (<li>)
- Item spacing:
margin-bottom: 10px
5.3 Blockquote (<blockquote>)
- Left border:
3px solid #C9A962(gold vertical line) - Left padding:
22px - Font style: normal (not italic for Chinese)
- Font-family:
'TsangerJinKai02', serif(use calligraphy font for quotes) - Background:
rgba(201, 169, 98, 0.05)(very subtle gold tint) - Top/bottom margin:
margin: 25px 0 - Padding:
15px 22px
---
6. Code Styles
6.1 Code block (<pre><code>)
- Font: JetBrains Mono
- Size:
17px - Background color:
#f8f7f5 - Border:
1px solid #e8e6e0 - Border radius:
6px - Padding:
20px - Line height:
1.6 - Horizontal scrolling enabled
6.2 Inline code (<code>)
- Font: JetBrains Mono
- Size: inherit, slightly smaller
- Background color:
#f8f7f5 - Padding:
2px 6px - Border radius:
4px
---
7. Responsive Design
Breakpoint: 650px and below
| Element | Desktop | Mobile |
|---|---|---|
| Body padding | 20px | 10px |
| Body font size | 20px | 20px |
| Container width | 600px | 100% |
| Container height | 800px | auto (min 80vh) |
| Content area padding | 50px | 30px |
| H1 font size | 44px | 38px |
| H2 font size | 28px | 26px |
| List font size | 20px | 20px |
| Code block font size | 17px | 15px |
| Code block padding | 20px | 15px |
---
8. Output Requirements
1. Generate complete HTML5 document with <!DOCTYPE>, <html>, <head>, <body> tags 2. All styles inline in `<style>` tag, no external CSS file needed 3. Correctly import Google Fonts (Inter, JetBrains Mono) 4. Include local font-face for TsangerJinKai02 5. Ensure semantic HTML structure 6. Clean code formatting with proper indentation 7. Include viewport meta tag for responsive support 8. Set page character encoding to UTF-8 9. Strictly follow the original content obtained, do not modify, simplify, or delete on your own.
---
9. Usage
User will provide article content in <user_content> tags, which may contain:
- Cover image
- Titles (h1-h6)
- Paragraph text
- Lists (ordered/unordered)
- Code blocks
- Links
- Emphasis/highlight text
- Blockquotes
Please convert these contents into a beautifully formatted HTML page according to the above specifications.
Important: When processing the article content, proactively identify and apply <mark> tags to:
- Memorable quotes and golden sentences (金句)
- Core viewpoints and key insights
- Bold assertions and thought-provoking statements
- Shareable phrases that capture the essence of the content
These highlighted elements help readers quickly identify the most impactful parts of the article.
---
10. Special Requirements
Please strictly follow the provided original content, do not modify, delete, or re-polish on your own. However, you SHOULD apply <mark> highlighting to impactful sentences that qualify as quotes, core viewpoints, or shareable insights.
---
11. Brand Identity - Mom Reading Club (妈妈读书会)
11.1 Brand Aesthetic
- Sophistication: Refined, cultured, intellectual
- Warmth: Approachable yet elegant
- Zen simplicity: Less is more, generous white space
- Chinese aesthetics: Calligraphy, ink-wash, traditional motifs reinterpreted with modern sensibility
11.2 Consistency Guidelines
- All covers should maintain the calligraphy/ink-wash style
- TsangerJinKai02 font is the signature typeface for titles
- Gold accent color
#C9A962should appear subtly in each design - Avoid busy, cluttered designs - embrace negative space
---
12. Xiaohongshu Community Compliance Guidelines (小红书社区规范)
CRITICAL: All generated content (text and images) MUST comply with Xiaohongshu community rules and community agreement. Before generating any content, ensure it adheres to the following requirements:
12.1 Prohibited Content (禁止内容)
Do NOT include any of the following:
1. Sexual/Nudity Content: No nudity, sexual content, or suggestive imagery. Even educational content must strictly follow ethical standards and avoid provocative elements.
2. Violence & Horror: No violent, bloody, terroristic, or disturbing content.
3. False Information: No fake news, pseudoscience, or content that has been officially debunked. Do not publish unverified health, medical, or investment advice.
4. Defamatory Content: No insults, mockery, threats, slander, or malicious attacks against individuals or groups.
5. Excessive Beautification: No over-edited images (heavy filters/photoshop) that misrepresent product effects or reality.
6. Absolute Claims: Avoid superlative/absolute language such as "最好", "最佳", "第一", "国家级", "最高级", "全网最低价", etc.
7. Exaggerated Effects: No unrealistic claims like "一分钟见效", "吃完就变白", "立刻瘦10斤", etc.
8. Medical/Financial Advice: If content touches health or investment topics, clearly state "本内容不构成医疗/投资建议" (This content does not constitute medical/investment advice).
9. Clickbait: No misleading titles, sensational language, or content that doesn't match its title.
10. Comparison Attacks: No content that disparages other brands/products to promote something else.
12.2 Cover Image Requirements (封面图要求)
When generating the cover illustration:
1. Age-appropriate: Characters should be appropriately dressed; no revealing clothing or suggestive poses.
2. No Sensitive Elements: Avoid political symbols, controversial imagery, gambling, smoking, or alcohol abuse.
3. Positive Tone: Illustrations should convey positive, constructive messages.
4. Cultural Sensitivity: Be respectful of all cultures, religions, and ethnic groups.
5. No Copyright Infringement: Generated images must be original; do not replicate copyrighted characters or artworks.
12.3 Text Content Requirements (文字内容要求)
1. Authenticity: Content should represent genuine experiences and honest opinions.
2. Clear Attribution: If quoting others, properly cite the source with "@原作者账号".
3. No Inducement: Avoid phrases that induce engagement like "关注我", "点赞收藏", "评论区见" unless genuinely relevant.
4. Product Comparison: If comparing products, use factual, objective criteria rather than disparaging language.
5. Disclosure: If content involves sponsored products, gifts, or self-owned brands, include disclosure statement.
12.4 Minor Protection (未成年人保护)
1. Never generate content inappropriate for minors. 2. If content involves children, ensure it's wholesome and appropriate. 3. No content that could exploit, endanger, or sexualize minors in any way.
12.5 Compliance Checklist
Before finalizing any output, verify:
- [ ] No absolute/superlative claims
- [ ] No exaggerated product/effect claims
- [ ] No false or unverified information
- [ ] No inappropriate imagery in cover
- [ ] No offensive or discriminatory language
- [ ] Appropriate for all ages
- [ ] Genuine and authentic tone
Reference:
- 社区规范: https://www.xiaohongshu.com/crown/community/rules
- 社区公约: https://www.xiaohongshu.com/crown/community/agreement
---
Xiaohongshu Images Skill
A Claude Code skill that transforms markdown, HTML, or text content into beautifully styled HTML pages with AI-generated cover images, then captures them as sequential screenshots at 3:4 ratio for Xiaohongshu posting.
Features
- Content Processing: Accepts markdown, HTML, or plain text content
- AI Cover Images: Generates editorial-style cover illustrations using
/baoyu-cover-imageskill - Styled HTML Output: Creates beautifully formatted HTML pages with modern typography
- Screenshot Capture: Takes sequential 3:4 ratio screenshots optimized for Xiaohongshu
- Smart Text Boundaries: Ensures no text is cut off in screenshots
Installation
Prerequisites
- Python 3.8 or higher
- Claude Code CLI
/baoyu-cover-imageskill installed in~/.claude/skills/
Setup
1. Clone or copy this skill to your Claude skills directory:
# Copy to global skills
cp -r xiaohongshu-images-skill ~/.claude/skills/
# Or symlink for development
ln -s /path/to/xiaohongshu-images-skill ~/.claude/skills/xiaohongshu-images-skill2. Install Python dependencies:
pip install playwright
playwright install chromium3. Ensure baoyu-cover-image skill is installed:
# Verify the skill exists
ls ~/.claude/skills/baoyu-cover-image/SKILL.mdUsage
Via Claude Code
Invoke the skill in Claude Code:
/xiaohongshu-imagesThen provide your content:
- Paste markdown/HTML content directly
- Provide a file path:
/path/to/article.md - Provide a URL to fetch content from
Example
/xiaohongshu-images
# My Article Title
This is the introduction paragraph explaining the topic...
## Section 1
Content for section 1 with detailed explanation...
## Section 2
More content here with examples...Output
The skill generates output in ~/Dev/obsidian/articles/<date-title>/:
xhs-preview.html- Styled HTML preview page_attachments/cover-xhs.png- AI-generated cover image_attachments/xhs-01.png, xhs-02.png, ...- Sequential screenshots
Directory Structure
xiaohongshu-images-skill/
├── SKILL.md # Main skill definition
├── README.md # This file
├── prompts/
│ └── default.md # Default HTML/CSS styling prompt
├── scripts/
│ └── screenshot.py # Screenshot capture
└── .gitignore
Output directory (outside skill folder):
~/Dev/obsidian/articles/<date>-<title>/
├── xhs-preview.html # Styled HTML preview page
├── imgs/ # Created by baoyu-cover-image
│ ├── prompts/
│ │ └── cover.md # Cover image prompt
│ └── cover.png # Generated cover (moved to _attachments/)
└── _attachments/ # Obsidian-style attachments folder
├── cover-xhs.png # Cover image (moved from imgs/cover.png)
├── xhs-01.png # Screenshot page 1
├── xhs-02.png # Screenshot page 2
└── ...Customization
Custom Prompt Templates
Create custom styling templates in the prompts/ directory:
1. Create a new .md file (e.g., prompts/minimal.md) 2. Define your HTML/CSS specifications 3. Invoke with: "Use the minimal template for this article"
Modifying Styles
Edit prompts/default.md to customize:
- Card dimensions and colors
- Font families and sizes
- Typography hierarchy
- Code block styling
- Responsive breakpoints
Configuration
Screenshot Settings
Default screenshot dimensions (3:4 ratio for Xiaohongshu):
- Width: 1080px
- Height: 1440px
- Scale factor: 2x (Retina quality)
To modify, edit scripts/screenshot.py:
SCREENSHOT_WIDTH = 1080
SCREENSHOT_HEIGHT = 1440Scripts
screenshot.py
Captures sequential screenshots of HTML pages.
python scripts/screenshot.py ~/Dev/obsidian/articles/<date>-<title>/xhs-preview.htmlOutput: ~/Dev/obsidian/articles/<date>-<title>/_attachments/xhs-01.png, xhs-02.png, etc.
Features:
- Automatic page scrolling
- Smart text boundary detection
- No text cut-off at boundaries
- 3:4 aspect ratio output
Troubleshooting
Cover Image Issues
- Ensure
/baoyu-cover-imageskill is installed and working - Check that the skill has proper access to image generation models
- Try running
/baoyu-cover-imagedirectly to debug
Screenshot Issues
- Install Playwright browsers:
playwright install chromium - Check file paths are correct
- Ensure HTML file is valid and accessible
Font Loading
If fonts don't load in screenshots:
- Increase wait time in
screenshot.py - Check Google Fonts availability
- Consider using local fonts
License
MIT License - See LICENSE file for details.
Related Skills
baoyu-cover-image- Cover image generation (required dependency)chinese-viral-writer- Chinese viral content creationwechat-article-formatter- WeChat article formattingwechat-article-publisher- WeChat publishing automation
#!/usr/bin/env python3
"""
Screenshot Capture Script for Xiaohongshu Images
Captures sequential screenshots of the container element at precise 3:4 aspect ratio.
Ensures no text is cut off - if a line would be split, the current screenshot ends
at the previous line with whitespace padding, and the next screenshot starts from
that same line.
Usage:
python screenshot.py <html_file_path>
Output:
Screenshots saved to <html_folder>/_attachments/xhs-01.png, xhs-02.png, etc.
"""
import sys
from pathlib import Path
try:
from playwright.sync_api import sync_playwright
except ImportError:
print("Error: Playwright is not installed.")
print("Install it with: pip install playwright && playwright install chromium")
sys.exit(1)
# Container dimensions (3:4 ratio)
CONTAINER_WIDTH = 600
CONTAINER_HEIGHT = 800
DEVICE_SCALE_FACTOR = 2
# Output dimensions (actual pixel size of screenshots)
OUTPUT_WIDTH = CONTAINER_WIDTH * DEVICE_SCALE_FACTOR # 1200px
OUTPUT_HEIGHT = CONTAINER_HEIGHT * DEVICE_SCALE_FACTOR # 1600px
def get_container_info(page) -> dict:
"""
Get information about the container element.
Returns:
Dict with container's scroll info and dimensions
"""
script = """
() => {
const container = document.querySelector('.container');
if (!container) return null;
const rect = container.getBoundingClientRect();
return {
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
scrollHeight: container.scrollHeight,
clientHeight: container.clientHeight
};
}
"""
return page.evaluate(script)
def scroll_container(page, scroll_top: int) -> int:
"""
Scroll the container to a specific position.
Returns:
Actual scroll position after scrolling
"""
script = f"""
() => {{
const container = document.querySelector('.container');
if (container) {{
container.scrollTop = {scroll_top};
return container.scrollTop;
}}
return 0;
}}
"""
return page.evaluate(script)
def find_safe_cut_position(page, viewport_height: int) -> dict:
"""
Find where to safely cut the current viewport without splitting text.
Analyzes elements visible in the current viewport and finds the last
complete element that fits entirely within the viewport.
Args:
page: Playwright page object
viewport_height: Height of the visible area (container clientHeight)
Returns:
Dict with:
- safe_y: Y position (relative to viewport top) where it's safe to cut
- has_more: Whether there's more content below
- next_start: Scroll position for the next screenshot
"""
script = f"""
() => {{
const container = document.querySelector('.container');
if (!container) return {{ safe_y: {viewport_height}, has_more: false, next_start: 0 }};
const containerRect = container.getBoundingClientRect();
const viewportHeight = {viewport_height};
const currentScroll = container.scrollTop;
const maxScroll = container.scrollHeight - container.clientHeight;
// If we're at or past the end, no more content
if (currentScroll >= maxScroll) {{
return {{ safe_y: viewportHeight, has_more: false, next_start: currentScroll }};
}}
// Get all block-level elements that could be cut
const blockElements = container.querySelectorAll(
'p, h1, h2, h3, h4, h5, h6, li, blockquote, pre, div.content > *, img, figure'
);
let lastSafeY = 0;
let nextStartScroll = currentScroll + viewportHeight;
let foundCutElement = false;
for (const el of blockElements) {{
const rect = el.getBoundingClientRect();
// Position relative to container's visible area
const elTop = rect.top - containerRect.top;
const elBottom = rect.bottom - containerRect.top;
// Skip elements that are completely above the viewport
if (elBottom <= 0) continue;
// Skip elements that start below the viewport
if (elTop >= viewportHeight) break;
// Check if this element is fully visible in the viewport
if (elTop >= 0 && elBottom <= viewportHeight) {{
// Element fully visible - update safe cut point to its bottom
lastSafeY = elBottom;
}} else if (elTop >= 0 && elBottom > viewportHeight) {{
// Element starts in viewport but extends beyond
// Cut before this element
foundCutElement = true;
// Next screenshot should start with this element visible
// We need to scroll so this element's top is at the viewport top
nextStartScroll = currentScroll + elTop;
break;
}} else if (elTop < 0 && elBottom > viewportHeight) {{
// Element spans the entire viewport (very tall element)
// This is a special case - we'll include what we can
lastSafeY = viewportHeight;
nextStartScroll = currentScroll + viewportHeight;
break;
}}
}}
// If no cut element found, use full viewport
if (!foundCutElement) {{
lastSafeY = viewportHeight;
nextStartScroll = currentScroll + viewportHeight;
}}
// Add small padding to avoid cutting too close to text
if (lastSafeY < viewportHeight && lastSafeY > 0) {{
lastSafeY = Math.min(lastSafeY + 5, viewportHeight);
}}
const hasMore = nextStartScroll < container.scrollHeight - 10;
return {{
safe_y: Math.floor(lastSafeY),
has_more: hasMore,
next_start: Math.floor(nextStartScroll)
}};
}}
"""
return page.evaluate(script)
def add_whitespace_mask(page, from_y: int):
"""
Add a whitespace mask to cover content below from_y position.
This creates a div that covers the container from from_y to the bottom,
matching the container's background color.
"""
script = f"""
() => {{
const container = document.querySelector('.container');
if (!container) return false;
// Remove any existing mask
const existingMask = document.getElementById('screenshot-mask');
if (existingMask) existingMask.remove();
// Get container's computed background color
const bgColor = window.getComputedStyle(container).backgroundColor || '#F9F9F6';
// Create mask element
const mask = document.createElement('div');
mask.id = 'screenshot-mask';
mask.style.cssText = `
position: absolute;
left: 0;
right: 0;
top: {from_y}px;
bottom: 0;
background-color: #F9F9F6;
z-index: 9999;
pointer-events: none;
`;
// Ensure container has relative positioning
const containerPosition = window.getComputedStyle(container).position;
if (containerPosition === 'static') {{
container.style.position = 'relative';
}}
container.appendChild(mask);
return true;
}}
"""
return page.evaluate(script)
def remove_whitespace_mask(page):
"""Remove the whitespace mask."""
script = """
() => {
const mask = document.getElementById('screenshot-mask');
if (mask) {
mask.remove();
return true;
}
return false;
}
"""
return page.evaluate(script)
def capture_screenshots(html_path: Path, output_dir: Path):
"""
Capture sequential 3:4 ratio screenshots of the container element.
Args:
html_path: Path to the HTML file
output_dir: Directory to save screenshots
"""
attachments_dir = output_dir / "_attachments"
attachments_dir.mkdir(parents=True, exist_ok=True)
print(f"Opening: {html_path}")
print(f"Screenshots will be saved to: {attachments_dir}")
print(f"Container size: {CONTAINER_WIDTH}x{CONTAINER_HEIGHT} (3:4 ratio)")
print(f"Output size: {OUTPUT_WIDTH}x{OUTPUT_HEIGHT} ({DEVICE_SCALE_FACTOR}x scale)")
print()
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
# Viewport larger than container to ensure full visibility
viewport_width = CONTAINER_WIDTH + 200
viewport_height = CONTAINER_HEIGHT + 200
context = browser.new_context(
viewport={"width": viewport_width, "height": viewport_height},
device_scale_factor=DEVICE_SCALE_FACTOR
)
page = context.new_page()
# Navigate and wait for content
file_url = f"file://{html_path.resolve()}"
page.goto(file_url, wait_until="networkidle")
page.wait_for_timeout(2000) # Wait for fonts/images
# Get container info
container_info = get_container_info(page)
if not container_info:
print("Error: Could not find .container element")
browser.close()
return []
print(f"Container dimensions: {container_info['width']}x{container_info['height']}")
print(f"Content height: {container_info['scrollHeight']}px")
print(f"Visible height: {container_info['clientHeight']}px")
container = page.locator('.container')
scroll_height = container_info['scrollHeight']
client_height = container_info['clientHeight']
# Start from the top
scroll_container(page, 0)
page.wait_for_timeout(100)
screenshot_index = 1
captured_screenshots = []
current_scroll = 0
max_iterations = 50 # Safety limit
print(f"\nCapturing screenshots...")
while screenshot_index <= max_iterations:
# Scroll to current position
actual_scroll = scroll_container(page, current_scroll)
page.wait_for_timeout(150)
# Find safe cut position
cut_info = find_safe_cut_position(page, client_height)
safe_y = cut_info['safe_y']
has_more = cut_info['has_more']
next_start = cut_info['next_start']
# Add mask if we need to hide partial content
needs_mask = safe_y < client_height and has_more
if needs_mask:
add_whitespace_mask(page, safe_y)
page.wait_for_timeout(50)
# Capture screenshot
filename = f"xhs-{screenshot_index:02d}.png"
filepath = attachments_dir / filename
container.screenshot(path=str(filepath))
# Remove mask
if needs_mask:
remove_whitespace_mask(page)
visible_height = safe_y if needs_mask else client_height
print(f" {filename}: scroll={current_scroll}, visible={visible_height}px" +
(" [padded]" if needs_mask else ""))
captured_screenshots.append(str(filepath))
# Check if we're done
if not has_more:
break
# Move to next section
current_scroll = next_start
screenshot_index += 1
# Safety check - if we're not making progress
if current_scroll >= scroll_height - 10:
break
browser.close()
return captured_screenshots
def main():
if len(sys.argv) < 2:
print("Usage: python screenshot.py <html_file_path>")
print()
print("Captures sequential 3:4 ratio screenshots of the container element.")
print("Features:")
print(" - Precise 3:4 aspect ratio (600x800 -> 1200x1600 @2x)")
print(" - Smart text boundary detection (no text cut-off)")
print(" - Automatic whitespace padding when needed")
print(" - Only captures container, excludes page background")
sys.exit(1)
html_path = Path(sys.argv[1]).resolve()
if not html_path.exists():
print(f"Error: File does not exist: {html_path}")
sys.exit(1)
if html_path.suffix.lower() not in ['.html', '.htm']:
print(f"Warning: File does not appear to be HTML: {html_path}")
output_dir = html_path.parent
print("=" * 60)
print("Xiaohongshu Screenshot Capture")
print("=" * 60)
try:
screenshots = capture_screenshots(html_path, output_dir)
print()
print("=" * 60)
print(f"Capture complete!")
print(f"Total screenshots: {len(screenshots)}")
print(f"Output location: {output_dir / '_attachments'}")
print(f"Each screenshot: {OUTPUT_WIDTH}x{OUTPUT_HEIGHT}px (3:4 ratio)")
print("=" * 60)
return 0
except Exception as e:
print(f"Error during capture: {e}")
import traceback
traceback.print_exc()
return 1
if __name__ == "__main__":
sys.exit(main())
Related skills
How it compares
Pick xiaohongshu-images over generic HTML-to-PDF tools when you need Xiaohongshu-specific 3:4 carousels with AI covers and text-safe page slicing.
FAQ
What is xiaohongshu-images?
Transform markdown/HTML into styled 3:4 ratio images for Xiaohongshu
When should I use xiaohongshu-images?
Transform markdown/HTML into styled 3:4 ratio images for Xiaohongshu
Is xiaohongshu-images safe to install?
Review the Security Audits panel on this page before production use.