marcolang/marketing-skills/instagram-carousel

Claude Code and agent skill by marcolang/marketing-skills

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

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 create, design, or generate an Instagram carousel, carrossel, slides para Instagram, or any Instagram multi-image post — even if they don't explicitly say "carousel" or "skill". Also trigger for req…

Install

npx vskill@latest install marcolang/marketing-skills/instagram-carousel

SKILL.md

The same SKILL.md was published earlier as neversight/learn-skills.dev/instagram-carousel.

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
bash
# 1. Check the actual file format (extension may lie)
file /path/to/image.png
python
import base64
from pathlib import Path
# 2. Read and encode
img_path = Path("/path/to/image.png")
# Use "image/jpeg" if `file` command says JPEG, else "image/png"
mime = "image/jpeg" # or "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
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")
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.

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 base64Browser 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 stringAlways use Python Path.write_text()
Assuming .png extension = PNG formatFile may actually be JPEG; wrong MIME type breaks renderingRun 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:

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%)

Step 3: Set Up Typography

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.


Slide 1 — Hook Rules

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

Slide Sequences

Standard (7 slides — default)
#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.
Listicle (5–10 slides)
#TypeBackground
1HeroLIGHT_BG
2–NItem NAlternating LIGHT/DARK
LastCTABrand gradient

Use for: "X ferramentas", "X erros", "X dicas"

Tutorial (7 slides)
#TypeBackground
1HeroLIGHT_BG
2Contexto / Por quêDARK_BG
3–5Passo 1, 2, 3Alternating
6Resultado esperadoDARK_BG
7CTABrand gradient
Comparação (5 slides)
#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

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
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.

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
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>
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>
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>

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
68
Repository forks
25
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/marcolang/marketing-skills/instagram-carousel/badge)](https://verified-skill.com/skills/marcolang/marketing-skills/instagram-carousel)

Something wrong with this skill or its page? Tell us.