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>
233 lines
9.4 KiB
Markdown
233 lines
9.4 KiB
Markdown
---
|
||
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."
|