Skip to main content

carousel-app

Launch the visual Instagram carousel maker app. Opens the local web app for creating, editing, and exporting branded Instagram carousels with AI-generated background images. Triggers on: open carousel app, launch carousel maker, carousel maker, visual carousel, instagram carousel app, open carousel, start carousel app.

Source facts

Repository
tylerprogramming/claude-skills
Last source activity
August 9, 2026 at 15:56
Detected SKILL.md language
English
Stars
0
Forks
2

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
carousel-app
description
Launch the visual Instagram carousel maker app. Opens the local web app for creating, editing, and exporting branded Instagram carousels with AI-generated background images. Triggers on: open carousel app, launch carousel maker, carousel maker, visual carousel, instagram carousel app, open carousel, start carousel app.
# Visual Instagram Carousel Maker Launch the visual carousel maker app at `~/carousel-studio/`. This is a React + Hono app for creating branded Instagram carousels with AI-generated background images, multiple slide types, and PDF/PNG export. ## How to Use ### Step 1: Check if already running ```bash lsof -ti:5175 | head -1 ``` If a process is already listening on port 5175, the app is running — skip to Step 3. ### Step 2: Start the dev server ```bash cd ~/carousel-studio && bun run dev & ``` Wait 3 seconds for the server to boot: ```bash sleep 3 ``` Verify it's up: ```bash lsof -ti:5175 | head -1 ``` If still nothing after 5 more seconds, check for errors: ```bash lsof -ti:3010 | head -1 ``` (The Hono API server runs on 3010, Vite client on 5175.) ### Step 3: Open in browser ```bash open http://localhost:5175 ``` ### Step 4: Confirm to the user Tell the user: - The carousel maker is open at `http://localhost:5175` - They can pick a framework (Educational, Hormozi, Quick Wins, Storytelling, Instagram Writer) - Generate AI background images per slide via the Background Image panel - Export all slides as PNG or a combined PDF - Carousels are auto-saved and can be reloaded from the drawer ## What the App Does - **Frameworks**: Pre-built slide structures for different content styles - **AI Backgrounds**: Kie.ai image generation per slide or for all slides at once - **Image Library**: Previously generated backgrounds are saved and reusable - **Text Scale**: Per-slide font size control (XS → XL + fine slider) - **Export**: Download individual PNGs or a multi-page PDF - **Save/Load**: Carousels saved as JSON to `~/carousel-studio/carousels/`, reload from the Library drawer ## Stopping the Server If the user wants to stop the app: ```bash pkill -f "bun run dev" 2>/dev/null; lsof -ti:5175 | xargs kill -9 2>/dev/null; lsof -ti:3010 | xargs kill -9 2>/dev/null ``` ## Notes - App lives at `~/carousel-studio/` - Output PNGs go to `~/carousel-studio/output/` - Background images saved as `bg_*.png` in that same folder - Requires `KIE_API_KEY` in `~/.claude/.env` for background image generation - Requires `ANTHROPIC_API_KEY` in `~/.claude/.env` for slide generation (Claude Opus 5). Falls back to `OPENAI_API_KEY` with gpt-5-mini if no Anthropic key is set. - Carousels save as local JSON in `~/carousel-studio/carousels/` — no database involved - **Export location is configurable.** Carousel Studio is a standalone app and defaults to writing into its own `exports/` folder. To have exports land in the content repo instead, set this in `~/carousel-studio/settings.json`: ```json { "exportDir": "~/content/platform/carousels", "handle": "@tylerreed" } ``` The rest of this skill assumes that setting is in place. ## Carousel Storage (Two Locations) When creating carousel content, always save to **both** locations: ### 1. App Library — `~/carousel-studio/carousels/<id>.json` This is what the carousel maker app reads. JSON format with the carousel's slides, colors, and text: ```json { "id": "carousel_<timestamp>", "title": "Carousel Title", "platform": "instagram", "slides": [ { "id": "slide_0_<timestamp>", "type": "cover", "slideNumber": 1, "headline": "Main Headline", "emphasisLine": "Accent line in terra cotta", "bodyText": "Supporting text.", "bgColor": "#F5F0EB", "textColor": "#1B1B1B", "accentColor": "#E07355" } ] } ``` Slide types: `cover` (slide 1), `content` (slides 2-5, include `stepNumber`), `cta` (slide 6). ### 2. Content folder — `~/content/platform/carousels/<slug>/` This is where the copy, captions, and exported files live: ``` ~/content/platform/carousels/<slug>/ content.md # 6-slide copy (Cover/Pain/Solution/How/Results/CTA) captions.md # Instagram caption (5 hashtags) + LinkedIn caption (no hashtags) slide_1.png # Exported from app (after building) ... slide_7.png <slug>.pdf # Combined PDF for LinkedIn ``` ### Always create both at the same time When generating carousel content, save the app JSON **and** the content folder in the same step. This keeps the Library and the content archive in sync. ### Scheduling via Blotato - **Instagram**: upload slides 1-6 as a carousel (skip CTA slide 7) - **LinkedIn**: upload the PDF - **X/Twitter**: post as a 7-post thread (see below) - Captions at `~/content/platform/carousels/<slug>/captions.md` ## X/Twitter Thread Scheduling Carousels perform well on X as threads: slide 1 + punchy caption as the main tweet, slides 2-6 as numbered replies, then a Skool link as the final reply. ### Structure - **Main tweet**: slide_1.png + X-native caption (no hashtags, under 230 chars, punchy) - **Replies 2-6**: each slide image + text `"2/6"`, `"3/6"` ... `"6/6"` - **Final reply**: `"join us at skool.com/the-ai-agency — free templates and full community 👇"` ### Timing - 9 PM EDT = 01:00 UTC the next calendar day - e.g. May 6 at 9 PM EDT → `scheduledTime: "2026-05-07T01:00:00.000Z"` ### Upload pattern — use Python MCP client directly Blotato presigned URL tokens get corrupted when passed through bash heredocs or JSON strings. Always upload via the Python MCP client: ```python def upload_slide(session_id, carousel_id, slide_num): path = os.path.expanduser(f"~/content/platform/carousels/{carousel_id}/slide_{slide_num}.png") r = mcp_call(session_id, "tools/call", { "name": "blotato_create_presigned_upload_url", "arguments": {"filename": f"carousel_{carousel_id}_slide{slide_num}.png"} }) data = json.loads(r["result"]["content"][0]["text"]) presigned_url = data["presignedUrl"] # use for PUT upload public_url = data["publicUrl"] # use in post mediaUrls with open(path, "rb") as f: img_data = f.read() urllib.request.urlopen( urllib.request.Request(presigned_url, data=img_data, method="PUT", headers={"Content-Type": "image/png", "Content-Length": str(len(img_data))}), timeout=60 ) return slide_num, public_url ``` Upload all 6 slides in parallel with `ThreadPoolExecutor(max_workers=6)` for speed. ### Post creation ```python post_data = { "accountId": "<your-x-account-id>", # from blotato_list_accounts "platform": "twitter", "text": caption, # X-native, no hashtags, under 230 chars "mediaUrls": [slide_urls[1]], "scheduledTime": "2026-05-07T01:00:00.000Z", "additionalPosts": [ {"text": "2/6", "mediaUrls": [slide_urls[2]]}, {"text": "3/6", "mediaUrls": [slide_urls[3]]}, {"text": "4/6", "mediaUrls": [slide_urls[4]]}, {"text": "5/6", "mediaUrls": [slide_urls[5]]}, {"text": "6/6", "mediaUrls": [slide_urls[6]]}, {"text": "join us at skool.com/the-ai-agency — free templates and full community 👇", "mediaUrls": []} ] } ``` Reference script: `/tmp/schedule_x_carousels.py`
View on GitHub