| name | socials-app-carousel-maker |
|---|---|
| version | 1.0.0 |
| description | Automate TikTok AND Instagram carousel marketing for any mobile app. Researches competitors, generates AI images, adds text overlays, posts via Post Bridge to TikTok + Instagram simultaneously, tracks analytics, and iterates on what works. Use when setting up TikTok/Instagram marketing automation, creating slideshow/carousel posts, analyzing post performance, optimizing app marketing funnels, or when a user mentions TikTok growth, Instagram Reels, carousel ads, or social media marketing for their app. Covers competitor research, image generation, text overlays, dual-platform posting (Post Bridge API), store analytics tracking (App Store + Google Play via custom API), conversion tracking, and a full feedback loop that adjusts hooks and CTAs based on views vs conversions. Includes full node-canvas text overlay implementation (Larry's exact technique), diagnostic framework for view vs conversion analysis, hook evolution tracking, CTA rotation, and Instagram-specific optimization. |
Automate your entire social media slideshow/carousel pipeline: generate → overlay → post to TikTok + Instagram simultaneously → track → iterate.
Proven results: 7 million views on the viral X article, 1M+ TikTok views, $670/month MRR — all from an AI agent running on an old gaming PC.
This skill does NOT bundle any dependencies. Your AI agent will research and install these based on your setup.
- Node.js (v18+) — all scripts run on Node.
- node-canvas (
npm install canvas) — adds text overlays to slide images. Native module, may need build tools (Python, make, C++ compiler). - Post Bridge — handles posting to TikTok AND Instagram (and 20+ other platforms) simultaneously via one API call. Sign up at post-bridge.com. Store your key as
POST_BRIDGE_API_KEYin the workspace.env. - Store App API — custom API (in
store-app-api/) running on another VPS. Fetches and stores purchase/download/impression stats from App Store Connect and Google Play.
- OpenAI —
gpt-image-1.5(ALWAYS 1.5, NEVER 1). Best for photorealistic images. Strongly recommended. - Stability AI — Stable Diffusion XL. Good for stylized images.
- Replicate — any open-source model (Flux, SDXL, etc.). Most flexible.
- Local — bring your own images, no API needed.
When this skill is first loaded, IMMEDIATELY start a conversation with the user. Don't dump a checklist — talk to them like a human marketing partner. Ask one or two things at a time. React to what they say.
Use scripts/onboarding.js --validate at the end to confirm the config is complete.
Before anything else, check if the user has an active TikTok account. If it's fresh, they MUST warm it up or TikTok will throttle reach from day one.
"Quick question before we dive in — do you already have a TikTok account you've been posting on, or is it new? If new, we need to warm it up first."
If new, walk them through 7-14 days of warmup:
- Scroll For You page naturally — watch some fully, skip others halfway
- Like sparingly (1 in 10) — not everything
- Follow accounts in their niche
- Leave a few genuine comments per session
- Post 1-2 casual non-promotional videos
Signal to look for: FYP is dominated by niche content → ready to post.
"Accounts that skip warmup get 80-90% less reach on their first posts. Two weeks up front saves months of wasted content."
If the account is already active, skip to Phase 1.
Start casual:
"Hey! Let's get your marketing set up. Tell me about your app — what's it called, what does it do?"
Follow the thread naturally:
- What it does → ask who it's for
- The audience → ask about the pain point it solves
- The pain point → ask what makes it stand out
- Get App Store + Google Play links naturally
- Determine category: home/beauty/fitness/productivity/food/other
"Is this a mobile app? Got both iOS and Android versions?"
If yes to both — great, the Store App API tracks both stores.
Store everything in tiktok-marketing/app-profile.json.
"Before we create anything, I want to research what competitors are doing on TikTok and Instagram — what's getting views, what hooks they use. Can I use the browser to look around?"
Wait for permission. Then:
- Search TikTok AND Instagram for the app's niche (3-5 competitors each)
- Analyse top-performing content: hooks, formats, view counts, CTAs, music
- Check App Store / Google Play for competitor apps
- Find the gap — what nobody is doing in the niche
- Save to
tiktok-marketing/competitor-research.json
Share findings conversationally — don't dump raw JSON.
See references/competitor-research.md for the full research process.
"We're going to do slideshows/carousels — same 6-image set posted to TikTok as a slideshow and to Instagram as a carousel reel simultaneously, one upload. TikTok data shows slideshows get 2.9x more comments and 2.6x more shares than video. Easier to generate consistently too."
Image generation:
"I'd strongly recommend OpenAI's gpt-image-1.5. It produces images that look like real iPhone photos — the kind people stop scrolling for. It's what's proven to work."
gpt-image-1.5 — NEVER gpt-image-1. Quality difference is massive. One setting = difference between 1K and 100K views.
Work through the image style with them (see references/slide-structure.md). Don't just accept their first answer — dig in:
"Now let's figure out what these images should actually look like. Do you want them to look like real photos someone took on their phone, or more like polished graphics or illustrations?"
Then dig deeper based on their answer:
- What's the subject? "What are we actually showing? Rooms? Faces? Products? Before/after comparisons?"
- What vibe? "Cozy and warm? Clean and minimal? Luxurious? Think about what your audience relates to or aspires to."
- Consistency: "Should all 6 slides look like the same place or person? If yes — I need to lock down specific details so each slide doesn't look totally different."
- Must-have elements? "Anything that HAS to be in every image? A specific product? Certain furniture? A pet?"
Build the base prompt WITH them. A good base prompt looks like:
iPhone photo of a [specific room/scene], [specific style], [specific details].
Realistic lighting, natural colors, taken on iPhone 15 Pro.
No text, no watermarks, no logos.
[Consistency anchors: "same window on left wall", "same grey sofa", "wooden coffee table in center"]
Key prompt rules (explain as they come up, don't lecture):
- "iPhone photo" + "realistic lighting" = looks real, not AI-generated
- Lock architecture/layout in EVERY slide prompt or each slide looks like a different place
- Include everyday objects (mugs, remotes, magazines) for a lived-in feel
- Portrait orientation (1024x1536) always — fills TikTok AND Instagram
- Extremely specific > vague ("small galley kitchen with white cabinets and a window above the sink" > "a kitchen")
NEVER use generic prompts like "a nice living room" — they produce generic images that get scrolled past.
Save the agreed prompt to config.json as imageGen.basePrompt.
Optional Batch API for 50% cheaper generation:
"OpenAI's Batch API submits jobs overnight — same quality, half the cost. Want to set that up for scheduled posts?"
Post Bridge posts to TikTok AND Instagram in a single API call. One upload, two platforms.
"Post Bridge is what posts to both TikTok and Instagram simultaneously. One image set, one API call — it handles both. Let me walk you through the setup."
- Sign up at post-bridge.com
- Connect TikTok — Integrations → Add TikTok → Authorize
- Connect Instagram — same flow, connect your Instagram account
- Enable API → Settings → API → copy your key
- Add to
.env:POST_BRIDGE_API_KEY=pb_live_xxxxx - Run
GET /v1/social-accountsto get account IDs for TikTok and Instagram - Save both account IDs to config
The dual-platform workflow:
- Both platforms get the same 6 images — the carousel translates perfectly to both formats
- TikTok: posted as draft (
draft: true) → user adds trending sound manually before publishing - Instagram: posted directly as a carousel (or trial reel if 1000+ followers)
- Cross-posting = same effort, double the algorithmic surface area
"One important thing — TikTok posts land as drafts in your TikTok inbox, not published directly. Before each one, add a trending sound from TikTok's library. Takes 30 seconds and is the single biggest factor in TikTok reach. Instagram posts go live directly."
Don't move on until Post Bridge is connected and GET /v1/social-accounts returns both accounts.
This is where the skill becomes genuinely intelligent. The Store App API (in store-app-api/) runs on your VPS and collects purchase, download, and impression data from both App Store Connect and Google Play.
Explain WHY it matters — this is the most important integration in the entire skill:
"So right now with Post Bridge, I can track which posts get views, likes, and comments. That's the top of the funnel. But views alone don't pay the bills — I need to know which posts actually drive paying subscribers."
"The Store App API is where the skill goes from 'content automation' to 'intelligent marketing system.' It syncs purchase data, download stats, and page conversion rates from both the App Store and Google Play every 6 hours. When I combine post analytics from Post Bridge with real purchase data from the store, I can make genuinely intelligent decisions:"
"If a post gets 50K views but zero conversions, I know the hook is great but the CTA or app page needs work. If a post gets 2K views but 5 paid subscribers, I know the content converts amazingly — just needs a better hook."
"Without the Store API, I'm optimizing for vanity metrics. With it, I'm optimizing for revenue. The difference is massive. A post with 200K views and zero conversions is worthless. A post with 5K views and 10 paid subscribers is gold. You can only tell the difference with purchase data connected."
Walk them through setup:
-
Deploy the Store App API on the VPS:
# On your VPS git clone / scp the store-app-api folder cd store-app-api # Fill in .env: APP_STORE_VENDOR_NUMBER and generate API_KEY docker-compose up -d
The API generates an
API_KEYon first run if none is set — note it down. -
Confirm it's reachable:
curl http://YOUR_VPS_IP:3400/health # → {"status":"ok"} -
Add to marketing config:
"storeApi": { "enabled": true, "baseUrl": "http://YOUR_VPS_IP:3400", "apiKey": "your-generated-api-key" }
-
Trigger an initial sync:
curl -X POST http://YOUR_VPS_IP:3400/api/sync?days=30 \ -H "Authorization: Bearer YOUR_API_KEY"
What this unlocks:
- Which posts drive actual downloads (not just views)
- Which posts drive actual purchases (subscriptions, IAP)
- App Store + Play Store impression → conversion funnel
- MRR estimate based on tracked purchases
Without Store API: optimize for views (vanity). With Store API: optimize for downloads and revenue (what matters).
See references/store-api-integration.md for full API docs.
Using competitor research + app profile, build the first week's strategy:
"Based on what I found and your app, here's my plan for the first week..."
Present:
- 3-5 hook ideas tailored to niche + competitor gaps
- Posting schedule (default: 7:30am, 4:30pm, 9pm — their timezone)
- Which hook categories to test first
- Instagram-specific note: carousels on Instagram get saved more than video — optimize slide 6 CTA for saves ("Save this for later" often outperforms "Link in bio" on Instagram)
Save to tiktok-marketing/strategy.json.
Set up a daily cron that runs before the first post (7:00 AM, user's timezone):
Task: node scripts/daily-report.js --config tiktok-marketing/config.json --days 3
Output: tiktok-marketing/reports/YYYY-MM-DD.md + summary to user
The report cross-references:
- Post analytics from Post Bridge (
GET /v1/posts/<id>) - Download + purchase spikes from Store App API (
GET /api/stats/attribution?days=3)
See references/analytics-loop.md for the full feedback loop.
Config saved to tiktok-marketing/config.json:
{
"app": {
"name": "AppName",
"description": "What it does",
"audience": "Who it's for",
"problem": "Pain point it solves",
"differentiator": "What makes it unique",
"appStoreUrl": "https://apps.apple.com/...",
"googlePlayUrl": "https://play.google.com/...",
"category": "home|beauty|fitness|productivity|food|other",
"isMobileApp": true
},
"imageGen": {
"provider": "openai",
"apiKey": "sk-...",
"model": "gpt-image-1.5",
"basePrompt": "YOUR LOCKED BASE PROMPT HERE"
},
"postbridge": {
"apiKey": "pb_live_...",
"accounts": {
"tiktok": "account_id_here",
"instagram": "account_id_here"
}
},
"storeApi": {
"enabled": true,
"baseUrl": "http://YOUR_VPS_IP:3400",
"apiKey": "your-store-api-key"
},
"posting": {
"tiktokDraft": true,
"instagramDraft": true,
"schedule": ["07:30", "16:30", "21:00"]
},
"competitors": "tiktok-marketing/competitor-research.json",
"strategy": "tiktok-marketing/strategy.json"
}First post is a TEST — not a publish:
"Let's generate the first 6 slides and look at them together. Goal is to dial in the image style BEFORE we start posting. If they look off, we tweak and retry."
Iterate prompt until images look right (typically 2-5 rounds). Only start the real schedule once the style is locked. See references/slide-structure.md for the formula.
node scripts/generate-slides.js \
--config tiktok-marketing/config.json \
--output tiktok-marketing/posts/YYYY-MM-DD-HHmm/ \
--prompts prompts.jsonCritical rules:
- ALWAYS portrait (1024x1536) — fills TikTok AND Instagram feed
- ALL 6 slides share the same base description (only style changes)
- Lock key elements across all slides (architecture, face, camera angle)
See references/slide-structure.md for the 6-slide formula.
This step uses node-canvas to render text directly onto your slide images. This is how Larry produces slides that have hit 1M+ views on TikTok — the text sizing, positioning, and styling are dialled in from hundreds of posts.
Before you can add text overlays, prompt the user to install node-canvas:
"To add text overlays to the slides, I need a library called node-canvas. It renders text directly onto images with full control over sizing, positioning, and styling — this is what Larry uses for his viral TikTok slides.
Can you run this in your terminal?"
npm install canvas"If that fails, it's because node-canvas needs some system libraries. Here's what to install first:"
macOS:
brew install pkg-config cairo pango libpng jpeg giflib librsvg npm install canvasUbuntu/Debian:
sudo apt-get install build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev npm install canvasWindows:
# node-canvas auto-downloads prebuilt binaries on Windows npm install canvas"Once installed, I can handle everything else — generating the overlays, sizing the text, positioning it perfectly. You won't need to touch this again."
Don't skip this step. Without node-canvas, text overlays won't work. If installation fails, help them troubleshoot — it's usually a missing system library. Once it's installed once, it stays.
- Load the raw slide image into a node-canvas
- Configure text settings based on the text length for that specific slide
- Draw the text with white fill and thick black outline
- Review the output — check sizing, positioning, readability
- Adjust and re-render if anything looks off
- Save the final image once it looks right
Exact code used:
const { createCanvas, loadImage } = require('canvas');
const fs = require('fs');
async function addOverlay(imagePath, text, outputPath) {
const img = await loadImage(imagePath);
const canvas = createCanvas(img.width, img.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
// ─── Adjust font size based on text length ───
const wordCount = text.split(/\s+/).length;
let fontSizePercent;
if (wordCount <= 5) fontSizePercent = 0.075; // Short: 75px on 1024w
else if (wordCount <= 12) fontSizePercent = 0.065; // Medium: 66px
else fontSizePercent = 0.050; // Long: 51px
const fontSize = Math.round(img.width * fontSizePercent);
const outlineWidth = Math.round(fontSize * 0.15);
const maxWidth = img.width * 0.75;
const lineHeight = fontSize * 1.3;
ctx.font = `bold ${fontSize}px Arial`;
ctx.textAlign = 'center';
ctx.textBaseline = 'top';
// ─── Word wrap ───
const lines = [];
const manualLines = text.split('\n');
for (const ml of manualLines) {
const words = ml.trim().split(/\s+/);
let current = '';
for (const word of words) {
const test = current ? `${current} ${word}` : word;
if (ctx.measureText(test).width <= maxWidth) {
current = test;
} else {
if (current) lines.push(current);
current = word;
}
}
if (current) lines.push(current);
}
// ─── Position: centered at ~28% from top ───
const totalHeight = lines.length * lineHeight;
const startY = (img.height * 0.28) - (totalHeight / 2);
const x = img.width / 2;
// ─── Draw each line ───
for (let i = 0; i < lines.length; i++) {
const y = startY + (i * lineHeight);
// Black outline
ctx.strokeStyle = '#000000';
ctx.lineWidth = outlineWidth;
ctx.lineJoin = 'round';
ctx.miterLimit = 2;
ctx.strokeText(lines[i], x, y);
// White fill
ctx.fillStyle = '#FFFFFF';
ctx.fillText(lines[i], x, y);
}
fs.writeFileSync(outputPath, canvas.toBuffer('image/png'));
}Key details that make slides look professional:
- Dynamic font sizing — short text gets bigger (75px), long text gets smaller (51px). Every slide is optimized individually.
- Word wrap — respects manual
\nbreaks but also auto-wraps lines that exceed 75% width. No squashing. - Centered at 28% from top — text block is vertically centered around this point, not pinned to it. Stays in the safe zone regardless of line count.
- Thick outline — 15% of font size. Makes text readable on ANY background — dark room, bright white wall, cluttered scene.
- Manual line breaks preferred — use
\nin your text for control. Keep lines to 4-6 words.
The difference between OK slides and viral slides is in these details. Slides consistently hit 50K-150K+ views because the text is sized right, positioned right, and readable at a glance while scrolling.
node scripts/add-text-overlay.js \
--dir tiktok-marketing/posts/YYYY-MM-DD-HHmm/ \
--texts texts.jsontexts.json — EXACTLY 6 strings, ALL must be non-empty (an empty string will be rejected):
[
"I showed my landlord\nwhat AI thinks our\nkitchen should look like",
"She said you can't\nchange anything\nchallenge accepted",
"So I downloaded\nthis app and\ntook one photo",
"Wait... is this\nactually the same\nkitchen??",
"Okay I'm literally\nobsessed with\nthis one",
"AppName showed me\nwhat's possible\nlink in bio"
]Good (manual breaks, 4-6 words per line):
"I showed my landlord\nwhat AI thinks our\nkitchen should look like"Bad (no breaks — auto-wraps but looks worse):
"I showed my landlord what AI thinks our kitchen should look like"Text rules (what makes slides go viral):
- Manual
\nbreaks — 4-6 words per line MAX, control the rhythm - REACTIONS not labels — "Wait this is actually nice??" not "Modern style"
- Read it out loud — each line should feel like a natural pause
- No emoji — canvas can't render them, they'll show as blank
- Safe zones: no text in bottom 20% (TikTok controls) or top 10% (status bar)
- Font auto-sizes: short text = bigger, long text = smaller
node scripts/post-carousel.js \
--config tiktok-marketing/config.json \
--dir tiktok-marketing/posts/YYYY-MM-DD-HHmm/ \
--caption "caption text with #hashtags" \
--tiktok-title "Title for TikTok"This uploads the 6 slides once and creates a single Post Bridge post that goes to both TikTok (as draft) and Instagram in one API call.
The script saves the returned Post Bridge post ID (postBridgeId) to tiktok-marketing/posts/YYYY-MM-DD-HHmm/post-meta.json. This is required for analytics tracking — don't skip it.
Caption strategy by platform:
- Shared caption: Long storytelling format (3x more engagement). Hook → Problem → Discovery → Result → CTA + max 5 hashtags.
- Instagram-specific: include "Save this 🔖" or "Save for later" — Instagram's algorithm rewards saves heavily. Carousels that get saved get pushed to Explore.
- TikTok-specific: Add trending sound BEFORE publishing from your TikTok drafts inbox.
Posts go to your TikTok inbox as drafts, NOT published directly. This is intentional and critical:
- Music is everything on TikTok. Trending sounds massively boost reach. The algorithm favours posts using popular audio. An API can't pick the right trending sound — you need to browse TikTok's sound library and pick what's hot RIGHT NOW in your niche.
- You add the music manually, then publish from your TikTok inbox. Takes 30 seconds per post.
- Posts without music get buried. Silent slideshows look like ads and get skipped. A trending sound makes your content feel native.
- Creative control. You can preview the final slideshow with music before it goes live. If something looks off, fix it before publishing.
This is the workflow that helped us hit 1M+ TikTok views and $670/month MRR. Don't skip the music step.
Tell the user during onboarding: "Posts will land in your TikTok inbox as drafts. Before publishing each one, add a trending sound from TikTok's library — the single biggest factor in reach. 30 seconds per post. Makes a massive difference."
- Open TikTok app → Drafts → find the slideshow
- Tap "Add sound" → browse trending sounds in your niche
- Pick something popular with high use count
- Preview with sound → Publish
This takes 30 seconds per post and is the single biggest factor in TikTok reach.
When post-carousel.js runs, it stores the postBridgeId in post-meta.json alongside the publish date. The analytics script reads this to track post performance:
node scripts/check-analytics.js --config tiktok-marketing/config.json --days 3The script:
- Reads all
post-meta.jsonfiles from the last N days - For each, calls
GET /v1/posts/<postBridgeId>to retrieve current metrics - Stores views, likes, comments, shares, and (Instagram) saves per post
- Cross-references with Store App API data for that date window
postBridgeId is stored at creation time — no re-linking required — but TikTok's internal indexing takes time to reflect actual view counts.
Instagram analytics are available immediately after posting. saves is the key metric to watch for Explore push.
The daily cron handles all of this automatically. It runs at 7:00 AM, checks posts from the last 3 days (all well past the delay window), and generates the full report.
This is what separates "posting carousels" from "running a marketing machine." Every morning at 7:00 AM, the daily cron runs and generates a report crossing:
- Post Bridge → per-post metrics: views, likes, comments, shares, saves per platform
- Store App API →
/api/stats/attribution?days=3— download and purchase spikes per day
Combined, the agent can make intelligent decisions about what to do next — not guessing, not vibes, actual data-driven optimization.
This is the core intelligence. Two axes: views (are people seeing it?) and conversions (are people paying?).
🟢 High views + High conversions → SCALE IT
- This is working. Make 3 variations of the winning hook immediately
- Test different posting times to find the sweet spot
- Cross-post to more platforms for extra reach
- Don't change anything about the CTA — it's converting
🟡 High views + Low conversions → FIX THE CTA
- The hook is doing its job — people are watching. But they're not downloading/subscribing
- Try different CTAs on slide 6 (direct vs subtle, "download" vs "search on App Store")
- Check if the app landing page matches the promise in the slideshow
- Test different caption structures — maybe the CTA is buried
- The hook is gold — don't touch it. Fix everything downstream
🟡 Low views + High conversions → FIX THE HOOKS
- The people who DO see it are converting — the content and CTA are great
- But not enough people are seeing it, so the hook/thumbnail isn't stopping the scroll
- Test radically different hooks (person+conflict, POV, listicle, mistakes format)
- Try different posting times and different slide 1 images
- Keep the CTA and content structure identical — just change the hook
🔴 Low views + Low conversions → FULL RESET
- Neither the hook nor the conversion path is working
- Try a completely different format or approach
- Research what's trending in the niche RIGHT NOW (use browser)
- Consider a different target audience angle
- Reference competitor research for what's working for others
🔴 High views + High downloads + Low purchases → APP ISSUE
- The marketing is working. People are watching AND downloading. But they're not paying.
- This is NOT a content problem — the app onboarding, paywall, or pricing needs fixing.
- Check: Is the paywall shown at the right time? Is the free experience too generous?
- Check: Does onboarding guide users to the "aha moment" before the paywall?
- This is a signal to pause posting and fix the app experience first
🟡 High views + Low downloads → CTA ISSUE
- People are watching but not downloading. The hooks work, the CTAs don't.
- Rotate through CTAs: "link in bio", "search on App Store", app name only, "free to try"
- Check the App Store page — does it match what the TikTok shows?
| Views | Downloads/Purchases | Action |
|---|---|---|
| 🟢 High | 🟢 High | SCALE — make 3 variations of the winning hook immediately |
| 🟡 High | 🔴 Low | FIX CTA — hook works, downstream is broken. Test new CTAs, check App Store page |
| 🟡 Low | 🟢 High | FIX HOOKS — content converts but needs more eyeballs. Try radically different hooks |
| 🔴 Low | 🔴 Low | FULL RESET — new format, new audience angle, new hook categories |
| 🔴 APP | Downloads high, subs=0 | APP ISSUE — marketing works but users aren't paying. Check onboarding/paywall |
Track in tiktok-marketing/hook-performance.json. The daily report updates this automatically.
{
"hooks": [
{
"postBridgeId": "pb_post_xxxxxxxx",
"text": "My boyfriend said our flat looks like a catalogue",
"app": "AppName",
"date": "2026-02-15",
"views": 45000,
"likes": 1200,
"comments": 45,
"shares": 89,
"saves": 320,
"conversions": 4,
"cta": "Download AppName — link in bio",
"lastChecked": "2026-02-16"
}
],
"ctas": [
{
"text": "Download [App] — link in bio",
"timesUsed": 5,
"totalViews": 120000,
"totalConversions": 8,
"conversionRate": 0.067
},
{
"text": "Search [App] on the App Store",
"timesUsed": 3,
"totalViews": 85000,
"totalConversions": 12,
"conversionRate": 0.141
}
],
"rules": {
"doubleDown": ["person-conflict-ai"],
"testing": ["listicle", "pov-format"],
"dropped": ["self-complaint", "price-comparison"]
}
}The daily report updates this automatically. Each post gets tagged with its hook text, CTA, view count, and attributed conversions. Over time, this builds a clear picture of which hook + CTA combinations actually drive revenue — not just views.
Decision rules:
- 50K+ views → DOUBLE DOWN — make 3 variations immediately
- 10K-50K → Good — keep in rotation
- 1K-10K → OK — try 1 more variation
- <1K twice → DROP — radically different approach
When views are good but conversions are low, cycle through CTAs:
- "Download [App] — link in bio"
- "[App] is free to try — link in bio"
- "I used [App] for this — link in bio"
- "Search [App] on the App Store"
- No explicit CTA (just app name visible)
Track which CTAs convert best per hook category. Tag every post with the CTA used so the data accumulates — conversionRate per CTA tells you which one actually drives downloads.
CTA rotation: When the report detects high views but low conversions, it automatically recommends rotating to a different CTA and tracks performance separately.
Instagram carousels behave differently from TikTok:
- Saves are the key metric on Instagram (not views) — a carousel with 500 saves will get pushed to Explore
- Comments on slide 2+ signal engagement depth — TikTok equivalent of watch time
- Shares drive reach more than likes
When diagnosing Instagram performance, prioritize saves > comments > likes > reach.
Optimal times (adjust for audience timezone):
- 7:30 AM — early scrollers
- 4:30 PM — afternoon break
- 9:00 PM — evening wind-down
3x/day minimum to both platforms. Both platform's algos evaluate content independently so the same post can perform differently on each.
See references/app-categories.md for category-specific slide prompts and hook formulas.
| Mistake | Fix |
|---|---|
| 1536x1024 (landscape) | Use 1024x1536 (portrait) — TikTok AND Instagram |
| Same hooks forever | Iterate weekly based on performance data |
| Only posting to TikTok | Instagram carousels get saved → Explore push. Free reach, same effort |
| No trending sound on TikTok | 30 sec before publishing = massive reach difference |
| Publishing TikTok directly via API | Always use draft mode — add sound manually in app |
| Not tracking saves on Instagram | Saves are Instagram's key engagement signal, not views |
spawnSync ETIMEDOUT |
Image gen takes 3-9 min for 6 slides — set 10min exec timeout |
Not storing postBridgeId after posting |
Always save to post-meta.json — required for daily analytics |
| Checking TikTok analytics too soon | Wait 1-2h after user publishes from drafts — TikTok indexing delay |
| Generic prompts ("a nice room") | Be extremely specific — generic = scrolled past |
| Font at 5% width | Use 6.5% (medium text) or 7.5% (short text) — readability at a glance |
| Text positioned at bottom | Center text block at ~28% from top — stays in safe zone |
| Different rooms/scenes per slide | Lock architecture in EVERY slide prompt |
| Labels not reactions | "Wait this is actually nice??" not "Modern minimalist" |
| Only tracking views | Connect Store App API — views without revenue = vanity metrics |
| No CTA rotation when conversions are low | Cycle through CTAs systematically and track each separately |
| Skipping the first test round | Always dial in image style BEFORE starting the posting schedule |