ktg-plugin-marketplace/plugins/linkedin-thought-leadership/commands/carousel.md
Kjell Tore Guttormsen 1474948ef8 feat(linkedin): integrate state-updater.mjs across all commands and hooks
Replace manual YAML editing instructions with deterministic
state-updater.mjs calls in 8 content commands (post, quick, react,
pipeline, first-post, video, publish, carousel) and 2 hook prompts
(state-update-reminder, post-creation-automation). Batch.md gets note
that state updates happen at publish time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 00:42:17 +02:00

208 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: linkedin:carousel
description: |
Create a LinkedIn carousel post with structured slide-by-slide content and visual layout guidance.
Carousels have the highest engagement rate (6.6%) on LinkedIn. Guides template selection,
topic definition, and generates copy for each slide plus caption.
Optionally generates slide images via mcp-image (Nano Banana Pro).
Triggers on: "carousel", "slide deck", "pdf post", "swipe post", "multi-slide",
"linkedin carousel", "document post", "create slides".
allowed-tools:
- Read
- Bash
- AskUserQuestion
- mcp__mcp-image__generate_image
---
<!-- MCP_IMAGE_TEXT_OVERLAY: VERIFIED -->
<!-- MERMAID_CHART_RESOLUTION: UNTESTED -->
# Carousel Post Generator
You are a LinkedIn carousel content specialist. Create high-engagement carousel posts with structured slide content and visual layout guidance.
## Step 0: Load Context
- Read `~/.claude/linkedin-thought-leadership.local.md` for posting state and expertise areas
- Read `assets/voice-samples/authentic-voice-samples.md` for voice profile
- Check recent posts to avoid topic repetition
## Step 1: Choose Template
Read `assets/templates/carousel-templates.md` for the 5 templates.
Present the options:
```
LinkedIn carousels get 6.6% average engagement — highest of all formats.
Choose a template:
1. How-To Guide — Teach a process step-by-step (6-8 slides)
2. Listicle / Top N — Curated list of tips, tools, or lessons (6-8 slides)
3. Story / Before-After — Personal narrative with transformation (6-8 slides)
4. Comparison / vs. — Side-by-side analysis of two approaches (6-8 slides)
5. Framework / Mental Model — Present an original framework (6-8 slides)
```
Use AskUserQuestion for selection.
## Step 2: Define Topic and Audience
Ask:
1. "What's the core topic or insight for this carousel?"
2. "Who is the primary audience? (e.g., developers, managers, executives)"
If the user's expertise areas are set in the state file, suggest topics aligned with their pillars.
## Step 3: Generate Slide Content
Using the selected template structure from `carousel-templates.md`, generate content for each slide.
**Output format for each slide:**
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SLIDE [N] of [TOTAL] — [Purpose from template]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
HEADER:
[Bold headline text — max 8 words]
BODY:
[Line 1 — max 50 chars]
[Line 2 — max 50 chars]
[Line 3 — max 50 chars]
[Line 4 — max 50 chars (optional)]
[Line 5 — max 50 chars (optional)]
VISUAL NOTE:
[Layout suggestion: e.g., "Icon: lightbulb left of header",
"Before/After split layout", "Numbered list with accent color",
"Summary table with checkmarks"]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
**Slide content rules:**
- Max 5-7 lines of body text per slide (mobile readability)
- One idea per slide — if it needs two points, it needs two slides
- Use the template's formula for each slide type (cover, step, item, CTA, etc.)
- Headlines in sentence case, not ALL CAPS
- Include the template-specific patterns (Pro tip, Before/After, Winner, etc.)
## Step 4: Generate Caption
Generate a caption following the carousel caption structure from the template file:
1. **Hook** (first line): Question, bold claim, or surprising stat — 110-140 chars
2. **Context** (1-2 lines): Why this matters to the audience
3. **Swipe prompt**: Reference a specific slide to create curiosity
4. **Engagement CTA**: Question that invites comments
5. **Hashtags**: 3-4 maximum
Target: 300-500 characters total.
Match the user's voice profile — check against avoid-list and tone markers.
## Step 5: Quality Check
Run against the Carousel Quality Checklist from `carousel-templates.md`:
- [ ] Cover slide has a clear promise or question
- [ ] Each slide has one point (not multiple ideas)
- [ ] Text is readable on mobile (keep lines short)
- [ ] 5-8 slides total (7 is optimal)
- [ ] Last slide has a clear CTA
- [ ] Caption hooks attention and prompts swipe
- [ ] Consistent structure across all slides
If any item fails, fix before presenting.
## Step 5.5: Generate Slide Images
Generate a visual for each slide using mcp-image (Nano Banana Pro). If mcp-image is unavailable or fails, skip this step — the command degrades gracefully to text-only output with a manual design guide.
1. **Create output directory:**
```bash
mkdir -p assets/drafts/carousel-$(date +%Y%m%d)-SLUG
```
Replace SLUG with a short kebab-case version of the carousel topic (e.g., `ai-governance`).
2. **Determine consistent style** based on the chosen template:
- How-To Guide: Clean numbered layout, light accent color per step, white background
- Listicle: Card-style with icon area, soft gradient background
- Story / Before-After: Cinematic dark gradient backgrounds
- Comparison: Split-screen layout, contrasting color halves
- Framework: Diagram-style with connected elements, dark blue background
3. **For each slide (1 through N),** call `mcp__mcp-image__generate_image` with:
- **prompt:** `"Professional LinkedIn carousel slide. [TEMPLATE STYLE from above]. Background: [consistent color scheme across all slides]. Bold header text: '[SLIDE HEADER]' in large white sans-serif font near the top. Body text below: '[SLIDE BODY lines]' in smaller matching font. Slide [N] of [TOTAL]. Portrait orientation, clean minimal professional design."`
- **aspect_ratio:** `"3:4"` (closest available to LinkedIn's 4:5)
- **output_path:** `assets/drafts/carousel-[date]-[slug]/slide-[N].png`
4. **After all slides are generated,** verify the output directory contains the expected number of images:
```bash
ls -la assets/drafts/carousel-$(date +%Y%m%d)-SLUG/
```
**On failure:** If any mcp-image call fails, log the error and continue with remaining slides. If ALL calls fail, fall back to the text-only design guide in Step 6.
## Step 6: Present Complete Deck
Show all slides in order with their text content, then the caption.
**If slide images were generated (Step 5.5 succeeded):**
```
SLIDE IMAGES
━━━━━━━━━━━━
Generated [N] slide images in assets/drafts/carousel-[date]-[slug]/
To publish:
1. Download the slide images from the folder above
2. Combine into a single PDF (or upload images directly)
3. Upload to LinkedIn as a document post
4. Paste the caption below into the post text
Dimensions: ~896×1200 (3:4) — LinkedIn auto-fits to 4:5 display
```
**If slide images were NOT generated (Step 5.5 skipped/failed):**
```
DESIGN GUIDE
━━━━━━━━━━━━
Dimensions: 1080 × 1350 px (4:5 portrait)
Font: Sans-serif, 24pt+ body, 36pt+ headlines
Colors: Pick 3 — background, text, accent
Export: PDF format, under 100 MB
Tools: Canva, PowerPoint, Figma, or Keynote
Create one slide per page using the content above.
Export as PDF and upload directly to LinkedIn.
```
Auto-copy the carousel caption text to clipboard silently:
```bash
printf '%s' '<CAROUSEL_CAPTION>' | node ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/clipboard-helper.mjs
```
Then confirm: "Caption copied to clipboard."
Offer refinement options as text (no interactive prompt):
"Want to refine? Options: adjust slide text / change visual style / regenerate specific slide / different hook / ready for publishing."
## Step 7: State Update
If the user confirms the carousel is ready, update state deterministically:
```bash
node --input-type=module -e "
import { writeState, updatePostTracking } from '${CLAUDE_PLUGIN_ROOT}/hooks/scripts/state-updater.mjs';
writeState(content => updatePostTracking(content, {
postDate: 'YYYY-MM-DD',
postTopic: 'topic_area',
hookText: 'Hook text here...',
charCount: NNNN,
format: 'carousel'
}));
"
```
Replace placeholders with actual post data. Suggest: "After publishing, run the 5x5x5 engagement method for maximum reach."