New: Earn 20% as an AgentAlley affiliate. Share your link and earn on every sale you refer. Join now New: Earn 20% as an affiliate. Join now

Create LinkedIn carousel posts as high-quality PNG images

LinkedIn Carousel Creator

by gooseworks-ai · MIT license · ★ 1,220 on GitHub · updated Sep 21

LinkedIn Carousel Creator cover

Create LinkedIn carousel posts as high-quality PNG images. Design informational multi-slide posts like "5 AI GTM workflows" with consistent styling, then automatically screenshot each slide at LinkedIn's optimal 1080x1080px format.

---
name: create-html-carousel
description: Create LinkedIn carousel posts as high-quality PNG images. Design informational multi-slide posts like "5 AI GTM workflows" with consistent styling, then automatically screenshot each slide at LinkedIn's optimal 1080x1080px format.
---

> **Deprecated:** This skill is superseded by `goose-graphics`. See `skills/composites/goose-graphics/` (install with `npx goose-skills install goose-graphics`). The carousel format is one of seven formats in the newer skill and supports 36 style presets plus image sourcing and PNG export. This skill is retained for one release cycle before removal.

# LinkedIn Carousel Creator

Create stunning LinkedIn carousel posts as PNG images. This skill generates styled HTML slides optimized for square format (1080×1080px), then automatically screenshots each slide for direct upload to LinkedIn.

## Core Philosophy

1. **LinkedIn-First Design** — Square format (1080×1080px), optimized for mobile feed viewing
2. **Informational Content** — Tips, workflows, lists, frameworks (not presentations)
3. **Consistent Styling** — Reuse proven design systems from frontend-slides
4. **Automated Export** — Generate HTML → Screenshot → PNG files ready for LinkedIn
5. **Viewport Perfect** — Every slide must fit exactly in 1080×1080px without scrolling

Overview

Create stunning LinkedIn carousel posts as PNG images. This skill generates styled HTML slides optimized for square format (1080×1080px), then automatically screenshots each slide for direct upload to LinkedIn.

Manual install (npx, ZIP)
Claude Codenpx skills add gooseworks-ai/goose-skills --skill create-html-carousel -g -a claude-code
Claude Code (manual)mkdir -p ~/.claude/skills && curl -sL https://codeload.github.com/gooseworks-ai/goose-skills/tar.gz/615c685f34f8 \ | tar -xz -C ~/.claude/skills --strip-components=4 goose-skills-615c685f34f8/skills/design/capabilities/create-html-carousel
Windows (PowerShell)New-Item -ItemType Directory -Force "$HOME\.claude\skills" | Out-Null; Invoke-WebRequest "https://m.agentalley.io/zip/477a227eda068cbf0675/create-html-carousel.zip" -OutFile "$env:TEMP\create-html-carousel.zip"; Expand-Archive "$env:TEMP\create-html-carousel.zip" -DestinationPath "$HOME\.claude\skills" -Force
Claude.ai / desktopDownload the ZIP and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md18.2 KB
  • README.md4.0 KB
  • STYLE_PRESETS.md14.6 KB
  • package.json367 B
  • screenshot-slides.js4.1 KB
  • skill.meta.json424 B
Read the files here
gooseworks-ai/615c6856 files
SKILL.md
Show the full text710 lines

Deprecated: This skill is superseded by goose-graphics. See skills/composites/goose-graphics/ (install with npx goose-skills install goose-graphics). The carousel format is one of seven formats in the newer skill and supports 36 style presets plus image sourcing and PNG export. This skill is retained for one release cycle before removal.

Create stunning LinkedIn carousel posts as PNG images. This skill generates styled HTML slides optimized for square format (1080×1080px), then automatically screenshots each slide for direct upload to LinkedIn.

Core Philosophy

  1. LinkedIn-First Design — Square format (1080×1080px), optimized for mobile feed viewing
  2. Informational Content — Tips, workflows, lists, frameworks (not presentations)
  3. Consistent Styling — Reuse proven design systems from frontend-slides
  4. Automated Export — Generate HTML → Screenshot → PNG files ready for LinkedIn
  5. Viewport Perfect — Every slide must fit exactly in 1080×1080px without scrolling

Format: Square (1080×1080px)

  • Aspect ratio: 1:1
  • File format: PNG (recommended) or JPG
  • File size: Under 10MB per image
  • Max slides: 10 images per carousel
  • Ideal slide count: 5-8 slides (best engagement)

Content Structure:

  1. Cover slide — Hook + title + your brand
  2. Content slides — One key point per slide (3-6 slides)
  3. Closing slide — CTA / summary / follow prompt

When to Use This Skill

Use for LinkedIn carousel posts like:

  • "5 AI GTM workflows you should be using"
  • "How to build X: A step-by-step guide"
  • "7 mistakes founders make with Y"
  • "The complete framework for Z"
  • "Before & After: How we 10x'd our metrics"

NOT for:

  • Long-form presentations (use frontend-slides)
  • Video content
  • Single-image posts

Workflow Overview

1. Content Input → User provides topic/outline
2. Style Selection → Choose visual style (or preview options)
3. HTML Generation → Create 1080×1080px HTML slides
4. Screenshot → Auto-capture each slide as PNG
5. Delivery → Folder of PNG files ready for LinkedIn upload

Phase 1: Content Discovery

Step 1.1: Get Topic & Structure

Ask the user:

Question 1: What's the topic?

  • Header: "Topic"
  • Question: "What's the main topic of this carousel?"
  • (Free text input)

Question 2: Content Type

  • Header: "Format"
  • Question: "What type of post is this?"
  • Options:
    • "Numbered list" — "5 ways to...", "7 mistakes...", "3 steps to..."
    • "How-to guide" — Step-by-step tutorial or process
    • "Framework" — Concept explanation with structure
    • "Before/After" — Transformation or case study
    • "Insights/Tips" — Collection of advice or learnings

Question 3: Slide Count

  • Header: "Length"
  • Question: "How many slides?"
  • Options:
    • "Short (5-6)" — Quick, punchy (best for mobile scrolling)
    • "Medium (7-8)" — Standard carousel length
    • "Long (9-10)" — Maximum LinkedIn allows

Question 4: Branding Handle

  • Header: "Brand"
  • Question: "What handle or name should appear on each slide?"
  • (Free text input — e.g., "@yourhandle", "Acme Inc", or leave blank for none)

Question 5: Content Ready?

  • Header: "Content"
  • Question: "Do you have the content written?"
  • Options:
    • "Yes, I have all content" — Paste it in
    • "I have bullet points" — Need light formatting
    • "Just the topic" — Need help outlining

If user has content, ask them to share it.

Content Density Rules for LinkedIn

Each slide should be scannable in 2-3 seconds on mobile:

Slide Type Max Content
Cover Title (1 line) + subtitle (1 line) + branding
List item Number/icon + heading (2 lines max) + body (3 lines max)
Framework Diagram/visual + 2-4 labels
Quote/Stat 1 large stat or quote + context
CTA 1 action + visual element

If content exceeds limits: Break into multiple slides or simplify.


Phase 2: Style Selection

Users can choose styles two ways:

Option A: Direct Selection (Faster)

Show preset picker:

Question: Pick a Style

  • Header: "Style"
  • Question: "Which visual style works best for your content?"
  • Options:
    • "Bold Signal" — High-contrast card on dark, confident
    • "Dark Botanical" — Elegant dark with soft abstract shapes
    • "Notebook Tabs" — Editorial cream paper with colorful tabs
    • "Pastel Geometry" — Friendly pastels with decorative pills
    • "Neon Cyber" — Futuristic tech aesthetic
    • "Split Pastel" — Playful two-tone split design

(See STYLE_PRESETS.md for full details on each style)

Option B: Guided Discovery

If user isn't sure, ask:

Question: Audience & Tone

  • Header: "Vibe"
  • Question: "Who's your audience and what tone?"
  • Options:
    • "Professional/Corporate" → Recommend: Bold Signal, Dark Botanical
    • "Creative/Playful" → Recommend: Split Pastel, Pastel Geometry
    • "Technical/Dev-focused" → Recommend: Neon Cyber, Terminal Green
    • "Elegant/Premium" → Recommend: Dark Botanical, Paper & Ink

Then generate 2-3 preview slides and let user pick.


File Structure

All carousel files (HTML source and PNG exports) are saved to the shared assets directory.

[carousel-name]/
├── index.html              # Full carousel (all slides)
├── slides/
│   ├── slide-01.html       # Individual slide pages
│   ├── slide-02.html
│   └── ...
└── exports/
    ├── slide-01.png        # Screenshots (generated in Phase 4)
    ├── slide-02.png
    └── ...
HTML Architecture for 1080×1080px

CRITICAL: LinkedIn carousel slides are SQUARE (1:1 ratio), not widescreen.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Slide 01</title>

    <!-- Fonts -->
    <link rel="stylesheet" href="https://api.fontshare.com/v2/css?f[]=..." />

    <style>
      /* ===========================================
           LINKEDIN CAROUSEL: SQUARE FORMAT
           Fixed 1080×1080px for screenshot
           =========================================== */
      :root {
        /* Fixed size for LinkedIn */
        --slide-width: 1080px;
        --slide-height: 1080px;

        /* Colors (from chosen preset) */
        --bg-primary: #0a0f1c;
        --text-primary: #ffffff;
        --accent: #00ffcc;

        /* Typography - scaled for square format */
        --title-size: 72px;
        --subtitle-size: 36px;
        --body-size: 28px;
        --small-size: 20px;

        /* Spacing */
        --slide-padding: 80px;
        --content-gap: 40px;

        /* Animation */
        --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
      }

      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }

      html,
      body {
        width: var(--slide-width);
        height: var(--slide-height);
        overflow: hidden;
      }

      body {
        font-family: var(--font-body);
        background: var(--bg-primary);
        color: var(--text-primary);
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        padding: var(--slide-padding);
      }

      /* Content container */
      .slide-content {
        width: 100%;
        max-width: 100%;
        display: flex;
        flex-direction: column;
        gap: var(--content-gap);
      }

      /* Typography hierarchy */
      h1 {
        font-size: var(--title-size);
        font-weight: 800;
        line-height: 1.1;
        margin-bottom: 20px;
      }

      h2 {
        font-size: var(--subtitle-size);
        font-weight: 700;
        line-height: 1.2;
      }

      p,
      li {
        font-size: var(--body-size);
        line-height: 1.4;
      }

      /* List styling */
      ul {
        list-style: none;
      }

      li {
        padding-left: 40px;
        position: relative;
        margin-bottom: 20px;
      }

      li::before {
        content: "→";
        position: absolute;
        left: 0;
        color: var(--accent);
        font-weight: bold;
      }

      /* Number badge (for list items) */
      .number {
        font-size: 120px;
        font-weight: 900;
        color: var(--accent);
        opacity: 0.15;
        position: absolute;
        top: -40px;
        left: -20px;
        z-index: 0;
      }

      /* Branding footer */
      .brand {
        position: absolute;
        bottom: var(--slide-padding);
        right: var(--slide-padding);
        font-size: var(--small-size);
        opacity: 0.7;
      }

      /* ===========================================
           STYLE-SPECIFIC OVERRIDES
           Inject preset styles here
           =========================================== */
      /* ... preset-specific CSS ... */
    </style>
  </head>
  <body>
    <div class="slide-content">
      <!-- Slide content goes here -->
      <h1>Your Title Here</h1>
      <p>Your content here</p>
    </div>

    <div class="brand">@yourbrand</div>
  </body>
</html>
Content Slide Templates

Cover Slide:

<div class="slide-content">
  <h1>5 AI GTM Workflows<br />You Should Be Using</h1>
  <p>Scale your outbound without scaling your team</p>
</div>
<div class="brand">@yourhandle</div>

Numbered Item (e.g., Slide 2/6):

<div class="slide-content">
  <div class="number">01</div>
  <h2>Signal-Based Outbound</h2>
  <p>
    Monitor job postings, funding announcements, and tech stack changes to find
    companies actively solving your problem.
  </p>
</div>
<div class="brand">@yourhandle • 1/5</div>

Framework Slide:

<div class="slide-content">
  <h2>The GTM Engineering Stack</h2>
  <div class="framework-grid">
    <div class="box">Research</div>
    <div class="box">Personalization</div>
    <div class="box">Outreach</div>
    <div class="box">Tracking</div>
  </div>
</div>
<div class="brand">@yourhandle • 3/5</div>

CTA Slide:

<div class="slide-content">
  <h2>Want more like this?</h2>
  <p>Follow me for more tips and workflows.</p>
  <div class="cta">Hit that follow button →</div>
</div>
<div class="brand">@yourhandle</div>

Phase 4: Screenshot Generation

After generating HTML, automatically capture screenshots.

Create a Node.js script to screenshot each slide:

// screenshot-slides.js
const { chromium } = require("playwright");
const path = require("path");
const fs = require("fs");

async function screenshotSlides(slidesDir, outputDir) {
  const browser = await chromium.launch();
  const page = await browser.newPage();

  // Set viewport to LinkedIn carousel size
  await page.setViewportSize({ width: 1080, height: 1080 });

  // Ensure output directory exists
  if (!fs.existsSync(outputDir)) {
    fs.mkdirSync(outputDir, { recursive: true });
  }

  // Find all HTML files in slides directory
  const slideFiles = fs
    .readdirSync(slidesDir)
    .filter((f) => f.endsWith(".html"))
    .sort();

  console.log(`Found ${slideFiles.length} slides to screenshot`);

  for (const slideFile of slideFiles) {
    const slidePath = path.join(slidesDir, slideFile);
    const outputName = slideFile.replace(".html", ".png");
    const outputPath = path.join(outputDir, outputName);

    console.log(`Capturing ${slideFile}...`);

    await page.goto(`file://${path.resolve(slidePath)}`);

    // Wait for fonts and animations
    await page.waitForTimeout(500);

    // Take screenshot
    await page.screenshot({
      path: outputPath,
      type: "png",
      fullPage: false,
    });

    console.log(`✓ Saved ${outputName}`);
  }

  await browser.close();
  console.log("\n✨ All slides captured!");
}

// Usage
const carouselName = process.argv[2];
if (!carouselName) {
  console.error("Usage: node screenshot-slides.js <carousel-name>");
  process.exit(1);
}

const slidesDir = path.join(__dirname, carouselName, "slides");
const outputDir = path.join(__dirname, carouselName, "exports");

screenshotSlides(slidesDir, outputDir);
Installation

The skill directory needs these dependencies:

{
  "name": "linkedin-carousel-screenshots",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "playwright": "^1.40.0"
  }
}

First time setup:

cd /path/to/skills/create-html-carousel
npm install
Running Screenshot Script

After generating HTML slides:

node screenshot-slides.js carousel-name

This will:

  1. Open each slide HTML in a headless browser
  2. Set viewport to 1080×1080px
  3. Wait for fonts/animations to load
  4. Capture PNG screenshot
  5. Save to [carousel-name]/exports/

Phase 5: Delivery

After screenshots are generated, present to user:

✨ Your LinkedIn carousel is ready!

📁 Location: /assets/carousel-name/

**Slides:**
- 6 HTML slides in slides/ folder
- 6 PNG images in exports/ folder (1080×1080px)

**Preview:**
Open index.html to see all slides with navigation.

**Upload to LinkedIn:**
1. Create new post on LinkedIn
2. Click "Add media"
3. Upload all PNGs from exports/ folder in order
4. Add your post copy
5. Publish!

**File sizes:**
- slide-01.png: 234 KB ✓
- slide-02.png: 198 KB ✓
- slide-03.png: 256 KB ✓
(All under 10MB limit)

Want to make any changes to the slides?

Style Adaptation for Square Format

All styles from frontend-slides work for carousels, but require these adjustments:

Typography Scaling

Square format has less horizontal space, so scale fonts:

Element Presentation (16:9) Carousel (1:1)
Title clamp(2rem, 6vw, 5rem) 72px (fixed)
Subtitle clamp(1.25rem, 3vw, 2.5rem) 36px (fixed)
Body clamp(0.875rem, 1.5vw, 1.125rem) 28px (fixed)
Small clamp(0.75rem, 1vw, 0.875rem) 20px (fixed)

Why fixed sizes? We're targeting a single export size (1080×1080px), not responsive web viewing.

Layout Adjustments

Vertical space is precious:

  • Reduce top/bottom padding (80px instead of 4rem)
  • Tighter line-height (1.2-1.4 instead of 1.5-1.6)
  • Fewer list items per slide (max 3-4)
  • Smaller decorative elements

Mobile-first mindset:

  • Most LinkedIn users view on phones
  • Text must be readable at thumbnail size
  • High contrast is critical
  • Bold, simple layouts beat intricate designs

Content Best Practices

Hook Formula (Cover Slide)

Strong hooks for LinkedIn carousels:

  • Number + Promise: "5 workflows that 10x'd our outbound"
  • Contrarian: "Stop doing X. Do this instead."
  • Before/After: "How we went from X to Y in 30 days"
  • Question: "Why are only 3% of founders doing this?"
  • Curiosity gap: "The GTM strategy nobody talks about"
Body Slides (Items 2-9)

Each slide should:

  1. One clear point — Don't cram multiple concepts
  2. Visual hierarchy — Large number/icon + heading + body
  3. Concrete, not abstract — "Use job postings to find intent" not "Leverage signals"
  4. Scannable — 2-3 second read time max
Closing Slide

Always include a CTA:

  • "Follow for more [topic]"
  • "Repost if this helped"
  • "Comment your biggest takeaway"
  • "DM me if you want the full playbook"

Avoid:

  • "Link in comments" (often gets buried)
  • "Check out my website" (feels salesy)
  • No CTA at all (wasted opportunity)

Troubleshooting

Fonts Not Loading in Screenshots

Symptom: Screenshots show default system fonts

Solution:

  1. Use web-safe fonts (Arial, Georgia) OR
  2. Add await page.waitForLoadState('networkidle') before screenshot
  3. Increase wait timeout: await page.waitForTimeout(1000)
Screenshots Are Blurry

Symptom: Text looks fuzzy or low-res

Solution:

  1. Set device scale factor in Playwright:
    await page.setViewportSize({
      width: 1080,
      height: 1080,
      deviceScaleFactor: 2, // Retina-quality
    });
    
Content Overflows the Slide

Symptom: Text or elements cut off in screenshot

Solution:

  1. Reduce font sizes
  2. Decrease padding
  3. Split into multiple slides
  4. Simplify content (fewer bullets, shorter text)
Colors Look Different in Export

Symptom: PNG colors don't match HTML preview

Solution:

  • Ensure browser color profile matches sRGB
  • Use hex colors, avoid CSS filters that may render differently
  • Test screenshot script before generating all slides

Preset Quick Reference

Preset Best For Vibe
Bold Signal Confident, high-impact Professional
Dark Botanical Elegant, premium Sophisticated
Notebook Tabs Editorial, organized Friendly-professional
Pastel Geometry Friendly, approachable Playful
Neon Cyber Tech, innovation Futuristic
Split Pastel Creative, fun Energetic

See STYLE_PRESETS.md for complete styling details.


  • frontend-slides — For full presentations (not carousels)
  • personalized-email — For outreach content to pair with LinkedIn posts
  • deep-web-research — For researching topics/stats for carousel content

Example Session Flow

  1. User: "Create a LinkedIn carousel about 5 AI GTM workflows"
  2. Skill asks: content type, slide count, have content ready?
  3. User provides bullet points of the 5 workflows
  4. Skill asks: style preference
  5. User picks "Bold Signal"
  6. Skill generates 7 HTML slides (cover + 5 workflows + CTA)
  7. Skill runs screenshot script automatically
  8. Skill delivers folder with HTML + PNG exports
  9. User uploads PNGs to LinkedIn and publishes

Total time: 5-10 minutes from idea to ready-to-publish carousel.

1---
2name: create-html-carousel
3description: Create LinkedIn carousel posts as high-quality PNG images. Design informational multi-slide posts like "5 AI GTM workflows" with consistent styling, then automatically screenshot each slide at LinkedIn's optimal 1080x1080px format.
4---
5 
6> **Deprecated:** This skill is superseded by `goose-graphics`. See `skills/composites/goose-graphics/` (install with `npx goose-skills install goose-graphics`). The carousel format is one of seven formats in the newer skill and supports 36 style presets plus image sourcing and PNG export. This skill is retained for one release cycle before removal.
7 
8# LinkedIn Carousel Creator
9 
10Create stunning LinkedIn carousel posts as PNG images. This skill generates styled HTML slides optimized for square format (1080×1080px), then automatically screenshots each slide for direct upload to LinkedIn.
11 
12## Core Philosophy
13 
141. **LinkedIn-First Design** — Square format (1080×1080px), optimized for mobile feed viewing
152. **Informational Content** — Tips, workflows, lists, frameworks (not presentations)
163. **Consistent Styling** — Reuse proven design systems from frontend-slides
174. **Automated Export** — Generate HTML → Screenshot → PNG files ready for LinkedIn
185. **Viewport Perfect** — Every slide must fit exactly in 1080×1080px without scrolling
19 
20---
21 
22## LinkedIn Carousel Specs
23 
24**Format:** Square (1080×1080px)
25 
26- **Aspect ratio:** 1:1
27- **File format:** PNG (recommended) or JPG
28- **File size:** Under 10MB per image
29- **Max slides:** 10 images per carousel
30- **Ideal slide count:** 5-8 slides (best engagement)
31 
32**Content Structure:**
33 
341. **Cover slide** — Hook + title + your brand
352. **Content slides** — One key point per slide (3-6 slides)
363. **Closing slide** — CTA / summary / follow prompt
37 
38---
39 
40## When to Use This Skill
41 
42Use for LinkedIn carousel posts like:
43 
44- "5 AI GTM workflows you should be using"
45- "How to build X: A step-by-step guide"
46- "7 mistakes founders make with Y"
47- "The complete framework for Z"
48- "Before & After: How we 10x'd our metrics"
49 
50**NOT for:**
51 
52- Long-form presentations (use frontend-slides)
53- Video content
54- Single-image posts
55 
56---
57 
58## Workflow Overview
59 
60```
611. Content Input → User provides topic/outline
622. Style Selection → Choose visual style (or preview options)
633. HTML Generation → Create 1080×1080px HTML slides
644. Screenshot → Auto-capture each slide as PNG
655. Delivery → Folder of PNG files ready for LinkedIn upload
66```
67 
68---
69 
70## Phase 1: Content Discovery
71 
72### Step 1.1: Get Topic & Structure
73 
74Ask the user:
75 
76**Question 1: What's the topic?**
77 
78- Header: "Topic"
79- Question: "What's the main topic of this carousel?"
80- (Free text input)
81 
82**Question 2: Content Type**
83 
84- Header: "Format"
85- Question: "What type of post is this?"
86- Options:
87 - "Numbered list" — "5 ways to...", "7 mistakes...", "3 steps to..."
88 - "How-to guide" — Step-by-step tutorial or process
89 - "Framework" — Concept explanation with structure
90 - "Before/After" — Transformation or case study
91 - "Insights/Tips" — Collection of advice or learnings
92 
93**Question 3: Slide Count**
94 
95- Header: "Length"
96- Question: "How many slides?"
97- Options:
98 - "Short (5-6)" — Quick, punchy (best for mobile scrolling)
99 - "Medium (7-8)" — Standard carousel length
100 - "Long (9-10)" — Maximum LinkedIn allows
101 
102**Question 4: Branding Handle**
103 
104- Header: "Brand"
105- Question: "What handle or name should appear on each slide?"
106- (Free text input — e.g., "@yourhandle", "Acme Inc", or leave blank for none)
107 
108**Question 5: Content Ready?**
109 
110- Header: "Content"
111- Question: "Do you have the content written?"
112- Options:
113 - "Yes, I have all content" — Paste it in
114 - "I have bullet points" — Need light formatting
115 - "Just the topic" — Need help outlining
116 
117If user has content, ask them to share it.
118 
119### Content Density Rules for LinkedIn
120 
121Each slide should be **scannable in 2-3 seconds** on mobile:
122 
123| Slide Type | Max Content |
124| ---------- | -------------------------------------------------------- |
125| Cover | Title (1 line) + subtitle (1 line) + branding |
126| List item | Number/icon + heading (2 lines max) + body (3 lines max) |
127| Framework | Diagram/visual + 2-4 labels |
128| Quote/Stat | 1 large stat or quote + context |
129| CTA | 1 action + visual element |
130 
131**If content exceeds limits:** Break into multiple slides or simplify.
132 
133---
134 
135## Phase 2: Style Selection
136 
137Users can choose styles two ways:
138 
139### Option A: Direct Selection (Faster)
140 
141Show preset picker:
142 
143**Question: Pick a Style**
144 
145- Header: "Style"
146- Question: "Which visual style works best for your content?"
147- Options:
148 - "Bold Signal" — High-contrast card on dark, confident
149 - "Dark Botanical" — Elegant dark with soft abstract shapes
150 - "Notebook Tabs" — Editorial cream paper with colorful tabs
151 - "Pastel Geometry" — Friendly pastels with decorative pills
152 - "Neon Cyber" — Futuristic tech aesthetic
153 - "Split Pastel" — Playful two-tone split design
154 
155(See STYLE_PRESETS.md for full details on each style)
156 
157### Option B: Guided Discovery
158 
159If user isn't sure, ask:
160 
161**Question: Audience & Tone**
162 
163- Header: "Vibe"
164- Question: "Who's your audience and what tone?"
165- Options:
166 - "Professional/Corporate" → Recommend: Bold Signal, Dark Botanical
167 - "Creative/Playful" → Recommend: Split Pastel, Pastel Geometry
168 - "Technical/Dev-focused" → Recommend: Neon Cyber, Terminal Green
169 - "Elegant/Premium" → Recommend: Dark Botanical, Paper & Ink
170 
171Then generate 2-3 preview slides and let user pick.
172 
173---
174 
175## Phase 3: Generate HTML Carousel
176 
177### File Structure
178 
179All carousel files (HTML source and PNG exports) are saved to the shared assets directory.
180 
181```
182[carousel-name]/
183├── index.html # Full carousel (all slides)
184├── slides/
185│ ├── slide-01.html # Individual slide pages
186│ ├── slide-02.html
187│ └── ...
188└── exports/
189 ├── slide-01.png # Screenshots (generated in Phase 4)
190 ├── slide-02.png
191 └── ...
192```
193 
194### HTML Architecture for 1080×1080px
195 
196**CRITICAL: LinkedIn carousel slides are SQUARE (1:1 ratio), not widescreen.**
197 
198```html
199<!DOCTYPE html>
200<html lang="en">
201 <head>
202 <meta charset="UTF-8" />
203 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
204 <title>Slide 01</title>
205 
206 <!-- Fonts -->
207 <link rel="stylesheet" href="https://api.fontshare.com/v2/css?f[]=..." />
208 
209 <style>
210 /* ===========================================
211 LINKEDIN CAROUSEL: SQUARE FORMAT
212 Fixed 1080×1080px for screenshot
213 =========================================== */
214 :root {
215 /* Fixed size for LinkedIn */
216 --slide-width: 1080px;
217 --slide-height: 1080px;
218 
219 /* Colors (from chosen preset) */
220 --bg-primary: #0a0f1c;
221 --text-primary: #ffffff;
222 --accent: #00ffcc;
223 
224 /* Typography - scaled for square format */
225 --title-size: 72px;
226 --subtitle-size: 36px;
227 --body-size: 28px;
228 --small-size: 20px;
229 
230 /* Spacing */
231 --slide-padding: 80px;
232 --content-gap: 40px;
233 
234 /* Animation */
235 --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
236 }
237 
238 * {
239 margin: 0;
240 padding: 0;
241 box-sizing: border-box;
242 }
243 
244 html,
245 body {
246 width: var(--slide-width);
247 height: var(--slide-height);
248 overflow: hidden;
249 }
250 
251 body {
252 font-family: var(--font-body);
253 background: var(--bg-primary);
254 color: var(--text-primary);
255 display: flex;
256 flex-direction: column;
257 justify-content: center;
258 align-items: center;
259 padding: var(--slide-padding);
260 }
261 
262 /* Content container */
263 .slide-content {
264 width: 100%;
265 max-width: 100%;
266 display: flex;
267 flex-direction: column;
268 gap: var(--content-gap);
269 }
270 
271 /* Typography hierarchy */
272 h1 {
273 font-size: var(--title-size);
274 font-weight: 800;
275 line-height: 1.1;
276 margin-bottom: 20px;
277 }
278 
279 h2 {
280 font-size: var(--subtitle-size);
281 font-weight: 700;
282 line-height: 1.2;
283 }
284 
285 p,
286 li {
287 font-size: var(--body-size);
288 line-height: 1.4;
289 }
290 
291 /* List styling */
292 ul {
293 list-style: none;
294 }
295 
296 li {
297 padding-left: 40px;
298 position: relative;
299 margin-bottom: 20px;
300 }
301 
302 li::before {
303 content: "→";
304 position: absolute;
305 left: 0;
306 color: var(--accent);
307 font-weight: bold;
308 }
309 
310 /* Number badge (for list items) */
311 .number {
312 font-size: 120px;
313 font-weight: 900;
314 color: var(--accent);
315 opacity: 0.15;
316 position: absolute;
317 top: -40px;
318 left: -20px;
319 z-index: 0;
320 }
321 
322 /* Branding footer */
323 .brand {
324 position: absolute;
325 bottom: var(--slide-padding);
326 right: var(--slide-padding);
327 font-size: var(--small-size);
328 opacity: 0.7;
329 }
330 
331 /* ===========================================
332 STYLE-SPECIFIC OVERRIDES
333 Inject preset styles here
334 =========================================== */
335 /* ... preset-specific CSS ... */
336 </style>
337 </head>
338 <body>
339 <div class="slide-content">
340 <!-- Slide content goes here -->
341 <h1>Your Title Here</h1>
342 <p>Your content here</p>
343 </div>
344 
345 <div class="brand">@yourbrand</div>
346 </body>
347</html>
348```
349 
350### Content Slide Templates
351 
352**Cover Slide:**
353 
354```html
355<div class="slide-content">
356 <h1>5 AI GTM Workflows<br />You Should Be Using</h1>
357 <p>Scale your outbound without scaling your team</p>
358</div>
359<div class="brand">@yourhandle</div>
360```
361 
362**Numbered Item (e.g., Slide 2/6):**
363 
364```html
365<div class="slide-content">
366 <div class="number">01</div>
367 <h2>Signal-Based Outbound</h2>
368 <p>
369 Monitor job postings, funding announcements, and tech stack changes to find
370 companies actively solving your problem.
371 </p>
372</div>
373<div class="brand">@yourhandle • 1/5</div>
374```
375 
376**Framework Slide:**
377 
378```html
379<div class="slide-content">
380 <h2>The GTM Engineering Stack</h2>
381 <div class="framework-grid">
382 <div class="box">Research</div>
383 <div class="box">Personalization</div>
384 <div class="box">Outreach</div>
385 <div class="box">Tracking</div>
386 </div>
387</div>
388<div class="brand">@yourhandle • 3/5</div>
389```
390 
391**CTA Slide:**
392 
393```html
394<div class="slide-content">
395 <h2>Want more like this?</h2>
396 <p>Follow me for more tips and workflows.</p>
397 <div class="cta">Hit that follow button →</div>
398</div>
399<div class="brand">@yourhandle</div>
400```
401 
402---
403 
404## Phase 4: Screenshot Generation
405 
406After generating HTML, automatically capture screenshots.
407 
408### Using Playwright (Recommended)
409 
410Create a Node.js script to screenshot each slide:
411 
412```javascript
413// screenshot-slides.js
414const { chromium } = require("playwright");
415const path = require("path");
416const fs = require("fs");
417 
418async function screenshotSlides(slidesDir, outputDir) {
419 const browser = await chromium.launch();
420 const page = await browser.newPage();
421 
422 // Set viewport to LinkedIn carousel size
423 await page.setViewportSize({ width: 1080, height: 1080 });
424 
425 // Ensure output directory exists
426 if (!fs.existsSync(outputDir)) {
427 fs.mkdirSync(outputDir, { recursive: true });
428 }
429 
430 // Find all HTML files in slides directory
431 const slideFiles = fs
432 .readdirSync(slidesDir)
433 .filter((f) => f.endsWith(".html"))
434 .sort();
435 
436 console.log(`Found ${slideFiles.length} slides to screenshot`);
437 
438 for (const slideFile of slideFiles) {
439 const slidePath = path.join(slidesDir, slideFile);
440 const outputName = slideFile.replace(".html", ".png");
441 const outputPath = path.join(outputDir, outputName);
442 
443 console.log(`Capturing ${slideFile}...`);
444 
445 await page.goto(`file://${path.resolve(slidePath)}`);
446 
447 // Wait for fonts and animations
448 await page.waitForTimeout(500);
449 
450 // Take screenshot
451 await page.screenshot({
452 path: outputPath,
453 type: "png",
454 fullPage: false,
455 });
456 
457 console.log(`✓ Saved ${outputName}`);
458 }
459 
460 await browser.close();
461 console.log("\n✨ All slides captured!");
462}
463 
464// Usage
465const carouselName = process.argv[2];
466if (!carouselName) {
467 console.error("Usage: node screenshot-slides.js <carousel-name>");
468 process.exit(1);
469}
470 
471const slidesDir = path.join(__dirname, carouselName, "slides");
472const outputDir = path.join(__dirname, carouselName, "exports");
473 
474screenshotSlides(slidesDir, outputDir);
475```
476 
477### Installation
478 
479The skill directory needs these dependencies:
480 
481```json
482{
483 "name": "linkedin-carousel-screenshots",
484 "version": "1.0.0",
485 "private": true,
486 "dependencies": {
487 "playwright": "^1.40.0"
488 }
489}
490```
491 
492First time setup:
493 
494```bash
495cd /path/to/skills/create-html-carousel
496npm install
497```
498 
499### Running Screenshot Script
500 
501After generating HTML slides:
502 
503```bash
504node screenshot-slides.js carousel-name
505```
506 
507This will:
508 
5091. Open each slide HTML in a headless browser
5102. Set viewport to 1080×1080px
5113. Wait for fonts/animations to load
5124. Capture PNG screenshot
5135. Save to `[carousel-name]/exports/`
514 
515---
516 
517## Phase 5: Delivery
518 
519After screenshots are generated, present to user:
520 
521```
522✨ Your LinkedIn carousel is ready!
523 
524📁 Location: /assets/carousel-name/
525 
526**Slides:**
527- 6 HTML slides in slides/ folder
528- 6 PNG images in exports/ folder (1080×1080px)
529 
530**Preview:**
531Open index.html to see all slides with navigation.
532 
533**Upload to LinkedIn:**
5341. Create new post on LinkedIn
5352. Click "Add media"
5363. Upload all PNGs from exports/ folder in order
5374. Add your post copy
5385. Publish!
539 
540**File sizes:**
541- slide-01.png: 234 KB ✓
542- slide-02.png: 198 KB ✓
543- slide-03.png: 256 KB ✓
544(All under 10MB limit)
545 
546Want to make any changes to the slides?
547```
548 
549---
550 
551## Style Adaptation for Square Format
552 
553All styles from frontend-slides work for carousels, but require these adjustments:
554 
555### Typography Scaling
556 
557Square format has less horizontal space, so scale fonts:
558 
559| Element | Presentation (16:9) | Carousel (1:1) |
560| -------- | -------------------------------- | -------------- |
561| Title | clamp(2rem, 6vw, 5rem) | 72px (fixed) |
562| Subtitle | clamp(1.25rem, 3vw, 2.5rem) | 36px (fixed) |
563| Body | clamp(0.875rem, 1.5vw, 1.125rem) | 28px (fixed) |
564| Small | clamp(0.75rem, 1vw, 0.875rem) | 20px (fixed) |
565 
566**Why fixed sizes?** We're targeting a single export size (1080×1080px), not responsive web viewing.
567 
568### Layout Adjustments
569 
570**Vertical space is precious:**
571 
572- Reduce top/bottom padding (80px instead of 4rem)
573- Tighter line-height (1.2-1.4 instead of 1.5-1.6)
574- Fewer list items per slide (max 3-4)
575- Smaller decorative elements
576 
577**Mobile-first mindset:**
578 
579- Most LinkedIn users view on phones
580- Text must be readable at thumbnail size
581- High contrast is critical
582- Bold, simple layouts beat intricate designs
583 
584---
585 
586## Content Best Practices
587 
588### Hook Formula (Cover Slide)
589 
590Strong hooks for LinkedIn carousels:
591 
592- Number + Promise: "5 workflows that 10x'd our outbound"
593- Contrarian: "Stop doing X. Do this instead."
594- Before/After: "How we went from X to Y in 30 days"
595- Question: "Why are only 3% of founders doing this?"
596- Curiosity gap: "The GTM strategy nobody talks about"
597 
598### Body Slides (Items 2-9)
599 
600Each slide should:
601 
6021. **One clear point** — Don't cram multiple concepts
6032. **Visual hierarchy** — Large number/icon + heading + body
6043. **Concrete, not abstract** — "Use job postings to find intent" not "Leverage signals"
6054. **Scannable** — 2-3 second read time max
606 
607### Closing Slide
608 
609Always include a CTA:
610 
611- "Follow for more [topic]"
612- "Repost if this helped"
613- "Comment your biggest takeaway"
614- "DM me if you want the full playbook"
615 
616Avoid:
617 
618- "Link in comments" (often gets buried)
619- "Check out my website" (feels salesy)
620- No CTA at all (wasted opportunity)
621 
622---
623 
624## Troubleshooting
625 
626### Fonts Not Loading in Screenshots
627 
628**Symptom:** Screenshots show default system fonts
629 
630**Solution:**
631 
6321. Use web-safe fonts (Arial, Georgia) OR
6332. Add `await page.waitForLoadState('networkidle')` before screenshot
6343. Increase wait timeout: `await page.waitForTimeout(1000)`
635 
636### Screenshots Are Blurry
637 
638**Symptom:** Text looks fuzzy or low-res
639 
640**Solution:**
641 
6421. Set device scale factor in Playwright:
643 ```javascript
644 await page.setViewportSize({
645 width: 1080,
646 height: 1080,
647 deviceScaleFactor: 2, // Retina-quality
648 });
649 ```
650 
651### Content Overflows the Slide
652 
653**Symptom:** Text or elements cut off in screenshot
654 
655**Solution:**
656 
6571. Reduce font sizes
6582. Decrease padding
6593. Split into multiple slides
6604. Simplify content (fewer bullets, shorter text)
661 
662### Colors Look Different in Export
663 
664**Symptom:** PNG colors don't match HTML preview
665 
666**Solution:**
667 
668- Ensure browser color profile matches sRGB
669- Use hex colors, avoid CSS filters that may render differently
670- Test screenshot script before generating all slides
671 
672---
673 
674## Preset Quick Reference
675 
676| Preset | Best For | Vibe |
677| --------------- | ---------------------- | --------------------- |
678| Bold Signal | Confident, high-impact | Professional |
679| Dark Botanical | Elegant, premium | Sophisticated |
680| Notebook Tabs | Editorial, organized | Friendly-professional |
681| Pastel Geometry | Friendly, approachable | Playful |
682| Neon Cyber | Tech, innovation | Futuristic |
683| Split Pastel | Creative, fun | Energetic |
684 
685See STYLE_PRESETS.md for complete styling details.
686 
687---
688 
689## Related Skills
690 
691- **frontend-slides** — For full presentations (not carousels)
692- **personalized-email** — For outreach content to pair with LinkedIn posts
693- **deep-web-research** — For researching topics/stats for carousel content
694 
695---
696 
697## Example Session Flow
698 
6991. User: "Create a LinkedIn carousel about 5 AI GTM workflows"
7002. Skill asks: content type, slide count, have content ready?
7013. User provides bullet points of the 5 workflows
7024. Skill asks: style preference
7035. User picks "Bold Signal"
7046. Skill generates 7 HTML slides (cover + 5 workflows + CTA)
7057. Skill runs screenshot script automatically
7068. Skill delivers folder with HTML + PNG exports
7079. User uploads PNGs to LinkedIn and publishes
708 
709Total time: 5-10 minutes from idea to ready-to-publish carousel.
710 
View all files on GitHub →

Details

Updated
Sep 21, 2026
License
MIT
Stars on the repo
★ 1,220
Checked
Source
gooseworks-ai/goose-skills ↗
Creator
gooseworks-ai · 206 listings
View creator

Made with create-html-carousel

LinkedIn Carousel Creator — CleanShot 2026-07-13 at 20 16 54@2x (from the gooseworks-ai/goose-skills README)
LinkedIn Carousel Creator — CleanShot 2026-07-13 at 20 16 54@2x (from the gooseworks-ai/goose-skills README)

by gooseworks-ai

Similar skills

See all →
SkillGenerate a branded slide-by-slide LinkedIn carouselGemini carouselcharlie947/social-media-skills · by charlie947Generate a branded slide-by-slide LinkedIn carousel using Gemini. Takes source content, builds a design brief, waits for approval, then outputs per-slide image generation prompts. 1080x1350 vertical format. Use this skill whenever the user says "carousel", "build a carousel", "turn this into a carousel", "gemini carousel", or wants multi-slide LinkedIn content. Always includes an approval gate between brief and image generation.★ 3.7k GitHub starsSkillBuild a LinkedIn document postLi carouselJakeschincariol/linkedin-agent-skill · by JakeschincariolBuild a LinkedIn document post (carousel) - slide-by-slide copy, the cover that earns the swipe, and the PDF to upload. Use when the user says carousel", "document post", "slides for LinkedIn", "turn this into a carousel", or has a list-shaped idea that would die as a text post.★ 1.9k GitHub starsSkillDraft an Instagram caption with the hook in the first 125Instagram Caption Writersergebulaev/instagram-skills · by sergebulaevDraft an Instagram caption with the hook in the first 125 characters, a skimmable body, and one clear CTA, using a 2026 hook formula chosen by goal (saves, shares, comments, follows). Runs the humanizer pass and, on approval, publishes with the image or video you supply via the Publora media flow. Use to caption a single image or a Reel. Not for slide-by-slide carousels (use ig-carousel-planner) or auditing a draft (use ig-humanizer --mode audit).★ 138 GitHub starsSkillPlan an Instagram carousel slide by slide, up to 10 slidesInstagram Carousel Plannersergebulaev/instagram-skills · by sergebulaevPlan an Instagram carousel slide by slide, up to 10 slides, with a hook slide that opens a loop, value slides that front-load the payoff, and a payoff slide that earns the save and follow. Picks a 2026 carousel formula (listicle, before/after, myth-buster, framework) by goal (saves, shares, follows), drafts each slide's text plus the caption, then publishes the images you supply via Publora. Use to structure a multi-slide carousel. Not for single-image captions (use ig-caption-writer).★ 138 GitHub starsSkillSocial media campaign analysis and performance trackingSocial media analyzeralirezarezvani/claude-skills · by alirezarezvaniSocial media campaign analysis and performance tracking. Calculates engagement rates, ROI, and benchmarks across platforms. Use when analyzing social media performance, calculating engagement rate, measuring campaign ROI, comparing platform metrics, or benchmarking against industry standards. Also use when the user mentions "social media audit," "engagement rate," or "which platform performs best.★ 26.3k GitHub starsSkillScore a LinkedIn post using real performance dataPost scorercharlie947/social-media-skills · by charlie947Score a LinkedIn post using real performance data. Pulls the user's own post history via Apify (or uses cached data) to identify what actually performs, then scores the draft against those patterns. Use this skill whenever the user says "score my post", "review my post", "rate this post", "give me feedback", "how good is this post", or pastes a LinkedIn post and asks for critique. Separates historical comparisons from an explicitly labelled editorial-only fallback. Designed for live scoring at events and everyday post review.★ 3.7k GitHub stars

More from gooseworks-ai

SkillMine the highest-converting ad angles from customer reviewsAd angle minergooseworks-ai/goose-skills · by gooseworks-aiMine the highest-converting ad angles from customer reviews, Reddit complaints, support tickets, and competitor ads. Extracts actual pain language, competitor weaknesses, and outcome phrases that real buyers use. Outputs a ranked angle bank with proof quotes and recommended ad formats per angle.★ 1.2k GitHub starsSkillAnalyze ad campaign performance data to identify what'sAd campaign analyzergooseworks-ai/goose-skills · by gooseworks-aiAnalyze ad campaign performance data (Google, Meta, LinkedIn) to identify what's working, what's wasting budget, and specific cut/scale/test recommendations. Runs statistical analysis, funnel diagnostics, and multi-channel budget reallocation with specific dollar-amount shift recommendations and scenario modeling.★ 1.2k GitHub starsSkillFor paid lead-gen and participant-recruitment adsAd lead quality analyzergooseworks-ai/goose-skills · by gooseworks-aiFor paid lead-gen and participant-recruitment ads, replaces vanity CPA with true CAC per qualified lead by joining ad-platform data with downstream funnel events, surfaces tracking gaps, and classifies every creative into Scale / Keep / Investigate / Cut.★ 1.2k GitHub starsSkillAnalyze the message match between your ads and landing pagesAd to landing page auditorgooseworks-ai/goose-skills · by gooseworks-aiAnalyze the message match between your ads and landing pages. Checks if the promise in the ad copy carries through to the landing page headline, body, and CTA. Flags disconnects that kill conversion rates. Works with Google, Meta, and LinkedIn ads.★ 1.2k GitHub starsSkillCheck and improve your brand's visibility across AI searchAeogooseworks-ai/goose-skills · by gooseworks-aiCheck and improve your brand's visibility across AI search engines (ChatGPT, Perplexity, Gemini, Grok, Claude, DeepSeek). Set up tracking, run visibility analyses, audit your website for AI readability, and get actionable recommendations. Uses the npx goose-aeo@latest CLI.★ 1.2k GitHub starsSkillSearch Amazon products - find items, compare pricesAmazon Product Searchgooseworks-ai/goose-skills · by gooseworks-aiSearch Amazon products - find items, compare prices, read reviews★ 1.2k GitHub stars