# Carousel Builder

> Turn a topic or research brief into an N-slide Instagram / LinkedIn / TikTok carousel with consistent visual style and ready-to-post captions. Modes: --topic / --research; --slides 3-12; --platform; --aspect; --text-mode. Use when: 'make a carousel about X', 'turn this research into a post', '8 slides on Y', 'carousel for LinkedIn'.

- **Type:** Skill
- **Install:** `agentstack add skill-mikefluff-skills-carousel-builder`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Mikefluff](https://agentstack.voostack.com/s/mikefluff)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Mikefluff](https://github.com/Mikefluff)
- **Source:** https://github.com/Mikefluff/skills/tree/main/skills/carousel-builder
- **Website:** https://www.npmjs.com/package/@mikefluff/skills

## Install

```sh
agentstack add skill-mikefluff-skills-carousel-builder
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

End-to-end carousel generator. Input: topic OR research brief. Output: N image files with consistent visual style + per-slide caption + final post copy + manifest for --resume.

This skill orchestrates four lower-level skills:
1. `essay-write` or `viral-text` → drafts the content
2. `image-prompt` style anchor + per-slide prompts
3. `common/runners` execute layer → batch generation via the chosen provider
4. `common/style-library/carousel/` → style anchor (24 bundled styles + user overrides)

Use when the user wants a finished carousel, not just prompts. Without `--execute`, returns the 8 prompts + captions for manual paste; with `--execute`, generates and saves the actual PNG slides.

This skill does NOT:
- Compose the slides into a single tall image — Instagram / LinkedIn handle multi-image posts natively.
- Add text overlays via a design tool — text either gets generated INSIDE the image (gpt-image-2 / Ideogram / Imagen) via `--text-mode embedded`, or is left to the user's editor (`--text-mode overlay`).
- Generate animated carousels (those are reels — use `reel-builder`).
- Post to platforms — that is `post-publisher`, which takes this skill's output directory as its input.

## ROLE

Topic / research → split content into N slides → pick style + model → assemble 8 per-slide prompts (style anchor + slide content + composition hint) → batch execute via image provider (one provider for all slides for consistency) → write slides + captions + manifest → print final paths.

## PIPELINE (v2.14.0+ — promptCarousel chain, mirrors `figma/app/lib/carousel/promptCarousel/`)

1. **Resolve input** — topic OR research brief OR finished post text:
   - `--research `: read the brief, extract TL;DR / key facts / suggested angles as the topic.
   - `--content-file `: user-supplied finished post text. PRESERVE the author's voice — direct quotes + cuts only, no paraphrasing. If the text contains `==word==` accent markers, those words become accent-color callouts on the relevant slides.
   - `--topic ""`: short topic string. Optionally invoke `viral-text` (IG/TikTok) or `essay-write` (LinkedIn) first to produce ~150-220 word post text with `==accents==` if the topic is rich enough to benefit. For pure promo decks (course invitation / product launch), topic-only is sufficient.

2. **Resolve style** — see [`common/visual-prompt-library/styles/_index.md`](../../common/visual-prompt-library/styles/_index.md):
   - `--style `: explicit style from the 13-name library (`BIOTECH`, `CYBER-NOIR`, `BRUTALIST`, `VAPORWAVE`, `MILITARY`, `SCIENTIFIC`, `STREETWEAR`, `ART-DECO`, `BLUEPRINT`, `GRUNGE`, `GLAMOUR`, `NATURE`, `ADVENTURE`). The library entry's full description is passed verbatim into the LLM user message.
   - `--style custom`: user provides a `customStyle` description as a free-text override. Passed verbatim.
   - `--style auto` (default): LLM auto-picks based on topic / tone / audience / goal — see the matrix at the bottom of `style-library.md`.
   - `--style-ref `: optional style reference image. Image-side multi-ref + the text style instruction.
   - `--character-ref `: optional character reference photo. The LLM is instructed NOT to describe face/build (the image-side reference handles identity); it describes pose/action/position only.
   - `--brand-colors ""`: optional named colors that MUST be the dominant palette in every slide.

3. **Pick model** — see [`references/model-picker.md`](references/model-picker.md):
   - `--model auto` (default): nano-banana-pro (text-in-image leader + multi-ref). Alternatives: gpt-image-2 (16 refs, top text rendering), Ideogram 3 Quality (text-heavy posters), Flux 2 Pro (photo-real).
   - One model for all slides — mixing models breaks consistency.

4. **Compose ONE LLM call** — load [`common/visual-prompt-library/system-prompt.md`](../../common/visual-prompt-library/system-prompt.md) (the SYSTEM_PROMPT) and `buildUserMessage(opts)` filled with the resolved inputs. Spawn ONE Agent (subagent_type=`general-purpose`) with `system=SYSTEM_PROMPT` and `user=`. The agent returns JSON `{"slides":[{"number":1,"prompt":"..."},...]}` — N short (1–3 sentence) image prompts, text-in-quotes, layout language, carousel chrome (page indicator + swipe/end marker) appended to each.

   **Discipline (all enforced in the SYSTEM_PROMPT — do NOT bypass)**:
   - ONE LLM call, not per-slide subagents (per-slide breaks visual consistency).
   - Each prompt 1–3 sentences. No 250-word spec-dumps with "12% frame height" / "1px stroke" — those produce magazine-with-overlay slop.
   - Text-to-render in double quotes exactly.
   - No meta-labels in the prompt body (no literal `HEADLINE:` / `SUBTITLE:` / `FRAMEWORK:` — they render as visible text on the image).
   - Infographic discipline for middle slides — real numbers / real names / real steps / real cards, never atmospheric vibes + a sentence.
   - Slide 1 = hook, last slide = CTA (full CTA phrase verbatim, no condensing).
   - Visual consistency across slides — same palette + treatment + character.

   **Retry on bad output**: if the agent returns malformed JSON OR fewer than N slides OR any prompt is missing carousel chrome / has forbidden literals (HEADLINE / hex codes / "Instagram"), re-run the agent ONCE with a stricter reminder appended. After 2 attempts, ship the partial result and warn the user.

5. **Assemble plan.json** — items `[{index, label, prompt, kwargs:{size, image_url}}]`. `prompt` is the LLM-returned text verbatim. `image_url` points to the character ref photo when provided (multi-ref capable provider locks identity). Single canonical path (e.g. `/tmp/plan.json` or `./generated/carousel//plan.json`) — overwrite each run, don't proliferate `plan-v1.json` / `plan-v2.json`.

6. **Estimate cost + confirm** — sum per-slide estimates × N slides. If total > $0.10 and not `--yes`, prompt for confirmation. See `common/runners/cost.confirm_batch()`.

7. **Batch execute** — `python3 -m common.runners.cli.carousel --plan-file  --yes`:
   - Parallelism: default 3 (rate-limit safe).
   - Manifest: `./generated/carousel//manifest.json` updated after every slide.
   - `--resume` picks up succeeded slides from the manifest, only retries failures.

8. **Compose captions** — `references/platform-presets.md` defines per-platform caption rules:
   - Instagram: hook (1 sentence) + body (3-5 sentences) + CTA + 15-25 hashtags
   - LinkedIn: longer narrative (300-800 chars), no hashtags spam, end with question CTA
   - TikTok: short post copy + 3-5 hashtags + sound credit if applicable
   Write per-slide caption (1-2 sentences) AND the main post caption. Both saved to `captions.md`.

9. **Output**:
   ```
   ./generated/carousel//
     slide-1.png  ... slide-N.png
     captions.md         # main post + per-slide alts
     manifest.json       # for --resume
     style-used.md       # snapshot of style anchor (for reproducibility)
     prompts.md          # all N per-slide prompts (for inspection / paste fallback)
   ```

   stdout last lines:
   ```
   Carousel: ./generated/carousel//  (N/M slides succeeded)
   Captions: ./generated/carousel//captions.md
   ```

## MODES

### Input

- `carousel-builder --topic ""` — generate content first via essay-write/viral-text, then slides
- `carousel-builder --research ` — ingest a research-brief markdown file
- `carousel-builder --content-file ` — use already-written content (skip step 1)
- `carousel-builder --slide-script-file ` — bring your own pre-split slide content (skip step 2)

### Style

- `--style auto` — pick from library based on topic + tone
- `--style ` — explicit style (see `common/style-library/carousel/_index.md`)
- `--style-ref ` — use user image as ref (requires multi-ref capable model)
- `--style-mod ""` — append a tweak to the chosen style anchor (e.g. "but with cooler color temperature")

### Structure

- `--slides N` — default 8, range 3-12
- `--platform instagram|linkedin|tiktok` — preset for aspect + caption rules (default instagram)
- `--aspect portrait|square|story` — overrides platform default (4:5 / 1:1 / 9:16)
- `--text-mode embedded|overlay|none` — embedded = text inside image (Ideogram/gpt-image-2/Imagen); overlay = no text in image, user adds in Canva; none = no text at all
- `--variants N` — generate N visual variations of each slide (default 1)

### Execution

- `--execute` — actually generate images (requires API key for chosen model)
- `--model auto|` — image provider (default auto-pick)
- `--output ` — custom output dir (default `./generated/carousel//`)
- `--parallelism N` — concurrent API calls (default 3, max 6)
- `--yes` — skip cost confirmation
- `--resume` — pick up from manifest.json after a partial failure

### Animation (chained reel — see "`--animate`" section below)

- `--animate` — after slides render, animate each slide via the video-chain SYSTEM_PROMPT + reel CLI (one command, no manual plan assembly)
- `--animate-duration 4|8` — seconds per shot (default 4)
- `--animate-provider veo-3-1-fast|veo-3-1|kling-3|runway-gen-4` — default veo-3-1-fast
- `--animate-stitch on|off` — ffmpeg-concat into one reel (on, default) or N independent clips (off)

### Inspection / dry-run

- `--prompts-only` — print all per-slide prompts, don't generate (use this to review before spending)
- `--cost-only` — print total estimated cost, exit
- `--check` — validate env vars + style file + research file exist; exit 0 if ready

## REFERENCES (load on demand)

| File | When to load |
|---|---|
| [common/visual-prompt-library/system-prompt.md](../../common/visual-prompt-library/system-prompt.md) | Step 4 — **PRIMARY**: the shared SYSTEM_PROMPT (verbatim) + buildUserMessage shape + retry policy + invocation pattern. Used by all visual-output skills (carousel / cover / flyer / quote / meme / banner / logo). |
| [common/visual-prompt-library/styles/_index.md](../../common/visual-prompt-library/styles/_index.md) | Step 2 — 13 named visual styles + auto-pick matrix. Shared library across all visual skills. |
| [references/slide-roles.md](references/slide-roles.md) | Optional — when briefing the LLM with substantive content per slide (framework boxes / data points / quote attribution), this file documents the 9 role-content contracts. NOT required — the SYSTEM_PROMPT in `common/visual-prompt-library/system-prompt.md` already enforces infographic discipline. |
| [common/style-library/carousel/_universal-rules.md](../../common/style-library/carousel/_universal-rules.md) | Legacy — the rules are now embedded in `common/visual-prompt-library/system-prompt.md` SYSTEM_PROMPT. Keep this file for back-compat link checks but prefer the system-prompt reference. |
| [references/slide-split.md](references/slide-split.md) | Legacy — replaced by the SYSTEM_PROMPT's infographic vocabulary section. |
| [references/style-resolution.md](references/style-resolution.md) | Legacy — replaced by `style-library.md` (which includes auto-pick matrix). |
| [references/model-picker.md](references/model-picker.md) | Step 3 — model auto-pick decision tree, capability matrix |
| [references/platform-presets.md](references/platform-presets.md) | Step 8 — caption rules per platform, hashtag policy, char limits |
| [references/batch-execute.md](references/batch-execute.md) | Step 6-7 — how batch runner works, manifest format, retry semantics, failure handling |
| [references/troubleshoot.md](references/troubleshoot.md) | When generation fails or style drifts across slides |

## EXAMPLES

See [examples/before-after.md](examples/before-after.md) — 3 calibration runs: 8-slide LinkedIn carousel from a research brief (Flux 2 Pro), 6-slide Instagram with embedded text (Ideogram 3 Quality), 10-slide TikTok with user-provided reference image (Nano Banana Pro).

## `--animate` — one-command carousel → animated reel (v2.19.0+)

With `--animate`, the skill continues past the static deck into a stitched animated reel WITHOUT any manual plan-file assembly:

1. **Slides render first** (steps above) → N slide PNGs + the slide-content summaries already in hand.

2. **Spawn ONE Agent with the canonical video SYSTEM_PROMPT** at [`../common/video-prompt-library/system-prompt.md`](../../common/video-prompt-library/system-prompt.md). Fill `buildUserMessage(opts)` with:
   - Mode `i2v`, N shots, aspect `9:16`, 4s per shot, target model (default `veo-3-1-fast`).
   - Per shot: the slide PNG path as `image_url` + a one-line summary of the slide's overlay text (so the LLM can pick a motion that fits the slide's rhetoric — it must NOT re-describe the text in the output prompt).
   - The character-identity marker (8–15 words) when a character ref was used.
   - Suggested micro-gesture variety across the deck (head turn / hand lift / finger tap / nod / blink — one distinct verb per shot).
   The Agent returns `{"shots":[{"index":N,"prompt":"...","kwargs":{...}}]}` — all N shots in ONE call. The SYSTEM_PROMPT enforces the full i2v discipline (2-sentence cap, 80-word cap, single motion verb, global lock verbatim, `lock_first_last` + `negative_prompt` kwargs for overlay-heavy frames, no punitive labels, subject-anchored contact motion).

3. **Build the reel plan mechanically** — each returned shot becomes a `skills.reel.plan.v1` item (label `shot-NN-`; labels MUST start with `shot-` or the reel CLI skips them). Write to `/reel-plan.json` (single canonical path, overwrite).

4. **Run the reel CLI**:
   ```
   python3 -m common.runners.cli.reel --plan-file /reel-plan.json --yes            # stitched final.mp4
   python3 -m common.runners.cli.reel --plan-file /reel-plan.json --yes --skip-stitch  # N independent clips (IG carousel-as-reels)
   ```
   Concat order follows plan index (fixed v2.18.0) — parallel finish order can't scramble the sequence.

5. **Verify against the source slides** — spot-check first frames of each shot mp4 against the slide PNGs (index ↔ content match). If a shot fails on Veo's safety filter (`no videos`), soften the PROMPT body per SYSTEM_PROMPT rule 10 and `--resume`.

Flags: `--animate` (off by default) · `--animate-duration 4|8` (default 4) · `--animate-provider veo-3-1-fast|veo-3-1|kling-3|runway-gen-4` (default veo-3-1-fast; pick non-Fast Veo when `last_frame` drift-lock matters more than cost) · `--animate-stitch on|off` (default on).

Cost (Veo 3.1 fast, $0.15/s): 3×4s = $1.80 · 5×4s = $3.00 · 8×4s = $4.80. Veo 3.1 standard ($0.40/s) is ~2.7× — use for publication-grade text stability (`last_frame` supported).

Cost (Kling 3 / Runway Gen-4 / Sora 2) — see `common/runners/cost.py` for per-provider pricing; all four accept `image_url` for image-to-video.

## CONSTRAINTS

- **ONE LLM call, not per-slide.** The carousel-builder SYSTEM_PROMPT is designed to receive all N prompts in a single response. Per-slide subagent calls break visual consistency and miss the "deck as cohesive sequence" framing. Tried and rejected in earlier versions.

- **1–3 sentence prompts only.** Image models perform best with concise prompts. 250+ word spec-dumps with "12% frame height" / "1px stroke" / percentages produce magazine-with-overlay output. The SYSTEM_PROMPT enforces this.

- **Style description = VOCABULARY + treatment, not a fixed recurring scene.** A style entry like "BIOTECH / ORGANIC — deep teal background, neural pathways, cyan glow" describes the visual language. Avoid baking literal scenes like "library reading room at dusk" into the style — every slide will render the same setting.

- **One style anchor across all slides.** Use the SAME provider, SAME style anchor text, SAME aspect ratio for every slide. The only thing that varies per slide is the content prompt + the role-specific composition hint. Mixing breaks the carousel feel.

- **One model for the whole carousel.** Don't mix Flux 2 Pro + Ideogram 3 across slides — even with the same anchor, the model's style fingerprint differs and the carousel loses cohesion.

- **Style library is the source of truth for visual consistency.** Don't write free-form style descriptions inside this skill. If

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Mikefluff](https://github.com/Mikefluff)
- **Source:** [Mikefluff/skills](https://github.com/Mikefluff/skills)
- **License:** MIT
- **Homepage:** https://www.npmjs.com/package/@mikefluff/skills

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-mikefluff-skills-carousel-builder
- Seller: https://agentstack.voostack.com/s/mikefluff
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
