instagram-carousel
Creates high-quality Instagram carousels as swipeable HTML previews with export-ready slides (1080×1350px PNG). Handles the full workflow: brand setup, slide copy, visual design system (colors, fonts, components), HTML generation, and Playwright-based export. Use this skill whenever the user asks to
By marcolang · 699 installs
npx skills add marcolang/marketing-skills --skill instagram-carousel
Source repository · Upstream listing
Instagram Carousel Generator
Generates fully self contained, swipeable HTML carousels where every slide is
designed to be exported as an individual 1080×1350px PNG for Instagram.
Step 1: Collect Brand Details
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.
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 ):
⚠️ 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.
Step by step: embed an image
Image as slide background (most common use)
For dark slides, use rgba(0,0,0,0.45) as the overlay instead.
Common image mistakes to avoid
Mistake What goes wrong Fix
<img src="gestante.png" Broken image — relative path only works if HTML and image share the same folder Always use base64 data: URI
background: url('data:...') inline with 1.5MB base64 Browser parser crash, 1.3M token context Use <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 rendering Run file command to detect actual format
Step 2: Derive the Full Color System
From the user's single primary brand color , generate the full 6 token palette:
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%)
Step 3: Set Up Typography
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 .serif (heading font) and .sans (body font) throughout all slides.
Slide 1 — Hook Rules
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
Slide Sequences
Standard (7 slides — default)
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.
Listicle (5–10 slides)
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"
Tutorial (7 slides)
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
Comparação (5 slides)
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
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
Required Elements on Every Slide
1. Progress Bar (bottom of every slide)
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
⚠️ Important: Always replace BRAND PRIMARY with the actual hex value before rendering. Never leave it as a variable name in the HTML output.
2. Swipe Arrow (right edge — every slide EXCEPT the last)
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
Reusable Components
Strikethrough pills
Tag pills
Prompt / quote box
Feature list
Numbered steps
Color swatches
CTA button (final slide only)
Tag / Category Label
Light slides: BRAND PRIMARY
Dark slides: BRAND LIGHT
Brand gradient slides: rgba(255,255,255,0.6)
Logo Lockup (first and last slides)
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
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
Instagram Frame (Preview Wrapper)
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.
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")
Exporting Slides as Instagram Ready PNGs
After the user approves the carousel preview, export each slide as an individual 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.
Install Playwright (only if needed)
Before running the export script, check and install only if missing:
Export Script
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.
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 device scale factor
Using shell scripts to generate HTML $ signs and backticks get interpolated Always use Python for HTML generation
Not waiting for fonts Headings render in fallback system fonts wait for timeout(3000) after page load
Not hiding IG frame chrome Export includes header, dots, caption Hide .ig header,.ig dots,.ig actions,.ig caption
Changing .ig frame width Entire layout shifts Always keep at exactly 420px
Leaving BRAND PRIMARY as variable name in CSS Color renders as invalid / invisible Always interpolate actual hex values into 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 ba