# Carousel Post

> Turn one topic into a ready-to-post image carousel -- 5 to 8 card PNGs plus the caption and hashtags. Use for "make a carousel", "turn this into cards", "make the Instagram post", "make image cards for this", "make something to post on the feed". Every card uses the bundled fixed template. Two cover options are produced -- a licensed non-AI stock photo and a people-free photoreal AI image -- shown as two full previews so the user picks; everything after the cover is built once. Long-form articles are blog-post; verifying the facts first is topic-brief.

- Skill: `chanuk0/carousel-post` (Agent Skill, multi-file: 12 files)
- Install (CLI): `npx skillmds@latest add chanuk0/carousel-post`
- Raw SKILL.md: https://api.skillmd.com/api/skills/chanuk0/carousel-post/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: chanuk0 (https://skillmd.com/u/chanuk0)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/chanuk0/carousel-post

---


# Carousel Post

Turns one topic into **5 to 8 card PNGs, a caption, and hashtags**, ready to upload.

A carousel is not a shortened article. What matters is how long a single card holds the eye
and whether the first card stops the scroll.

## The template is not optional

Every post uses the **bundled card template (13 patterns)** exactly as shipped.

- Copy `templates/base.css` to the output's `cards/base.css` **unmodified**.
- Use only the document skeleton in `templates/card.html` and the card patterns in
  `templates/patterns.html`.
- First card is `card--cover`. Last card is one of `card--cta-channel`,
  `card--cta-comment`, or `card--cta-reply`.
- Body cards come from `card--photo`, `card--official`, `card--official-zoom`,
  `card--checklist`, `card--compare`, `card--steps`, `card--number`, `card--caution`,
  `card--myth`.
- No inline `style` attributes, no extra `<style>` block. No new colors, gradients, shadows,
  rounded cards, or decorative shapes.
- If a pattern doesn't fit the content, switch to a **different bundled pattern** rather than
  forcing it.

`scripts/check_cards.py` verifies the CSS matches the original byte for byte, the template
marker is present, patterns are allowed, the first and last cards are right, and no inline
styles crept in. **Don't route around it or ship with warnings unresolved.**

## Core principles

### The user picks the cover: real photo or AI

Before building the final cover, prepare **two cover candidates only** carrying the same
title. Body and CTA cards are built once.

1. **Option A, licensed stock photo** — find a **non-AI** free photo whose licence and
   original page you can verify (Pexels, Unsplash, and similar). Prefer scenes where someone
   interacts with the subject, favoring hands, backs, and objects over faces. If the user
   supplies a photo and says to use it, that's the exception. **Never ask the user to shoot
   something.**
2. **Option B, photoreal AI image** — natural, like a real photograph, and **with no people
   in it**. Show the object, the place, or the situation. If a person is unavoidable, hands
   or a back only. **Never generate a face.**

Slot each cover in front of the identical body and CTA cards to produce `preview-a.png` and
`preview-b.png`. In chat, show **two clickable file links to the full previews** — not the
covers on their own. The two previews must differ **only** in the first card; everything
after it is identical, pixel for pixel. Apply the chosen cover to `cards/card-01.*` and the
final `preview.png` only after the user picks.

If the first search turns up nothing suitable, change the search terms, the scene, and the
site, and keep looking. Where no exact match exists, take a neutral everyday scene close to
the subject. **Never stall waiting on a photo, and never present only the AI option and pick
for the user.** Selection rules are in `references/images.md`.

### Crop screenshots to what matters, then make it big

**Never drop a full-page screenshot in.** The card's screen frame is roughly **880x558px**
and the image is set to `contain`, so the wider you capture, the smaller the text gets.

- Cut out **one block** — the table or the sentence. Drop the page header, the whitespace,
  the unrelated menus, the surrounding paragraphs.
- Crop close to the frame's ratio (about 1.6:1). Outside 1:1 to 1.8:1 and the letterboxing
  shrinks the text again.
- **Legibility floor:** the smallest body text inside the crop must be at least **1/34 of the
  crop width** in height. (900px wide crop means 26px text.) Below that, crop tighter or
  split it across two cards.
- If the source is low-resolution and stays blurry after cropping, **re-capture it larger**
  (zoom the browser first). Never upscale a small image.
- Cropping must not reverse a condition or strip its context. If you need two separate
  sentences, use `card--official-zoom` to show the original location beside the excerpt, or
  move it to a text card instead.
- Export the card to PNG and **open it at 100% to confirm the text is readable.** If it
  isn't, it doesn't ship.

Body images are chosen in this order: **real screenshot -> licensed non-AI stock -> official
supplied image -> text card -> AI image**. Don't fill an empty card with a mood shot. Across
the whole 5-to-8 card set, **at most one AI-generated image**, cover included. Pick the AI
cover and there are zero AI body images.

### The first card stops the scroll; it doesn't explain

Throw **one** hook — the benefit, the result, the number, the news, or the twist — and throw
it big. The formal name, the definition, the conditions, and the procedure do not belong on
the cover. Conditions and risks appear there only when they are the actual story.

Concrete detail on the cover is capped at **one piece**. Don't stack a deadline, an amount,
an audience, a product name, and a category on one card.

- Title fits in two lines at 92px, ideally under about 45 characters total. A full line is a
  summary, not a hook.
- The eyebrow is **one** label. Don't list variants or conditions in it.
- **Leave something to find on the next card.** Say everything and there's no reason to swipe.

Example — `Swap before 30 Sept and you qualify for both schemes` stacks deadline, action, and
outcome until the hook blurs. `After 30 September you cannot switch` keeps one piece and
moves the rest to card two.

Curiosity phrasing (`you'll want to see this`, `most people miss this`) is fine as **support**
for the hook. What's not fine is using only that and hiding the actual subject. The cover
must carry **at least one** of a concrete benefit, audience, result, number, or piece of news.

- Fine: `Most people miss this | 50% off exam fees for under-35s`
- Fine: `Worth doing today | three discounted attempts this year`
- Not fine: `This is huge` with nothing else

### Card two makes the subject make sense

For a policy, a program, an offer, or a financial product, use the second card to establish
**what this actually is.** The default flow is
`cover hook -> what it is -> benefit, audience, conditions -> how to do it -> CTA`.

Don't let card two restate the cover's number. One or two sentences, no more.

- What it is, and who runs it
- Who gets what, and in what form: discount, refund, cash, credit

Example — after a cover reading `Most people miss this | 50% off exam fees`, card two reads:
`The national skills body covers half the exam fee for under-35s. It applies at checkout
when you register.`

If the subject is already obvious, don't add an explainer card mechanically.

### Be accurate without turning it into a warning label

Eligibility, application steps, and product structure are **useful information**, not risk
warnings. Don't phrase every condition as a penalty, and don't recite loss-of-principal,
auto-renewal, and rejection risk just because the topic involves money.

- Keep only the warnings that genuinely change what someone does.
- **A dedicated caution card is not the default.** Use `card--caution`, at most once, when
  loss of principal, debt, fees, auto-renewal, long lock-in, or irreversibility is central.
- For grants, offers, and information posts, fold eligibility and steps into the card they
  belong to and skip the caution card.
- **Never repeat the same condition** across cover, body, CTA, and caption. One place, once.
- Skip stock phrases (`terms may change, check again`, `investing carries risk`) unless they
  change a specific action. The checked-on date and the official source do that job.

AI images visualize the subject or support an explanation. **Never generate a scene that
could be mistaken for evidence** — a payment landing, an approval, a completed application,
an official document, an app UI. Without a real screenshot, use a text card.

## Output layout

```text
drafts/YYYY-MM-DD-<topic>/
|- plan.md              # the single planning document
|- photos/
|  |- profile.png       # your CTA profile image
|  |- sources.md        # every image's origin, rights, and generation notes
|- cover-candidates/
|  |- cover-a-stock.*        # licensed non-AI photo
|  |- cover-b-ai.*           # people-free photoreal AI image
|  |- cover-a-preview.png    # same title on each, for comparison
|  |- cover-b-preview.png
|- cards/
|  |- base.css          # byte-identical to templates/base.css
|  |- card-01.html ...  # every card carries the template marker
|  |- card-01.png  ...
|- A/                   # shareable set: cover A + the shared cards
|- B/                   # shareable set: cover B + the same shared cards
|- preview-a.png
|- preview-b.png
|- preview.png          # final, after the user picks
|- caption.md
```

`A/` and `B/` are **two complete, uploadable sets.** Each contains card PNGs only, numbered,
so the user can share or open a folder directly. `A/card-01.png` is the stock cover,
`B/card-01.png` is the AI cover, and **everything from card two on must be byte-identical
between the two folders.** `cards/` is the working folder with HTML and CSS — not for sharing.

## Procedure

### 1. Get the topic

Work from a `topic-brief` output. If there isn't one, or it covers a different subject, **stop
and go do the brief first.** Extract the following, marking anything absent as `unconfirmed`:

```text
how much someone gets or saves / who qualifies / the deadline
current status / the official URL / the steps and eligibility that actually matter
any serious caveat that changes a decision (only if there is one)
```

### 2. Get the visuals

Read and follow `references/images.md`.

1. Find a non-AI free stock photo, ideally without a prominent face, as option A.
2. On the photo's detail page, confirm it isn't flagged as AI-generated, then record the
   photographer, the original URL, the licence URL, and the date accessed as `stock`. Never
   download from a search thumbnail or an unattributed re-host.
3. No suitable photo? Change the search terms, the scene, and the site. Still nothing? Take a
   neutral everyday scene close to the subject. **Never ask the user to shoot anything.**
4. Generate a people-free photoreal option B per `references/images.md`. If a person is
   unavoidable, no face.
5. For body cards that need evidence, capture the official page yourself. Official
   photography and product images are fine where the source and the usage terms are clear.
   Crop to the frame ratio (about 1.6:1) and check the 1/34 legibility floor.
6. Build the body once, from screenshots, stock, official images, and text cards. At most one
   AI image in the finished set, and none in the body if the cover is AI.
7. Build the full `preview-a.png` and `preview-b.png` with only the cover swapped, and give
   the user two clickable links to choose from.

Classify every final image as `shot`, `stock`, `official`, or `ai` in `photos/sources.md`.
`shot` is only for images the user supplied. The number of photos is not a cap on card count.

### 3. Plan

Read `references/structure.md` and write `plan.md`.

| Field | Content |
| --- | --- |
| Type | explainer / first-hand test / comparison / checklist, plus why |
| Card count | 5-8, default 5-6, with a reason for each card past 6 |
| Cover plan | A stock / B AI, three title candidates, comparison previews, user's choice |
| Card table | number \| role \| **bundled pattern class** \| one-line message \| image \| source |
| Caption angle | two opening-line candidates |
| Caution placement | none / one card / one caption line, and why |

Fix card one as `card--cover` and the last card as one of the three CTA patterns first. Card
HTML and the caption both derive from this file. **To change the content, change the plan
first.**

### 4. Build the card HTML

1. Copy `templates/base.css` to `cards/base.css` unchanged.
2. Put your profile image at `photos/profile.png`.
3. Copy the `templates/card.html` skeleton for each card.
4. Paste one `<section class="card ...">` from `templates/patterns.html` and change only the
   text, image paths, source line, and page numbers.
5. Read `references/design.md` for text volume and pattern selection.

Fixed values: 1080x1350, 72px sides, 72px top, 96px bottom. Photo and official cards keep the
810px visual over the 540px information panel. The cover is one eyebrow line plus a two-line
92px title. Body cards are a two-line 62px title plus at most two 38px sentences.

### 5. Capture PNGs

```bash
python scripts/capture.py <out>/cards
python scripts/make_preview.py <out>/cards --cover <out>/cover-candidates/cover-a-preview.png --output <out>/preview-a.png
python scripts/make_preview.py <out>/cards --cover <out>/cover-candidates/cover-b-preview.png --output <out>/preview-b.png
python scripts/export_sets.py <out>
```

Any card or cover PNG that isn't 1080x1350 is a failure. Open both previews and confirm the
cards appear in order and that **only the first card differs**.

`export_sets.py` writes the two shareable sets and **stops** if the covers are identical, if
either cover is the wrong size, or if anything after card one differs between the sets.

Give the user two preview links plus the `A/` and `B/` folder paths. Once they choose, apply
that cover to `cards/card-01.*`, rebuild the final `preview.png`, and rerun `export_sets.py`.
**Keep both folders after the choice** — they may want to swap covers later.

### 6. Caption

Read `references/caption.md` and write `caption.md`. Don't restate the cards; carry the
context, the how-to, the checked-on date, and the official source that would clutter an image.

**The last CTA card and the caption CTA must match.** If the card asks for a comment keyword,
the caption uses the same keyword, spelled identically.

### 7. Check

```bash
python scripts/check_cards.py <out>
```

Template match, card count, patterns, image sources, PNG dimensions, `A/` and `B/` set
agreement, caption structure, hashtags, and **CTA agreement between the last card and the
caption.** Fix until it passes. If you didn't run it, report `not run` and why.

Then open the cards yourself and work through the eye-check list in `references/design.md`
and `references/images.md`. In particular: do the two previews differ only on card one; is
the finished set at one AI image or fewer; are there no faces; does the cover carry both a
reason to swipe and one concrete detail; is the official screenshot readable at 100%; does
card two explain the subject rather than repeat the cover?

## The fact line

Be as punchy as you like. Don't move a fact.

1. Never invent a number, a condition, or a result.
2. Never blur applied / under review / approved / received.
3. Never describe an AI image as if it were real evidence.

