- 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
---
## LinkedIn Carousel Specs
**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.
---
## Phase 3: Generate HTML Carousel
### 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.**
```html
<!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:**
```html
<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):**
```html
<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:**
```html
<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:**
```html
<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.
### Using Playwright (Recommended)
Create a Node.js script to screenshot each slide:
View on GitHub