ktg-plugin-marketplace/plugins/linkedin-studio/commands/carousel.md
Kjell Tore Guttormsen 8c52bdb2e4 fix(linkedin-studio): S15 — UX finish §6c (B1 onboarding inline-draft + B3 carousel full-deck clipboard)
B2 (router tiering) was already delivered in S14, so S15 = B1 + B3 only.
No surface/count/version change -> within-v4.1.0 refinement (S11-S13 precedent).

- B1 (commands/onboarding.md): replace the "Run /linkedin:first-post" dead-end
  hand-off in Phase 3 with the first-post drafting steps embedded inline (3.1 topic
  -> 3.2 3-line draft -> 3.3 QC -> 3.4 present+clipboard -> 3.5 state-update that sets
  first_post_date). Wizard now yields a draft in-flow; 0 dead-end strings. Stays within
  the existing allowed-tools (Read/Bash/AskUserQuestion); UI-brief §12b scope-guard
  honored (no provider seams / progressive-disclosure added).
- B3 (commands/carousel.md): Step 6 now assembles the ENTIRE deck (every slide's copy
  + the caption) into the clipboard payload, not just the caption; full-deck assembly
  precedes the clipboard-helper.mjs call.

Independent /trekreview (2 Opus reviewers): brief-conformance 0 findings; code-correctness
1 MAJOR that is PRE-EXISTING and out of S15 scope (onboarding Phase 2 saves need Write in
allowed-tools; lines 142/157, untouched by the S15 diff) -> DEFERRED to next session per
"ekte design-funn -> neste sesjon". Verdict ALLOW for the delivered scope (not a WARN-override).

Gate: test-runner.sh 74/0/0; node --test 98/98; commands=29; v4.1.0 unchanged.
See docs/remediation/review.md for the full record (ALLOW + 1 deferred MAJOR).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:44:34 +02:00

233 lines
9.4 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/documents are the top-performing organic format 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
- Task
---
<!-- 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-studio.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/documents are the top-performing organic format (~7%; see `references/algorithm-signals-reference.md`).
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.
### De-AI / Differentiation Gate
The caption is the feed text, and it rides the same low-substance down-rank LinkedIn confirmed. Confirm the caption and cover slide carry the signals LinkedIn named — **personal substance, original thinking, concrete specifics, genuine voice** — and use no mechanical-response engagement bait ("Comment YES", "Like for Part 2"); a genuine question is fine. (The voice-guardian hook scores the caption on save.)
If the deck's premise is a list the audience has seen many times — commodity content — delegate an originality pass to the `differentiation-checker` agent: invoke it via `Task` with `subagent_type: linkedin-studio:differentiation-checker` (foreground, from this command layer), then sharpen the angle before generating slides.
## 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.
```
**Assemble the entire deck** — every slide's copy (header + body, plus its visual note) followed by the caption — into ONE clipboard payload, so the whole carousel travels in a single copy, not just the caption. A carousel's deliverable is the slide text you paste into your design tool *and* the caption; copying only the caption left the bulk of the work uncopied. Build the payload like this:
```
SLIDE 1 of [TOTAL] — [purpose]
[HEADER]
[BODY line 1]
[BODY line 2]
...
Visual: [visual note]
SLIDE 2 of [TOTAL] — [purpose]
...
— — —
CAPTION
[caption text]
```
Then auto-copy the full deck to clipboard silently:
```bash
printf '%s' '<FULL_DECK_PAYLOAD>' | node ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/clipboard-helper.mjs
```
Substitute `<FULL_DECK_PAYLOAD>` with the assembled deck above — all slides' copy + the caption. Then confirm: "Full deck — [N] slides + 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."