skills/web-design/carousel-designer/SKILL.md
Design and produce high-engagement social media carousels as self-contained HTML, rendered to PDF + PNGs via Playwright. Use when asked to build, generate, design, or iterate on a carousel, social media slides, Instagram carousel, LinkedIn carousel, slide deck, swipe post, or branded content slides. Supports Instagram, LinkedIn, Twitter/X, and Stories. Supports three modes: SHOWCASE (AI art / prompt shares), EDUCATE (tutorials, how-tos, listicles), and THINK (thought leadership / raw ideas). Also use for comparison carousels (tool-vs-tool, before-vs-after, model-vs-model) where each compared output should get its own full-width slide rather than a cramped split layout.
npx skillsauth add michailbul/laniameda-skills carousel-designerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Generate publish-ready social media carousels as a single self-contained HTML file. Export to PDF + PNGs via Playwright.
<project>/
src/slides.html <- single file, all slides
dist/carousel.pdf
dist/slides/01.png ... NN.png
package.json <- { "type": "module", "dependencies": { "playwright": "^1.52" } }
Before designing anything, extract from the user's message:
| Field | Default | |-------|---------| | Topic | (required) | | Key points | Extract or infer from topic | | CTA | "Save + follow" | | Tone | brand-system-aligned | | Platform | Instagram + LinkedIn (1080x1350) | | Mode | EDUCATE | | Slide count | 7 (min 5, max 10) | | Carousel type | Educational | | Brand system | Use the active brand guidelines when available | | Comparison format | If comparing outputs, default to one output per slide (full-width), not side-by-side unless the user explicitly asks for a split |
If topic is unclear, ask one question only: "What's the main idea you want to get across?"
| Platform | Dimensions | Max Slides | Aspect Ratio | |----------|-----------|------------|--------------| | Instagram | 1080x1350px | 20 | 4:5 | | LinkedIn | 1080x1350px | 20 | 4:5 | | Twitter/X | 1080x1080px | 4 | 1:1 | | Story | 1080x1920px | 7 | 9:16 |
Default to 1080x1350 (4:5) unless X-only or Story is explicitly requested. 4:5 takes more feed real estate than square.
The image IS the content. The design system provides a premium dark frame.
assets/styles/mode-showcase.cssassets/templates/showcase-template.html.showcase-frame, .showcase-prompt, .showcase-param-tag, .showcase-model-badgeStructured content with clear hierarchy and progressive disclosure.
assets/styles/mode-educate.cssassets/templates/educate-template.html.step-number, .edu-card, .edu-list, .edu-callout, .edu-progressPure text, maximum negative space, dramatic typography.
assets/styles/mode-think.cssassets/templates/think-template.html.think-hero, .think-body-lg, .think-accent, .think-gradient, .think-counterreferences/REFERENCES.md -- extract layout patterns, type choices, color moments, spacing ratios from listed references. Note which patterns apply to each slide type.references/layout-rules.md -- internalize all 12 rules. These override any general instincts about layout.references/design-standards.md -- lock in the typography scale + quality checklist.assets/linkedin-base.html -- use as skeleton (fonts, tokens, grid/grain, slide counter all pre-wired). Read assets/components/primitives.html -- copy-paste the right building block per slide.assets/styles/carousel-base.css first, then the mode-specific CSS. Use the corresponding template from assets/templates/ as a starting point.src/slides.html:
npm install then node scripts/render.mjsRENDER_COMPLETE: dist/carousel.pdf + dist/slides/01-NN.pngslide_1.headline: clips right edge -- reduce font-size 148px -> 120px
slide_3.metric-card: missing shadow
slide_7.closing: no CTA keyword -- add "Comment THROUGHPUT and I'll send it"
Every carousel maps to four functional zones. No exceptions.
| Position | Role | Job | |----------|------|-----| | Slide 1 | THE HOOK | Stop the scroll. Bold, visual, provocative. Biggest text. | | Slide 2 | THE TRANSITION | What will the user gain / what will the user avoid / what makes you qualified | | Slides 3–N-1 | THE TEASE | Reveal info bit by bit. Examples, statistics, captivating visuals. Keep swiping. | | Last slide | THE ACTION | Make the next step obvious. One clear CTA. |
Typography minimums at carousel scale (1080x1350):
# Send PDF
message(send, filePath: $PROJECT/dist/carousel.pdf)
# Send cover preview
message(send, filePath: $PROJECT/dist/slides/01.png,
caption: "Carousel ready. N slides. Reply with any tweaks.")
If Michael asks to schedule or post, use the Publora REST API.
Prerequisite: Publora API key must be in env as PUBLORA_API_KEY. Account must be on Pro plan ($2.99/mo/account).
1. List connected accounts (find the LinkedIn platform ID):
curl -s https://api.publora.com/api/v1/platform-connections \
-H "x-publora-key: $PUBLORA_API_KEY" | jq '.connections'
# Returns: [{platformId: "linkedin-ABC123", username: "...", displayName: "..."}]
2. Schedule the carousel:
Publora accepts LinkedIn carousels as a PDF document upload. Use the presigned upload URL flow.
# Step 1: get presigned S3 upload URL
curl -s -X POST https://api.publora.com/api/v1/get-upload-url \
-H "Content-Type: application/json" \
-H "x-publora-key: $PUBLORA_API_KEY" \
-d '{"filename": "carousel.pdf", "contentType": "application/pdf"}'
# Returns: { uploadUrl, fileKey }
# Step 2: upload PDF to S3
curl -s -X PUT "$UPLOAD_URL" \
-H "Content-Type: application/pdf" \
--data-binary @$PROJECT/dist/carousel.pdf
# Step 3: create post with fileKey
curl -s -X POST https://api.publora.com/api/v1/create-post \
-H "Content-Type: application/json" \
-H "x-publora-key: $PUBLORA_API_KEY" \
-d "{
\"content\": \"$POST_CAPTION\",
\"platforms\": [\"$LINKEDIN_PLATFORM_ID\"],
\"scheduledTime\": \"$ISO_DATETIME\",
\"mediaKey\": \"$FILE_KEY\"
}"
When to use Publora vs. manual delivery:
| # | Type | Components to use | |---|------|-------------------| | 1 | Cover | kicker, hero-headline, subtitle, badge-row | | 2 | Problem | kicker, section-headline, subtitle | | 3 | Stat / Math | kicker, section-headline, metric-card OR equation-block | | 4 | Stat / Math | kicker, section-headline, metric-card OR equation-block | | 5 | System | kicker, section-headline, checklist | | 6 | Solution | kicker, section-headline, stack-grid | | 7 | CTA | kicker, section-headline, ordered-list, closing-line |
Use these as building blocks for any carousel type:
Slide 1: Bold claim hook
Slide 2: Why this matters (context)
Slides 3-6: One tip each, numbered
Slide 7: CTA (save + follow)
Slide 1: Outcome hook ("How I went from X to Y")
Slide 2: The starting situation
Slide 3: The challenge / pain
Slide 4: What we tried (failed)
Slide 5: What actually worked
Slide 6: The result (numbers/proof)
Slide 7: Key takeaway + CTA
Slide 1: Transformation hook
Slide 2: The "before" state (problem framed)
Slide 3: Problem 1 -- what made it broken
Slide 4: The "after" state
Slide 5: What changed + why it worked
Slide 6: Result proof
Slide 7: Offer to help / CTA
Slide 1: Hook — what is being compared and why it matters
Slide 2: Comparison item 1 — output A (full-width)
Slide 3: Comparison item 1 — output B (full-width)
Slide 4: Comparison item 2 — output A
Slide 5: Comparison item 2 — output B
...
Final slide: Exact value-exchange CTA
Rules:
Slide 1: Number hook ("7 tools that changed how I create")
Slide 2: Context -- why tools matter / what was missing
Slides 3-6: 1-2 tools per slide, name + one-liner use case
Slide 7: Save + follow CTA
Educational (5-8 slides): Hook -> Context -> Content -> Content -> Content -> Stats -> CTA Storytelling (6-8 slides): Hook -> Context -> Content -> Content -> Quote -> Content -> CTA Listicle (5-10 slides): Hook -> Content -> Content -> Content -> Content -> ... -> CTA Comparison (5-7 slides): Hook -> Before/After -> Content -> Content -> Stats -> CTA Single Concept Deep Dive (4-6 slides): Hook -> Context -> Content -> Content -> CTA
The most important slide. If this fails, nobody swipes.
| Type | Formula | Example | |------|---------|---------| | Bold claim | "[X]% of [audience] [painful truth]" | "90% of content strategies skip this" | | Question | "Why does [common thing] [not work]?" | "Why does posting daily still not grow you?" | | Number + promise | "[N] [things] you [outcome verb]" | "5 tools that replaced my whole production team" | | Contrarian | "Stop doing [popular thing]. Do [this]." | "Stop making content. Build a content engine." | | Before/After | State the transformation in one line | "I went from 3 posts/month to 30 posts/week -- same effort" |
| Principle | How to apply | |-----------|-------------| | Curiosity gap | Hook promises value that requires swiping to unlock | | Numbered progress | Show "3/7" or progress dots to create completion drive | | Visual continuity | Consistent design signals "there's more" | | Increasing value | Best insight last -- rewards completing the whole carousel | | Swipe cue | Arrow or "Swipe ->" text on slide 1 |
| Mood | Background | Accent | Body text |
|------|-----------|--------|-----------|
| Obsidian editorial | #0A0805 | #F26157 (coral) | rgba(240,235,232,0.60+) |
| Carbon system | #191919 | #F26157 / #79B791 | rgba(240,235,232,0.60+) |
| Graphite utility | #3A3A3A | #F26157 | rgba(240,235,232,0.60+) |
| Linen light | #FFF4EA | #F26157 | #1A1008 |
| Amber signal | #E8A838 | #1A1008 / #F26157 | #1A1008 |
Validated rejects for carousel backgrounds:
#3D2E42 / purple-adjacent Charcoal Violet#4A5E7A / blue-grey Slate Blue#000000#FFFFFFDefault to the brand-system palette above unless the user explicitly asks for a different visual language.
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
Display: Bebas Neue. Body: Space Grotesk. Mono: JetBrains Mono. Never use Arial/Inter/Roboto as display.
Font stack: Space Grotesk (headlines) + Inter (body) + JetBrains Mono (code/labels). Loaded via carousel-base.css.
<script> block)tailwind.config = {
theme: { extend: {
colors: { primary:'#8566AF', secondary:'#BA943B', accent:'#EA3F2C', 'accent-alt':'#FF552E', brand:'#09090B' },
fontFamily: {
display: ['"Bebas Neue"', 'Impact', 'sans-serif'],
body: ['"Space Grotesk"', '"Helvetica Neue"', 'sans-serif'],
mono: ['"JetBrains Mono"', '"SF Mono"', 'monospace'],
},
}},
}
These apply to all carousels unless Michael explicitly overrides:
Creative brands and creative studios. Not engineers. Not enterprise buyers. People who think in campaigns, content calendars, and creative output -- not runtimes.
For OpenClaw architecture / agent infrastructure topics, technical framing is acceptable and intentional. The audience there is technical-curious builders, not default creative brand audience.
slide, id slide-0N, fixed dimensions via CSS::before, grain via ::after. chrome div: position:relative; z-index:1; padding:78px 76px; display:flex; flex-direction:column. Slide counter "0N / 07" on every slide..slide is 1080x1350 with grid background and vignette built in. .safe-zone has 80px inset with 48px bottom padding for footer. .slide-footer with handle + progress dots on every slide.RENDER_COMPLETE only after PDF + all PNGs verified to exist| Mistake | Fix | |---------|-----| | Weak hook (slide 1) | Bold claim, question, or number + promise | | Too much text per slide | Max 30-40 words, hard limit | | No visual consistency | Same colors, fonts, margins throughout | | No swipe indicator on slide 1 | Add "Swipe ->" or arrow | | No CTA on last slide | Ask to save, follow, share, or comment | | Cramming 2+ ideas per slide | One point per slide, always | | Square format on Instagram | Default to 1080x1350 (4:5) | | Leading with technical language | Lead with outcome; audience is creative brands | | Center-aligned body text | Left-align everything (see layout-rules.md rule 1) |
| File | What it contains | When to use |
|------|-----------------|-------------|
| references/REFERENCES.md | Design inspiration + brand DNA | Extract layout/type/color patterns before designing |
| references/layout-rules.md | 12 explicit design rules | Alignment, scale contrast, spacing, card style, narrative arc |
| references/design-standards.md | Typography scale, color rules, quality checklist | Type sizes, color assignments, QA after render |
| references/brief-template.md | Brief template for structured requests | Fill before building when topic needs structuring |
| references/quality-checklist.md | Per-slide visual review checklist | Run on every PNG set before approving |
| File | What it contains |
|------|-----------------|
| assets/linkedin-base.html | Brutalist skeleton: fonts, Tailwind config, grid/grain, slide counter |
| assets/components/primitives.html | All brutalist primitives: kicker, headlines, metric-card, equation, terminal, checklist, stack-grid, badge-row, closing-line |
| assets/brand-tokens.js | Tailwind color + font config |
| assets/styles/carousel-base.css | Dark Tech design tokens + shared components (ALWAYS load for modes) |
| assets/styles/mode-showcase.css | Showcase-specific styles |
| assets/styles/mode-educate.css | Educate-specific styles |
| assets/styles/mode-think.css | Think-specific styles |
| assets/templates/showcase-template.html | 3-slide showcase starter (image hook, prompt detail, CTA) |
| assets/templates/educate-template.html | 5-slide educate starter (hook, step, list, stats, CTA) |
| assets/templates/think-template.html | 3-slide think starter (statement, emphasis, CTA) |
| scripts/render.mjs | Playwright render -> PDF + PNGs (copy to project root) |
LinkedIn carousel (brutalist, default):
/carousel-designer 5 ways to increase throughput
Instagram educate mode:
/carousel-designer educate: how to use Claude Code skills, 7 slides, platform:instagram
Showcase mode (AI art):
/carousel-designer showcase: my latest Midjourney garden scene
Think mode (thought leadership):
/carousel-designer think: taste is the last moat in AI
With specific slide count:
/carousel-designer 10 tools every designer needs, 10 slides
Twitter/X format:
/carousel-designer 3 things about X, platform:x
development
Seedance 2.0 video prompt director. Converts plain-text scene descriptions into production-ready bilingual EN+ZH video prompts optimized for the Seedance 2.0 video generator. Handles all Seedance work — action (combat, pursuit, stunts), general (landscapes, journeys, atmosphere), dialogue (confrontations, negotiations, interrogations), and non-narrative commercial work (ad spots, music videos, fashion films, automotive inserts, product shots, pet/character demos, cutaway montages, social reels for TikTok / Reels / YouTube Shorts). Use whenever the user wants to create a Seedance video prompt, mentions Seedance, or describes a cinematic scene for video generation. For NARRATIVE screenplay-integrated work, use seedance-screenwriter instead.
development
Write Seedance 2.0 prompts in screenplay format for narrative storytelling — when the prompts will be cut into a film, short, or scene. Use whenever you're generating shots that will be edited into a continuous story with dialogue, character beats, scene continuity, or coverage. Pairs with the screenwriter skill — read the scene's screenplay first (or the project's `scene.md` if it exists), then translate each shot into a Seedance prompt that reads as a screenplay page, not as an engineering spec.
documentation
Скилл-инструмент для сценариста полнометражного фильма или сериала. Используй всегда, когда пользователь хочет писать сценарий, поэпизодник, разрабатывать сцены, бит-шит, диалоги, делать ревизии, считать экранное время, резать длину, работать с персонажами или мифологией истории. Скилл работает на основе методологий Макки, Кэмпбелла и Аристотеля, выдаёт Hollywood-формат .docx, поддерживает билингвальные сценарии (диалог на одном языке + перевод в скобках под ним), и помогает аудитировать структуру по причинности и движению ценности. Скилл не привязан к конкретной истории — пользователь приносит свою.
development
Extract shot composition DNA from any car photograph into structured JSON — camera angle, lens, framing, lighting — stripped of car-specific details. Then reuse extracted angles with any car identity to generate new images at scale. Use when: extracting angles from reference photos, building a shot library, batch-analyzing car photography, replicating a great angle with a different car, running extraction pipelines in Freepik or Flora. Triggers: "extract this angle", "steal this composition", "shot DNA", "analyze this car photo", "replicate this shot with my car", "batch extract angles", "car photography analysis", "angle extraction", "build a shot library".