instagram-carousel

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Instagram 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):
  1. Brand name — displayed on first and last slides
  2. Instagram handle — shown in the IG frame header
  3. Primary brand color — hex code, or describe and Claude picks one
  4. Logo — SVG path, brand initial, or skip
  5. Font preference — see typography table below, or specific Google Fonts
  6. Tone — professional, casual, playful, bold, minimal, etc.
  7. Images — profile photo, screenshots, product images, etc.
  8. Idioma dos slides — default: Português (BR) unless specified otherwise
  9. 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.

生成前,请向用户收集以下信息(若未提供):
  1. 品牌名称 —— 显示在第一张和最后一张幻灯片上
  2. Instagram账号 —— 显示在IG框架头部
  3. 品牌主色调 —— 十六进制代码,或描述后由Claude选择
  4. Logo —— SVG路径、品牌首字母,或跳过
  5. 字体偏好 —— 参考下方排版表格,或指定Google Fonts字体
  6. 语气风格 —— 专业、随意、活泼、大胆、极简等
  7. 图片素材 —— 头像、截图、产品图等
  8. 幻灯片语言 —— 默认:葡萄牙语(巴西),除非另有指定
  9. 轮播图格式 —— 标准(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

⚠️ 重要规则

  1. NEVER use relative paths (
    gestante.png
    ) — they break in every browser context except the exact folder the HTML lives in.
  2. NEVER use
    background: url(filepath)
    — leads to 1.5MB+ base64 inline strings that crash the browser parser.
  3. ALWAYS embed as base64
    data:
    URI
    — works in preview, export, and any environment.
  4. ALWAYS generate the HTML via Python (
    Path.write_text()
    ) — shell heredocs interpolate
    $
    and backticks, corrupting base64 strings.
  1. 永远不要使用相对路径
    gestante.png
    )—— 除非HTML和图片在同一文件夹,否则在所有浏览器环境中都会失效。
  2. 永远不要使用
    background: url(filepath)
    —— 会生成1.5MB以上的base64内联字符串,导致浏览器解析崩溃。
  3. 始终以base64
    data:
    URI嵌入
    —— 在预览、导出及任何环境下均可正常工作。
  4. 始终通过Python生成HTML
    Path.write_text()
    )—— Shell heredocs会插值
    $
    和反引号,破坏base64字符串。

Step-by-step: embed an image

分步操作:嵌入图片

bash
undefined
bash
undefined

1. Check the actual file format (extension may lie)

1. 检查实际文件格式(扩展名可能不准确)

file /path/to/image.png

```python
import base64
from pathlib import Path
file /path/to/image.png

```python
import base64
from pathlib import Path

2. 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
命令显示为JPEG则使用"image/jpeg",否则使用"image/png"

mime = "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")
undefined
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> <!-- 幻灯片内容放在此处,z-index:2 --> </div> """
Path("/home/claude/carousel.html").write_text(html, encoding="utf-8")
undefined

Image 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
rgba(0,0,0,0.45)
as the overlay instead.
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

需避免的常见图片错误

MistakeWhat goes wrongFix
<img src="gestante.png">
Broken image — relative path only works if HTML and image share the same folderAlways use base64
data:
URI
background: url('data:...')
inline with 1.5MB base64
Browser parser crash, 1.3M token contextUse
<img>
tag with
object-fit:cover
Generating HTML via shell
echo
or heredoc
$
and backtick characters in base64 get interpolated and corrupt the string
Always use Python
Path.write_text()
Assuming
.png
extension = PNG format
File may actually be JPEG; wrong MIME type breaks renderingRun
file
command to detect actual format

错误问题后果修复方案
<img src="gestante.png">
图片加载失败 —— 相对路径仅在HTML与图片同文件夹时生效始终使用base64
data:
URI
background: url('data:...')
内联1.5MB以上的base64
浏览器解析崩溃,占用1.3M以上上下文令牌使用
<img>
标签搭配
object-fit:cover
通过Shell
echo
或heredoc生成HTML
base64中的
$
和反引号会被插值,导致字符串损坏
始终使用Python
Path.write_text()
假设
.png
扩展名=PNG格式
文件实际可能为JPEG;错误的MIME类型会导致渲染失败运行
file
命令检测实际格式

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 background
Rules 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.
StyleHeading FontBody Font
Editorial / premiumPlayfair DisplayDM Sans
Modern / cleanPlus Jakarta Sans (700)Plus Jakarta Sans (400)
Warm / approachableLoraNunito Sans
Technical / sharpSpace GroteskSpace Grotesk
Bold / expressiveFrauncesOutfit
Classic / trustworthyLibre BaskervilleWork Sans
Rounded / friendlyBricolage GrotesqueBricolage 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
.serif
(heading font) and
.sans
(body font) throughout all slides.

根据用户的字体偏好,从Google Fonts中选择标题字体正文字体
风格标题字体正文字体
编辑感 / 高端Playfair DisplayDM Sans
现代 / 简洁Plus Jakarta Sans (700)Plus Jakarta Sans (400)
温暖 / 亲和LoraNunito Sans
科技感 / 锐利Space GroteskSpace Grotesk
大胆 / 有表现力FrauncesOutfit
经典 / 可靠Libre BaskervilleWork Sans
圆润 / 友好Bricolage GrotesqueBricolage 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
(标题字体)和
.sans
(正文字体)在所有幻灯片中统一应用。

Slide 1 — Hook Rules

幻灯片1 —— 钩子规则

The first slide must stop the scroll in under 1 second. Prioritize these formats:
Hook formatExample
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张幻灯片 —— 默认)

#TypeBackgroundPurpose
1HeroLIGHT_BGHook — bold statement, logo lockup, optional watermark
2ProblemDARK_BGPain point — what's broken, frustrating, or outdated
3SolutionBrand gradientThe answer — what solves it, optional quote/prompt box
4FeaturesLIGHT_BGWhat you get — feature list with icons
5DetailsDARK_BGDepth — customization, specs, differentiators
6How-toLIGHT_BGSteps — numbered workflow or process
7CTABrand gradientCall to action — logo, tagline, CTA button. No arrow. Full progress bar.
序号类型背景目的
1Hero页LIGHT_BG钩子 —— 大胆声明、Logo组合、可选水印
2痛点页DARK_BG痛点 —— 现存问题、痛点、过时之处
3解决方案页品牌渐变答案 —— 解决方案,可选引用/提示框
4功能页LIGHT_BG核心价值 —— 带图标的功能列表
5详情页DARK_BG深度信息 —— 自定义选项、规格、差异化优势
6操作指南页LIGHT_BG步骤 —— 编号工作流或流程
7CTA页品牌渐变行动号召 —— Logo、标语、CTA按钮。无箭头,进度条满格。

Listicle (5–10 slides)

列表型(5–10张幻灯片)

#TypeBackground
1HeroLIGHT_BG
2–NItem NAlternating LIGHT/DARK
LastCTABrand gradient
Use for: "X ferramentas", "X erros", "X dicas"
序号类型背景
1Hero页LIGHT_BG
2–N第N项交替LIGHT/DARK背景
最后一张CTA页品牌渐变
适用于:"X个工具"、"X个错误"、"X个技巧"

Tutorial (7 slides)

教程型(7张幻灯片)

#TypeBackground
1HeroLIGHT_BG
2Contexto / Por quêDARK_BG
3–5Passo 1, 2, 3Alternating
6Resultado esperadoDARK_BG
7CTABrand gradient
序号类型背景
1Hero页LIGHT_BG
2背景/原因DARK_BG
3–5步骤1、2、3交替背景
6预期成果DARK_BG
7CTA页品牌渐变

Comparação (5 slides)

对比型(5张幻灯片)

#TypeBackground
1Hero (o que será comparado)LIGHT_BG
2Opção ALIGHT_BG
3Opção BDARK_BG
4VeredictoBrand gradient
5CTADARK_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

序号类型背景
1Hero页(说明对比主题)LIGHT_BG
2选项ALIGHT_BG
3选项BDARK_BG
4结论品牌渐变
5CTA页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:
    rgba(0,0,0,0.08)
    track,
    BRAND_PRIMARY
    fill,
    rgba(0,0,0,0.3)
    counter
  • Dark slides:
    rgba(255,255,255,0.12)
    track,
    #fff
    fill,
    rgba(255,255,255,0.4)
    counter
  • 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
BRAND_PRIMARY
with the actual hex value before rendering. Never leave it as a variable name in the HTML output.
显示当前在轮播图中的位置,随滑动填充。
  • 位置:绝对定位在底部,全宽,左右内边距28px,底部内边距20px
  • 轨道:高度3px,圆角
  • 填充宽度:
    ((slideIndex + 1) / totalSlides) * 100%
  • 浅色幻灯片:轨道
    rgba(0,0,0,0.08)
    ,填充
    BRAND_PRIMARY
    ,计数器
    rgba(0,0,0,0.3)
  • 深色幻灯片:轨道
    rgba(255,255,255,0.12)
    ,填充
    #fff
    ,计数器
    rgba(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>`;
}
⚠️ 重要提示: 渲染前务必将
BRAND_PRIMARY
替换为实际的十六进制色值,切勿在HTML输出中保留变量名。

2. 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:
    rgba(0,0,0,0.06)
    bg,
    rgba(0,0,0,0.25)
    stroke
  • Dark slides:
    rgba(255,255,255,0.08)
    bg,
    rgba(255,255,255,0.35)
    stroke
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:
    0 36px
    standard
  • Bottom-aligned slides with progress bar:
    0 36px 52px
    to clear the bar
  • 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:
.ig-frame
must be exactly 420px wide. The carousel viewport is 420×525px. Do NOT change this width — export depends on it.

在聊天中展示时,需包裹在Instagram风格的框架内:
  • 头部: 头像(BRAND_PRIMARY圆形+Logo)+ 账号 + 副标题
  • 视口: 4:5宽高比,包含所有幻灯片的可滑动/拖拽轨道
  • 指示器: 视口下方的小圆点指示器
  • 操作按钮: 点赞、评论、分享、收藏SVG图标
  • 文案: 账号 + 简短描述 + "2 HOURS AGO"时间戳
支持基于指针的滑动/拖拽交互预览。幻灯片仍为可独立导出的图片。
重要提示:
.ig-frame
宽度必须精确为420px。轮播图视口为420×525px。请勿修改此宽度 —— 导出依赖该尺寸。

Review Flow

审核流程

Always follow this flow. Never skip to export without approval.
  1. Generate the HTML preview first — never jump directly to export
  2. Show the preview and ask: "Quais slides precisam de ajuste antes de exportar?"
  3. Fix only the mentioned slides — never regenerate the entire carousel unless the direction fundamentally changes
  4. Only proceed to export when the user explicitly confirms approval (e.g., "pode exportar", "aprovado", "ok")

务必遵循此流程,未经批准切勿直接导出。
  1. 先生成HTML预览 —— 切勿直接跳转到导出环节
  2. 展示预览并询问:"导出前需要调整哪些幻灯片?"
  3. 仅修改用户提及的幻灯片 —— 除非方向发生根本性变化,否则切勿重新生成整个轮播图
  4. 仅在用户明确确认批准后(例如:"可以导出"、"已批准"、"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

导出重要规则

  1. Use Python for HTML generation — never use shell scripts with variable interpolation. Always use
    Path.write_text()
    or
    open().write()
    .
  2. Embed images as base64 — all user-uploaded images must be base64-encoded as
    data:image/jpeg;base64,...
    URIs. Check actual file format with the
    file
    command — a
    .png
    extension may contain a JPEG.
  3. Keep the 420px layout width — use Playwright's
    device_scale_factor
    to scale up to 1080px output WITHOUT changing the layout viewport.
  1. 使用Python生成HTML —— 切勿使用带变量插值的Shell脚本。始终使用
    Path.write_text()
    open().write()
  2. 以base64嵌入图片 —— 所有用户上传的图片必须编码为
    data:image/jpeg;base64,...
    格式的URI。使用
    file
    命令检查实际文件格式 ——
    .png
    扩展名的文件可能实际为JPEG。
  3. 保持420px布局宽度 —— 使用Playwright的
    device_scale_factor
    放大到1080px输出,切勿修改布局视口。

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 chromium

Export 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

工作原理

  • device_scale_factor=2.5714
    renders at high DPI — a 420px element becomes 1080px in the output. Layout stays at 420px.
  • clip
    captures only the carousel viewport, not browser chrome.
  • wait_for_timeout(3000)
    gives Google Fonts time to load.
  • track.style.transition = 'none'
    disables swipe animation so slides snap instantly.
  • device_scale_factor=2.5714
    以高DPI渲染 —— 420px的元素在输出中变为1080px,布局保持420px不变。
  • clip
    仅捕获轮播图视口,不包含浏览器chrome元素。
  • wait_for_timeout(3000)
    等待Google Fonts加载完成。
  • track.style.transition = 'none'
    禁用滑动动画,使幻灯片瞬间切换。

Common Export Mistakes to Avoid

需避免的常见导出错误

MistakeWhat goes wrongFix
Setting viewport to 1080×1350Layout reflows — fonts tiny, spacing breaksKeep viewport at 420×525, use
device_scale_factor
Using shell scripts to generate HTML
$
signs and backticks get interpolated
Always use Python for HTML generation
Not waiting for fontsHeadings render in fallback system fonts
wait_for_timeout(3000)
after page load
Not hiding IG frame chromeExport includes header, dots, captionHide
.ig-header,.ig-dots,.ig-actions,.ig-caption
Changing
.ig-frame
width
Entire layout shiftsAlways keep at exactly 420px
Leaving
BRAND_PRIMARY
as variable name in CSS
Color renders as invalid / invisibleAlways interpolate actual hex values into HTML

错误问题后果修复方案
将视口设置为1080×1350布局重排 —— 字体过小,间距错乱保持视口为420×525,使用
device_scale_factor
使用Shell脚本生成HTML
$
符号和反引号被插值
始终使用Python生成HTML
未等待字体加载标题回退到系统默认字体页面加载后执行
wait_for_timeout(3000)
未隐藏IG框架chrome元素导出内容包含头部、指示器、文案隐藏
.ig-header,.ig-dots,.ig-actions,.ig-caption
修改
.ig-frame
宽度
整个布局偏移始终保持宽度为精确的420px
在CSS中保留
BRAND_PRIMARY
变量名
颜色渲染无效/不可见始终将实际十六进制色值插入HTML

Design Principles

设计原则

  1. Every slide is export-ready — arrow and progress bar are part of the slide image
  2. Light/dark alternation — creates visual rhythm across swipes
  3. Heading + body font pairing — display font for impact, body for readability
  4. Brand-derived palette — all colors stem from one primary, keeping everything cohesive
  5. Progressive disclosure — progress bar fills and arrow guides forward
  6. Last slide is special — no arrow, full progress bar, clear CTA
  7. Consistent components — same tag style, list style, spacing across all slides
  8. Content padding clears UI — body text never overlaps progress bar or arrow
  9. Hook-first copy — Slide 1 exists to stop the scroll, not to introduce the brand
  10. Iterate fast — show preview, fix specific slides, don't rebuild from scratch
  1. 每张幻灯片均可直接导出 —— 箭头和进度条是幻灯片图片的一部分
  2. 明暗交替 —— 在滑动过程中形成视觉节奏
  3. 标题+正文字体搭配 —— 展示字体增强冲击力,正文字体保证可读性
  4. 品牌衍生配色 —— 所有颜色源自单一主色调,保持整体一致性
  5. 渐进式信息披露 —— 进度条填充和箭头引导用户前进
  6. 最后一张幻灯片特殊处理 —— 无箭头,进度条满格,清晰的CTA
  7. 组件一致性 —— 所有幻灯片使用相同的标签样式、列表样式和间距
  8. 内容避开UI元素 —— 正文永远不覆盖进度条或箭头
  9. 钩子优先文案 —— 幻灯片1的目的是抓住用户注意力,而非介绍品牌
  10. 快速迭代 —— 展示预览,修改特定幻灯片,无需从头重建