instagram-carousel
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseInstagram Carousel Generator
Instagram轮播图生成器
Generates fully self-contained, swipeable HTML carousels where every slide is
designed to be exported as an individual 1080×1350px PNG for Instagram.
生成完全独立、可滑动的HTML轮播图,每张幻灯片均可导出为适用于Instagram的1080×1350px独立PNG图片。
Step 1: Collect Brand Details
步骤1:收集品牌详情
Before generating, ask the user for the following (if not already provided):
- Brand name — displayed on first and last slides
- Instagram handle — shown in the IG frame header
- Primary brand color — hex code, or describe and Claude picks one
- Logo — SVG path, brand initial, or skip
- Font preference — see typography table below, or specific Google Fonts
- Tone — professional, casual, playful, bold, minimal, etc.
- Images — profile photo, screenshots, product images, etc.
- Idioma dos slides — default: Português (BR) unless specified otherwise
- Carousel format — standard (7 slides) or alternate sequence (see sequences section)
If the user provides a website URL or brand assets, derive colors and style from those.
If the user says "make me a carousel about X" without brand details, ask before generating. Don't assume defaults.
生成前,请向用户收集以下信息(若未提供):
- 品牌名称 —— 显示在第一张和最后一张幻灯片上
- Instagram账号 —— 显示在IG框架头部
- 品牌主色调 —— 十六进制代码,或描述后由Claude选择
- Logo —— SVG路径、品牌首字母,或跳过
- 字体偏好 —— 参考下方排版表格,或指定Google Fonts字体
- 语气风格 —— 专业、随意、活泼、大胆、极简等
- 图片素材 —— 头像、截图、产品图等
- 幻灯片语言 —— 默认:葡萄牙语(巴西),除非另有指定
- 轮播图格式 —— 标准(7张幻灯片)或自定义序列(见序列部分)
若用户提供网站URL或品牌资产,可从中提取颜色和风格信息。
若用户仅说“为我制作关于X的轮播图”但未提供品牌详情,需先询问再生成,请勿默认设置。
Handling User-Provided Images
处理用户提供的图片
This section applies from the very first HTML generation — not only during export.
When the user provides an image file path (e.g., , ):
/home/user/gestante.png/mnt/user-data/uploads/foto.jpg本节从首次HTML生成阶段即适用 —— 不仅限于导出环节。
当用户提供图片文件路径(例如:、)时:
/home/user/gestante.png/mnt/user-data/uploads/foto.jpg⚠️ Critical Rules
⚠️ 重要规则
- NEVER use relative paths () — they break in every browser context except the exact folder the HTML lives in.
gestante.png - NEVER use — leads to 1.5MB+ base64 inline strings that crash the browser parser.
background: url(filepath) - ALWAYS embed as base64 URI — works in preview, export, and any environment.
data: - ALWAYS generate the HTML via Python () — shell heredocs interpolate
Path.write_text()and backticks, corrupting base64 strings.$
- 永远不要使用相对路径()—— 除非HTML和图片在同一文件夹,否则在所有浏览器环境中都会失效。
gestante.png - 永远不要使用 —— 会生成1.5MB以上的base64内联字符串,导致浏览器解析崩溃。
background: url(filepath) - 始终以base64 URI嵌入 —— 在预览、导出及任何环境下均可正常工作。
data: - 始终通过Python生成HTML()—— Shell heredocs会插值
Path.write_text()和反引号,破坏base64字符串。$
Step-by-step: embed an image
分步操作:嵌入图片
bash
undefinedbash
undefined1. Check the actual file format (extension may lie)
1. 检查实际文件格式(扩展名可能不准确)
file /path/to/image.png
```python
import base64
from pathlib import Pathfile /path/to/image.png
```python
import base64
from pathlib import Path2. Read and encode
2. 读取并编码
img_path = Path("/path/to/image.png")
img_path = Path("/path/to/image.png")
Use "image/jpeg" if file
command says JPEG, else "image/png"
file如果file
命令显示为JPEG则使用"image/jpeg",否则使用"image/png"
filemime = "image/jpeg" # or "image/png"
b64 = base64.b64encode(img_path.read_bytes()).decode()
data_uri = f"data:{mime};base64,{b64}"
mime = "image/jpeg" # 或 "image/png"
b64 = base64.b64encode(img_path.read_bytes()).decode()
data_uri = f"data:{mime};base64,{b64}"
3. Inject into HTML template as a Python variable — never via shell
3. 将HTML作为Python变量注入 —— 切勿通过Shell
html = f"""
<div style="position:relative;width:100%;height:100%;">
<img src="{data_uri}"
style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;">
<div style="position:absolute;inset:0;background:rgba(255,255,255,0.35);z-index:1;"></div>
<!-- slide content goes here, z-index:2 -->
</div>
"""
Path("/home/claude/carousel.html").write_text(html, encoding="utf-8")
undefinedhtml = f"""
<div style="position:relative;width:100%;height:100%;">
<img src="{data_uri}"
style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;">
<div style="position:absolute;inset:0;background:rgba(255,255,255,0.35);z-index:1;"></div>
<!-- 幻灯片内容放在此处,z-index:2 -->
</div>
"""
Path("/home/claude/carousel.html").write_text(html, encoding="utf-8")
undefinedImage as slide background (most common use)
将图片作为幻灯片背景(最常用场景)
html
<!-- Inside the slide div, before any content -->
<img src="{data_uri}"
style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;">
<!-- Semi-transparent overlay so text stays readable -->
<div style="position:absolute;inset:0;background:rgba(255,255,255,0.35);z-index:1;"></div>
<!-- All slide content must have z-index:2 or higher -->For dark slides, use as the overlay instead.
rgba(0,0,0,0.45)html
<!-- 在幻灯片div内,所有内容之前 -->
<img src="{data_uri}"
style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;">
<!-- 半透明覆盖层,确保文字可读 -->
<div style="position:absolute;inset:0;background:rgba(255,255,255,0.35);z-index:1;"></div>
<!-- 所有幻灯片内容的z-index必须为2或更高 -->深色幻灯片请使用作为覆盖层。
rgba(0,0,0,0.45)Common image mistakes to avoid
需避免的常见图片错误
| Mistake | What goes wrong | Fix |
|---|---|---|
| Broken image — relative path only works if HTML and image share the same folder | Always use base64 |
| Browser parser crash, 1.3M token context | Use |
Generating HTML via shell | | Always use Python |
Assuming | File may actually be JPEG; wrong MIME type breaks rendering | Run |
| 错误 | 问题后果 | 修复方案 |
|---|---|---|
| 图片加载失败 —— 相对路径仅在HTML与图片同文件夹时生效 | 始终使用base64 |
| 浏览器解析崩溃,占用1.3M以上上下文令牌 | 使用 |
通过Shell | base64中的 | 始终使用Python |
假设 | 文件实际可能为JPEG;错误的MIME类型会导致渲染失败 | 运行 |
Step 2: Derive the Full Color System
步骤2:生成完整配色系统
From the user's single primary brand color, generate the full 6-token palette:
BRAND_PRIMARY = {user's color} // Main accent — progress bar, icons, tags
BRAND_LIGHT = {primary lightened ~20%} // Secondary accent — tags on dark, pills
BRAND_DARK = {primary darkened ~30%} // CTA text, gradient anchor
LIGHT_BG = {warm or cool off-white} // Light slide background (never pure #fff)
LIGHT_BORDER = {slightly darker than LIGHT_BG} // Dividers on light slides
DARK_BG = {near-black with brand tint} // Dark slide backgroundRules for deriving colors:
- LIGHT_BG: tinted off-white complementing the primary (warm → warm cream, cool → cool gray-white)
- DARK_BG: near-black with subtle brand tint (warm → #1A1918, cool → #0F172A)
- LIGHT_BORDER: always ~1 shade darker than LIGHT_BG
- Brand gradient:
linear-gradient(165deg, BRAND_DARK 0%, BRAND_PRIMARY 50%, BRAND_LIGHT 100%)
根据用户提供的单一品牌主色调,生成包含6个色值的完整配色方案:
BRAND_PRIMARY = {用户提供的颜色} // 主强调色 —— 进度条、图标、标签
BRAND_LIGHT = {主色调提亮约20%} // 次强调色 —— 深色背景上的标签、胶囊按钮
BRAND_DARK = {主色调加深约30%} // CTA文字、渐变锚点色
LIGHT_BG = {暖调或冷调米白色} // 浅色幻灯片背景(永远不要用纯#fff)
LIGHT_BORDER = {比LIGHT_BG稍深的颜色} // 浅色幻灯片上的分隔线
DARK_BG = {带品牌色调的近黑色} // 深色幻灯片背景配色推导规则:
- LIGHT_BG:与主色调互补的米白色(暖色调→暖奶油色,冷色调→冷灰白色)
- DARK_BG:带轻微品牌色调的近黑色(暖色调→#1A1918,冷色调→#0F172A)
- LIGHT_BORDER:始终比LIGHT_BG深1个色阶
- 品牌渐变:
linear-gradient(165deg, BRAND_DARK 0%, BRAND_PRIMARY 50%, BRAND_LIGHT 100%)
Step 3: Set Up Typography
步骤3:设置排版
Based on the user's font preference, pick a heading font and body font from Google Fonts.
| Style | Heading Font | Body Font |
|---|---|---|
| Editorial / premium | Playfair Display | DM Sans |
| Modern / clean | Plus Jakarta Sans (700) | Plus Jakarta Sans (400) |
| Warm / approachable | Lora | Nunito Sans |
| Technical / sharp | Space Grotesk | Space Grotesk |
| Bold / expressive | Fraunces | Outfit |
| Classic / trustworthy | Libre Baskerville | Work Sans |
| Rounded / friendly | Bricolage Grotesque | Bricolage Grotesque |
Font size scale (fixed across all brands):
- Headings: 28–34px, weight 600, letter-spacing -0.3 to -0.5px, line-height 1.1–1.15
- Body: 14px, weight 400, line-height 1.5–1.55
- Tags/labels: 10px, weight 600, letter-spacing 2px, uppercase
- Step numbers: heading font, 26px, weight 300
- Small text: 11–12px
Apply via CSS classes (heading font) and (body font) throughout all slides.
.serif.sans根据用户的字体偏好,从Google Fonts中选择标题字体和正文字体。
| 风格 | 标题字体 | 正文字体 |
|---|---|---|
| 编辑感 / 高端 | Playfair Display | DM Sans |
| 现代 / 简洁 | Plus Jakarta Sans (700) | Plus Jakarta Sans (400) |
| 温暖 / 亲和 | Lora | Nunito Sans |
| 科技感 / 锐利 | Space Grotesk | Space Grotesk |
| 大胆 / 有表现力 | Fraunces | Outfit |
| 经典 / 可靠 | Libre Baskerville | Work Sans |
| 圆润 / 友好 | Bricolage Grotesque | Bricolage Grotesque |
字体大小规范(所有品牌通用):
- 标题:28–34px,字重600,字母间距-0.3至-0.5px,行高1.1–1.15
- 正文:14px,字重400,行高1.5–1.55
- 标签/标注:10px,字重600,字母间距2px,大写
- 步骤编号:使用标题字体,26px,字重300
- 小字:11–12px
通过CSS类(标题字体)和(正文字体)在所有幻灯片中统一应用。
.serif.sansSlide 1 — Hook Rules
幻灯片1 —— 钩子规则
The first slide must stop the scroll in under 1 second. Prioritize these formats:
| Hook format | Example |
|---|---|
| Afirmação polêmica | "Você está usando IA errado" |
| Número + benefício | "7 ferramentas que substituem seu designer" |
| Pergunta que dói | "Por que seus carrosséis têm 0 salvamentos?" |
| Resultado concreto | "Esse post gerou 4.200 seguidores em 3 dias" |
| Inversão de expectativa | "Mais esforço no design = menos alcance" |
Rules:
- Never start with the brand name as headline
- Visual proof on Slide 1 whenever possible (screenshot, result, real number)
- Hook must promise value that the following slides deliver
第一张幻灯片必须在1秒内抓住用户注意力。优先使用以下格式:
| 钩子格式 | 示例 |
|---|---|
| 争议性声明 | "你正在错误地使用AI" |
| 数字+收益 | "7个可以替代设计师的工具" |
| 直击痛点的问题 | "为什么你的轮播图没有被保存?" |
| 具体成果 | "这个帖子3天内吸引了4200名粉丝" |
| 反转预期 | "设计投入越多,曝光量越少" |
规则:
- 永远不要以品牌名称作为标题开头
- 尽可能在幻灯片1中加入视觉证明(截图、成果数据、真实数字)
- 钩子必须承诺后续幻灯片能提供的价值
Slide Sequences
幻灯片序列
Standard (7 slides — default)
标准序列(7张幻灯片 —— 默认)
| # | Type | Background | Purpose |
|---|---|---|---|
| 1 | Hero | LIGHT_BG | Hook — bold statement, logo lockup, optional watermark |
| 2 | Problem | DARK_BG | Pain point — what's broken, frustrating, or outdated |
| 3 | Solution | Brand gradient | The answer — what solves it, optional quote/prompt box |
| 4 | Features | LIGHT_BG | What you get — feature list with icons |
| 5 | Details | DARK_BG | Depth — customization, specs, differentiators |
| 6 | How-to | LIGHT_BG | Steps — numbered workflow or process |
| 7 | CTA | Brand gradient | Call to action — logo, tagline, CTA button. No arrow. Full progress bar. |
| 序号 | 类型 | 背景 | 目的 |
|---|---|---|---|
| 1 | Hero页 | LIGHT_BG | 钩子 —— 大胆声明、Logo组合、可选水印 |
| 2 | 痛点页 | DARK_BG | 痛点 —— 现存问题、痛点、过时之处 |
| 3 | 解决方案页 | 品牌渐变 | 答案 —— 解决方案,可选引用/提示框 |
| 4 | 功能页 | LIGHT_BG | 核心价值 —— 带图标的功能列表 |
| 5 | 详情页 | DARK_BG | 深度信息 —— 自定义选项、规格、差异化优势 |
| 6 | 操作指南页 | LIGHT_BG | 步骤 —— 编号工作流或流程 |
| 7 | CTA页 | 品牌渐变 | 行动号召 —— Logo、标语、CTA按钮。无箭头,进度条满格。 |
Listicle (5–10 slides)
列表型(5–10张幻灯片)
| # | Type | Background |
|---|---|---|
| 1 | Hero | LIGHT_BG |
| 2–N | Item N | Alternating LIGHT/DARK |
| Last | CTA | Brand gradient |
Use for: "X ferramentas", "X erros", "X dicas"
| 序号 | 类型 | 背景 |
|---|---|---|
| 1 | Hero页 | LIGHT_BG |
| 2–N | 第N项 | 交替LIGHT/DARK背景 |
| 最后一张 | CTA页 | 品牌渐变 |
适用于:"X个工具"、"X个错误"、"X个技巧"
Tutorial (7 slides)
教程型(7张幻灯片)
| # | Type | Background |
|---|---|---|
| 1 | Hero | LIGHT_BG |
| 2 | Contexto / Por quê | DARK_BG |
| 3–5 | Passo 1, 2, 3 | Alternating |
| 6 | Resultado esperado | DARK_BG |
| 7 | CTA | Brand gradient |
| 序号 | 类型 | 背景 |
|---|---|---|
| 1 | Hero页 | LIGHT_BG |
| 2 | 背景/原因 | DARK_BG |
| 3–5 | 步骤1、2、3 | 交替背景 |
| 6 | 预期成果 | DARK_BG |
| 7 | CTA页 | 品牌渐变 |
Comparação (5 slides)
对比型(5张幻灯片)
| # | Type | Background |
|---|---|---|
| 1 | Hero (o que será comparado) | LIGHT_BG |
| 2 | Opção A | LIGHT_BG |
| 3 | Opção B | DARK_BG |
| 4 | Veredicto | Brand gradient |
| 5 | CTA | DARK_BG |
General rules for all sequences:
- Start with a hook — first slide must stop the scroll
- End CTA on brand gradient — no swipe arrow, progress bar at 100%
- Alternate light and dark backgrounds for visual rhythm
- Adapt sequence to topic — not every carousel needs all slides
| 序号 | 类型 | 背景 |
|---|---|---|
| 1 | Hero页(说明对比主题) | LIGHT_BG |
| 2 | 选项A | LIGHT_BG |
| 3 | 选项B | DARK_BG |
| 4 | 结论 | 品牌渐变 |
| 5 | CTA页 | DARK_BG |
所有序列通用规则:
- 以钩子开头 —— 第一张幻灯片必须抓住用户注意力
- 最后一张CTA页使用品牌渐变背景 —— 无滑动箭头,进度条100%
- 交替浅色和深色背景,形成视觉节奏
- 根据主题调整序列 —— 并非所有轮播图都需要完整的幻灯片结构
Slide Architecture
幻灯片架构
Format
格式
- Aspect ratio: 4:5 (Instagram carousel standard)
- Each slide is self-contained — all UI elements baked into the image
- Alternate LIGHT_BG and DARK_BG backgrounds for visual rhythm
- 宽高比:4:5(Instagram轮播图标准)
- 每张幻灯片独立完整 —— 所有UI元素都嵌入到图片中
- 交替LIGHT_BG和DARK_BG背景,形成视觉节奏
Required Elements on Every Slide
每张幻灯片必备元素
1. Progress Bar (bottom of every slide)
1. 进度条(每张幻灯片底部)
Shows position in the carousel. Fills as user swipes.
- Position: absolute bottom, full width, 28px horizontal padding, 20px bottom padding
- Track: 3px height, rounded corners
- Fill width:
((slideIndex + 1) / totalSlides) * 100% - Light slides: track,
rgba(0,0,0,0.08)fill,BRAND_PRIMARYcounterrgba(0,0,0,0.3) - Dark slides: track,
rgba(255,255,255,0.12)fill,#fffcounterrgba(255,255,255,0.4) - Counter label beside the bar: "1/7" format, 11px, weight 500
javascript
function progressBar(index, total, isLightSlide) {
const pct = ((index + 1) / total) * 100;
const trackColor = isLightSlide ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.12)';
const fillColor = isLightSlide ? BRAND_PRIMARY : '#fff'; // use actual BRAND_PRIMARY value
const labelColor = isLightSlide ? 'rgba(0,0,0,0.3)' : 'rgba(255,255,255,0.4)';
return `<div style="position:absolute;bottom:0;left:0;right:0;padding:16px 28px 20px;z-index:10;display:flex;align-items:center;gap:10px;">
<div style="flex:1;height:3px;background:${trackColor};border-radius:2px;overflow:hidden;">
<div style="height:100%;width:${pct}%;background:${fillColor};border-radius:2px;"></div>
</div>
<span style="font-size:11px;color:${labelColor};font-weight:500;">${index + 1}/${total}</span>
</div>`;
}⚠️ Important: Always replace with the actual hex value before rendering. Never leave it as a variable name in the HTML output.
BRAND_PRIMARY显示当前在轮播图中的位置,随滑动填充。
- 位置:绝对定位在底部,全宽,左右内边距28px,底部内边距20px
- 轨道:高度3px,圆角
- 填充宽度:
((slideIndex + 1) / totalSlides) * 100% - 浅色幻灯片:轨道,填充
rgba(0,0,0,0.08),计数器BRAND_PRIMARYrgba(0,0,0,0.3) - 深色幻灯片:轨道,填充
rgba(255,255,255,0.12),计数器#fffrgba(255,255,255,0.4) - 轨道旁的计数器标签:"1/7"格式,11px,字重500
javascript
function progressBar(index, total, isLightSlide) {
const pct = ((index + 1) / total) * 100;
const trackColor = isLightSlide ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.12)';
const fillColor = isLightSlide ? BRAND_PRIMARY : '#fff'; // 使用实际的BRAND_PRIMARY色值
const labelColor = isLightSlide ? 'rgba(0,0,0,0.3)' : 'rgba(255,255,255,0.4)';
return `<div style="position:absolute;bottom:0;left:0;right:0;padding:16px 28px 20px;z-index:10;display:flex;align-items:center;gap:10px;">
<div style="flex:1;height:3px;background:${trackColor};border-radius:2px;overflow:hidden;">
<div style="height:100%;width:${pct}%;background:${fillColor};border-radius:2px;"></div>
</div>
<span style="font-size:11px;color:${labelColor};font-weight:500;">${index + 1}/${total}</span>
</div>`;
}⚠️ 重要提示: 渲染前务必将替换为实际的十六进制色值,切勿在HTML输出中保留变量名。
BRAND_PRIMARY2. Swipe Arrow (right edge — every slide EXCEPT the last)
2. 滑动箭头(右侧 —— 除最后一张外的所有幻灯片)
Subtle chevron guiding the user to keep swiping. Removed on the last slide.
- Position: absolute right, full height, 48px wide
- Background: gradient fade transparent → subtle tint
- Chevron: 24×24 SVG, rounded strokes
- Light slides: bg,
rgba(0,0,0,0.06)strokergba(0,0,0,0.25) - Dark slides: bg,
rgba(255,255,255,0.08)strokergba(255,255,255,0.35)
javascript
function swipeArrow(isLightSlide) {
const bg = isLightSlide ? 'rgba(0,0,0,0.06)' : 'rgba(255,255,255,0.08)';
const stroke = isLightSlide ? 'rgba(0,0,0,0.25)' : 'rgba(255,255,255,0.35)';
return `<div style="position:absolute;right:0;top:0;bottom:0;width:48px;z-index:9;display:flex;align-items:center;justify-content:center;background:linear-gradient(to right,transparent,${bg});">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M9 6l6 6-6 6" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>`;
}引导用户继续滑动的微妙 Chevron 图标,最后一张幻灯片需移除。
- 位置:绝对定位在右侧,全高,宽度48px
- 背景:渐变透明→轻微色调
- Chevron:24×24 SVG,圆角描边
- 浅色幻灯片:背景,描边
rgba(0,0,0,0.06)rgba(0,0,0,0.25) - 深色幻灯片:背景,描边
rgba(255,255,255,0.08)rgba(255,255,255,0.35)
javascript
function swipeArrow(isLightSlide) {
const bg = isLightSlide ? 'rgba(0,0,0,0.06)' : 'rgba(255,255,255,0.08)';
const stroke = isLightSlide ? 'rgba(0,0,0,0.25)' : 'rgba(255,255,255,0.35)';
return `<div style="position:absolute;right:0;top:0;bottom:0;width:48px;z-index:9;display:flex;align-items:center;justify-content:center;background:linear-gradient(to right,transparent,${bg});">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M9 6l6 6-6 6" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>`;
}Reusable Components
可复用组件
Strikethrough pills
删除线胶囊按钮
html
<span style="font-size:11px;padding:5px 12px;border:1px solid rgba(255,255,255,0.1);border-radius:20px;color:#6B6560;text-decoration:line-through;">{Old tool}</span>html
<span style="font-size:11px;padding:5px 12px;border:1px solid rgba(255,255,255,0.1);border-radius:20px;color:#6B6560;text-decoration:line-through;">{旧工具}</span>Tag pills
标签胶囊按钮
html
<span style="font-size:11px;padding:5px 12px;background:rgba(255,255,255,0.06);border-radius:20px;color:{BRAND_LIGHT};">{Label}</span>html
<span style="font-size:11px;padding:5px 12px;background:rgba(255,255,255,0.06);border-radius:20px;color:{BRAND_LIGHT};">{标签}</span>Prompt / quote box
提示/引用框
html
<div style="padding:16px;background:rgba(0,0,0,0.15);border-radius:12px;border:1px solid rgba(255,255,255,0.08);">
<p class="sans" style="font-size:13px;color:rgba(255,255,255,0.5);margin-bottom:6px;">{Label}</p>
<p class="serif" style="font-size:15px;color:#fff;font-style:italic;line-height:1.4;">"{Quote text}"</p>
</div>html
<div style="padding:16px;background:rgba(0,0,0,0.15);border-radius:12px;border:1px solid rgba(255,255,255,0.08);">
<p class="sans" style="font-size:13px;color:rgba(255,255,255,0.5);margin-bottom:6px;">{标签}</p>
<p class="serif" style="font-size:15px;color:#fff;font-style:italic;line-height:1.4;">"{引用文本}"</p>
</div>Feature list
功能列表
html
<div style="display:flex;align-items:flex-start;gap:14px;padding:10px 0;border-bottom:1px solid {LIGHT_BORDER};">
<span style="color:{BRAND_PRIMARY};font-size:15px;width:18px;text-align:center;">{icon}</span>
<div>
<span class="sans" style="font-size:14px;font-weight:600;color:{DARK_BG};">{Label}</span>
<span class="sans" style="font-size:12px;color:#8A8580;">{Description}</span>
</div>
</div>html
<div style="display:flex;align-items:flex-start;gap:14px;padding:10px 0;border-bottom:1px solid {LIGHT_BORDER};">
<span style="color:{BRAND_PRIMARY};font-size:15px;width:18px;text-align:center;">{图标}</span>
<div>
<span class="sans" style="font-size:14px;font-weight:600;color:{DARK_BG};">{标签}</span>
<span class="sans" style="font-size:12px;color:#8A8580;">{描述}</span>
</div>
</div>Numbered steps
编号步骤
html
<div style="display:flex;align-items:flex-start;gap:16px;padding:14px 0;border-bottom:1px solid {LIGHT_BORDER};">
<span class="serif" style="font-size:26px;font-weight:300;color:{BRAND_PRIMARY};min-width:34px;line-height:1;">01</span>
<div>
<span class="sans" style="font-size:14px;font-weight:600;color:{DARK_BG};">{Step title}</span>
<span class="sans" style="font-size:12px;color:#8A8580;">{Step description}</span>
</div>
</div>html
<div style="display:flex;align-items:flex-start;gap:16px;padding:14px 0;border-bottom:1px solid {LIGHT_BORDER};">
<span class="serif" style="font-size:26px;font-weight:300;color:{BRAND_PRIMARY};min-width:34px;line-height:1;">01</span>
<div>
<span class="sans" style="font-size:14px;font-weight:600;color:{DARK_BG};">{步骤标题}</span>
<span class="sans" style="font-size:12px;color:#8A8580;">{步骤描述}</span>
</div>
</div>Color swatches
颜色样本
html
<div style="width:32px;height:32px;border-radius:8px;background:{color};border:1px solid rgba(255,255,255,0.08);"></div>html
<div style="width:32px;height:32px;border-radius:8px;background:{color};border:1px solid rgba(255,255,255,0.08);"></div>CTA button (final slide only)
CTA按钮(仅最后一张幻灯片)
html
<div style="display:inline-flex;align-items:center;gap:8px;padding:12px 28px;background:{LIGHT_BG};color:{BRAND_DARK};font-family:'{BODY_FONT}',sans-serif;font-weight:600;font-size:14px;border-radius:28px;">
{CTA text}
</div>html
<div style="display:inline-flex;align-items:center;gap:8px;padding:12px 28px;background:{LIGHT_BG};color:{BRAND_DARK};font-family:'{BODY_FONT}',sans-serif;font-weight:600;font-size:14px;border-radius:28px;">
{CTA文本}
</div>Tag / Category Label
标签/分类标注
html
<span class="sans" style="display:inline-block;font-size:10px;font-weight:600;letter-spacing:2px;color:{color};margin-bottom:16px;">{TAG TEXT}</span>- Light slides:
BRAND_PRIMARY - Dark slides:
BRAND_LIGHT - Brand gradient slides:
rgba(255,255,255,0.6)
html
<span class="sans" style="display:inline-block;font-size:10px;font-weight:600;letter-spacing:2px;color:{color};margin-bottom:16px;">{标签文本}</span>- 浅色幻灯片:
BRAND_PRIMARY - 深色幻灯片:
BRAND_LIGHT - 品牌渐变幻灯片:
rgba(255,255,255,0.6)
Logo Lockup (first and last slides)
Logo组合(第一张和最后一张幻灯片)
- If logo icon: 40px circle (BRAND_PRIMARY bg) + icon centered + brand name beside
- If initials: 40px circle with first letter in white
- Brand name: 13px, weight 600, letter-spacing 0.5px
- 若为Logo图标:40px圆形(BRAND_PRIMARY背景)+ 居中图标 + 旁侧品牌名称
- 若为首字母:40px圆形,白色首字母
- 品牌名称:13px,字重600,字母间距0.5px
Layout Rules
布局规则
- Content padding: standard
0 36px - Bottom-aligned slides with progress bar: to clear the bar
0 36px 52px - Hero/CTA slides:
justify-content: center - Content-heavy slides:
justify-content: flex-end - Content must never overlap the progress bar — use
padding-bottom: 52px
- 内容内边距:标准
0 36px - 带进度条的底部对齐幻灯片:,避免遮挡进度条
0 36px 52px - Hero/CTA幻灯片:
justify-content: center - 内容密集型幻灯片:
justify-content: flex-end - 内容绝不能覆盖进度条 —— 使用
padding-bottom: 52px
Instagram Frame (Preview Wrapper)
Instagram框架(预览容器)
When displaying in chat, wrap in an Instagram-style frame:
- Header: Avatar (BRAND_PRIMARY circle + logo) + handle + subtitle
- Viewport: 4:5 aspect ratio, swipeable/draggable track with all slides
- Dots: Small dot indicators below the viewport
- Actions: Heart, comment, share, bookmark SVG icons
- Caption: Handle + short description + "2 HOURS AGO" timestamp
Include pointer-based swipe/drag interaction for preview. Slides are still standalone export-ready images.
Important: must be exactly 420px wide. The carousel viewport is 420×525px. Do NOT change this width — export depends on it.
.ig-frame在聊天中展示时,需包裹在Instagram风格的框架内:
- 头部: 头像(BRAND_PRIMARY圆形+Logo)+ 账号 + 副标题
- 视口: 4:5宽高比,包含所有幻灯片的可滑动/拖拽轨道
- 指示器: 视口下方的小圆点指示器
- 操作按钮: 点赞、评论、分享、收藏SVG图标
- 文案: 账号 + 简短描述 + "2 HOURS AGO"时间戳
支持基于指针的滑动/拖拽交互预览。幻灯片仍为可独立导出的图片。
重要提示: 宽度必须精确为420px。轮播图视口为420×525px。请勿修改此宽度 —— 导出依赖该尺寸。
.ig-frameReview Flow
审核流程
Always follow this flow. Never skip to export without approval.
- Generate the HTML preview first — never jump directly to export
- Show the preview and ask: "Quais slides precisam de ajuste antes de exportar?"
- Fix only the mentioned slides — never regenerate the entire carousel unless the direction fundamentally changes
- Only proceed to export when the user explicitly confirms approval (e.g., "pode exportar", "aprovado", "ok")
务必遵循此流程,未经批准切勿直接导出。
- 先生成HTML预览 —— 切勿直接跳转到导出环节
- 展示预览并询问:"导出前需要调整哪些幻灯片?"
- 仅修改用户提及的幻灯片 —— 除非方向发生根本性变化,否则切勿重新生成整个轮播图
- 仅在用户明确确认批准后(例如:"可以导出"、"已批准"、"ok"),再进行导出
Exporting Slides as Instagram-Ready PNGs
将幻灯片导出为适用于Instagram的PNG
After the user approves the carousel preview, export each slide as an individual 1080×1350px PNG.
用户批准轮播图预览后,将每张幻灯片导出为独立的1080×1350px PNG。
Critical Export Rules
导出重要规则
-
Use Python for HTML generation — never use shell scripts with variable interpolation. Always useor
Path.write_text().open().write() -
Embed images as base64 — all user-uploaded images must be base64-encoded asURIs. Check actual file format with the
data:image/jpeg;base64,...command — afileextension may contain a JPEG..png -
Keep the 420px layout width — use Playwright'sto scale up to 1080px output WITHOUT changing the layout viewport.
device_scale_factor
-
使用Python生成HTML —— 切勿使用带变量插值的Shell脚本。始终使用或
Path.write_text()。open().write() -
以base64嵌入图片 —— 所有用户上传的图片必须编码为格式的URI。使用
data:image/jpeg;base64,...命令检查实际文件格式 ——file扩展名的文件可能实际为JPEG。.png -
保持420px布局宽度 —— 使用Playwright的放大到1080px输出,切勿修改布局视口。
device_scale_factor
Install Playwright (only if needed)
安装Playwright(仅在需要时)
Before running the export script, check and install only if missing:
bash
python3 -c "import playwright" 2>/dev/null || pip3 install playwright
python3 -c "from playwright.sync_api import sync_playwright; sync_playwright().__enter__().chromium" 2>/dev/null || python3 -m playwright install chromium运行导出脚本前,检查并仅在缺失时安装:
bash
python3 -c "import playwright" 2>/dev/null || pip3 install playwright
python3 -c "from playwright.sync_api import sync_playwright; sync_playwright().__enter__().chromium" 2>/dev/null || python3 -m playwright install chromiumExport Script
导出脚本
python
import asyncio
from pathlib import Path
from playwright.async_api import async_playwright
INPUT_HTML = Path("/path/to/carousel.html")
OUTPUT_DIR = Path("/path/to/output/slides")
OUTPUT_DIR.mkdir(exist_ok=True)
TOTAL_SLIDES = 7 # Update to match your carousel
VIEW_W = 420
VIEW_H = 525
SCALE = 1080 / 420 # = 2.5714...
async def export_slides():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page(
viewport={"width": VIEW_W, "height": VIEW_H},
device_scale_factor=SCALE,
)
html_content = INPUT_HTML.read_text(encoding="utf-8")
await page.set_content(html_content, wait_until="networkidle")
await page.wait_for_timeout(3000) # Wait for Google Fonts to load
# Hide IG frame chrome, show only the slide viewport
await page.evaluate("""() => {
document.querySelectorAll('.ig-header,.ig-dots,.ig-actions,.ig-caption')
.forEach(el => el.style.display='none');
const frame = document.querySelector('.ig-frame');
frame.style.cssText = 'width:420px;height:525px;max-width:none;border-radius:0;box-shadow:none;overflow:hidden;margin:0;';
const viewport = document.querySelector('.carousel-viewport');
viewport.style.cssText = 'width:420px;height:525px;aspect-ratio:unset;overflow:hidden;cursor:default;';
document.body.style.cssText = 'padding:0;margin:0;display:block;overflow:hidden;';
}""")
await page.wait_for_timeout(500)
for i in range(TOTAL_SLIDES):
await page.evaluate("""(idx) => {
const track = document.querySelector('.carousel-track');
track.style.transition = 'none';
track.style.transform = 'translateX(' + (-idx * 420) + 'px)';
}""", i)
await page.wait_for_timeout(400)
await page.screenshot(
path=str(OUTPUT_DIR / f"slide_{i+1}.png"),
clip={"x": 0, "y": 0, "width": VIEW_W, "height": VIEW_H}
)
print(f"Exported slide {i+1}/{TOTAL_SLIDES}")
await browser.close()
asyncio.run(export_slides())python
import asyncio
from pathlib import Path
from playwright.async_api import async_playwright
INPUT_HTML = Path("/path/to/carousel.html")
OUTPUT_DIR = Path("/path/to/output/slides")
OUTPUT_DIR.mkdir(exist_ok=True)
TOTAL_SLIDES = 7 # 根据你的轮播图更新此数值
VIEW_W = 420
VIEW_H = 525
SCALE = 1080 / 420 # = 2.5714...
async def export_slides():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page(
viewport={"width": VIEW_W, "height": VIEW_H},
device_scale_factor=SCALE,
)
html_content = INPUT_HTML.read_text(encoding="utf-8")
await page.set_content(html_content, wait_until="networkidle")
await page.wait_for_timeout(3000) # 等待Google Fonts加载
# 隐藏IG框架的chrome元素,仅显示幻灯片视口
await page.evaluate("""() => {
document.querySelectorAll('.ig-header,.ig-dots,.ig-actions,.ig-caption')
.forEach(el => el.style.display='none');
const frame = document.querySelector('.ig-frame');
frame.style.cssText = 'width:420px;height:525px;max-width:none;border-radius:0;box-shadow:none;overflow:hidden;margin:0;';
const viewport = document.querySelector('.carousel-viewport');
viewport.style.cssText = 'width:420px;height:525px;aspect-ratio:unset;overflow:hidden;cursor:default;';
document.body.style.cssText = 'padding:0;margin:0;display:block;overflow:hidden;';
}""")
await page.wait_for_timeout(500)
for i in range(TOTAL_SLIDES):
await page.evaluate("""(idx) => {
const track = document.querySelector('.carousel-track');
track.style.transition = 'none';
track.style.transform = 'translateX(' + (-idx * 420) + 'px)';
}""", i)
await page.wait_for_timeout(400)
await page.screenshot(
path=str(OUTPUT_DIR / f"slide_{i+1}.png"),
clip={"x": 0, "y": 0, "width": VIEW_W, "height": VIEW_H}
)
print(f"已导出幻灯片 {i+1}/{TOTAL_SLIDES}")
await browser.close()
asyncio.run(export_slides())Why This Works
工作原理
- renders at high DPI — a 420px element becomes 1080px in the output. Layout stays at 420px.
device_scale_factor=2.5714 - captures only the carousel viewport, not browser chrome.
clip - gives Google Fonts time to load.
wait_for_timeout(3000) - disables swipe animation so slides snap instantly.
track.style.transition = 'none'
- 以高DPI渲染 —— 420px的元素在输出中变为1080px,布局保持420px不变。
device_scale_factor=2.5714 - 仅捕获轮播图视口,不包含浏览器chrome元素。
clip - 等待Google Fonts加载完成。
wait_for_timeout(3000) - 禁用滑动动画,使幻灯片瞬间切换。
track.style.transition = 'none'
Common Export Mistakes to Avoid
需避免的常见导出错误
| Mistake | What goes wrong | Fix |
|---|---|---|
| Setting viewport to 1080×1350 | Layout reflows — fonts tiny, spacing breaks | Keep viewport at 420×525, use |
| Using shell scripts to generate HTML | | Always use Python for HTML generation |
| Not waiting for fonts | Headings render in fallback system fonts | |
| Not hiding IG frame chrome | Export includes header, dots, caption | Hide |
Changing | Entire layout shifts | Always keep at exactly 420px |
Leaving | Color renders as invalid / invisible | Always interpolate actual hex values into HTML |
| 错误 | 问题后果 | 修复方案 |
|---|---|---|
| 将视口设置为1080×1350 | 布局重排 —— 字体过小,间距错乱 | 保持视口为420×525,使用 |
| 使用Shell脚本生成HTML | | 始终使用Python生成HTML |
| 未等待字体加载 | 标题回退到系统默认字体 | 页面加载后执行 |
| 未隐藏IG框架chrome元素 | 导出内容包含头部、指示器、文案 | 隐藏 |
修改 | 整个布局偏移 | 始终保持宽度为精确的420px |
在CSS中保留 | 颜色渲染无效/不可见 | 始终将实际十六进制色值插入HTML |
Design Principles
设计原则
- Every slide is export-ready — arrow and progress bar are part of the slide image
- Light/dark alternation — creates visual rhythm across swipes
- Heading + body font pairing — display font for impact, body for readability
- Brand-derived palette — all colors stem from one primary, keeping everything cohesive
- Progressive disclosure — progress bar fills and arrow guides forward
- Last slide is special — no arrow, full progress bar, clear CTA
- Consistent components — same tag style, list style, spacing across all slides
- Content padding clears UI — body text never overlaps progress bar or arrow
- Hook-first copy — Slide 1 exists to stop the scroll, not to introduce the brand
- Iterate fast — show preview, fix specific slides, don't rebuild from scratch
- 每张幻灯片均可直接导出 —— 箭头和进度条是幻灯片图片的一部分
- 明暗交替 —— 在滑动过程中形成视觉节奏
- 标题+正文字体搭配 —— 展示字体增强冲击力,正文字体保证可读性
- 品牌衍生配色 —— 所有颜色源自单一主色调,保持整体一致性
- 渐进式信息披露 —— 进度条填充和箭头引导用户前进
- 最后一张幻灯片特殊处理 —— 无箭头,进度条满格,清晰的CTA
- 组件一致性 —— 所有幻灯片使用相同的标签样式、列表样式和间距
- 内容避开UI元素 —— 正文永远不覆盖进度条或箭头
- 钩子优先文案 —— 幻灯片1的目的是抓住用户注意力,而非介绍品牌
- 快速迭代 —— 展示预览,修改特定幻灯片,无需从头重建