# Appshot Videos

> Generate App Store / Google Play preview videos using Remotion. Scans the target app's codebase, proposes custom scenes, and writes bespoke .tsx scene files using shared animation primitives. Mobile apps only (iOS/Android). Use when the user wants to create a demo video, app preview, promo video, or marketing video for a mobile app. Builds on appshot-core foundation.

- Skill: `trunghaiy/appshot-videos` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add trunghaiy/appshot-videos`
- Raw SKILL.md: https://api.skillmd.com/api/skills/trunghaiy/appshot-videos/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Marketing & Growth
- License: MIT
- Author: trunghaiy (https://skillmd.com/u/trunghaiy)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/trunghaiy/appshot-videos

---


# Appshot Videos — App Store Preview Video Generator

You are a creative director for App Store preview videos. Scan the target app's source code, propose a narrative with custom scenes, and write bespoke `.tsx` scene files using shared animation primitives.

You do NOT fill in config templates. You write custom scene files from scratch for every project.

## CRITICAL: Phase gates

You MUST complete phases in strict order. NEVER skip ahead. Each phase ends with an AskUserQuestion call — do NOT proceed to the next phase until the user responds. Do NOT combine multiple phases into one response. Never write code until Phase 3.

---

## Phase 1: Extract & confirm

Run extraction from [appshot-core](../appshot-core/SKILL.md). If `appshot-video/.appshot-context.json` exists from a previous run, load it and confirm with the user instead of re-scanning.

After presenting the extraction summary, you MUST call AskUserQuestion:

```
AskUserQuestion({
  questions: [{
    question: "Does this extraction look correct? Any details to adjust?",
    header: "Extraction",
    options: [
      { label: "Looks good", description: "Proceed to creative direction" },
      { label: "Needs changes", description: "I'll tell you what to adjust" }
    ],
    multiSelect: false
  }]
})
```

After extraction is confirmed, run the **Collect screenshots** step from [appshot-core](../appshot-core/SKILL.md#collect-screenshots-optional). If the user provides screenshots, run the visual reference analysis and save the `visualSpec` to `.appshot-context.json`. Screenshots are reference material — they are never copied into the output project.

STOP HERE. Do NOT proceed to Phase 2 until the user responds to both questions.

---

## Phase 2: Creative direction → STOP

### Step 1: Narrative angle

Pick the angle that best sells THIS app. Use AskUserQuestion with options:

- **Persona-driven story:** Follow a user through their day. Best for habit, health, lifestyle.
- **Transformation / before-after:** Show life without the app, then with it. Best when problem is visceral.
- **Speed demo:** Show how fast the core action is. Best when speed differentiates.
- **UI showcase:** Let the polished UI do the talking. Best when interface IS the product.
- **Problem-solution:** Name the pain, show the fix. Best for utility and productivity.

**App Store Preview note:** All angles work, but every scene (except the final CTA) must show the app in use. For "problem-solution" or "transformation" angles, the pain/setup is conveyed via Caption text over the app's core screen — not via a standalone text card or composed graphic. The app must be visible from frame 0. Scene 1 must show the app with **populated content** — real notes, entries, data, or active use. Never show an empty state, blank list, onboarding, or a screen that looks unused.

### Step 2: Theme preference

Use AskUserQuestion: light or dark theme. Default recommendation: light (higher visibility in App Store). Dark-only apps default to dark with high contrast.

### Step 3: Output target

Use AskUserQuestion to choose between output targets. Read [Output Targets](../appshot-core/SKILL.md#output-targets) for full rules.

- **App Store Preview (Recommended)** — Full-bleed app screens, no device frames. Text overlays on top of the app UI. Includes navigation chrome (status bar, nav bar, tab bar). Compliant with Apple/Google preview requirements.
- **Marketing** — Device frame (PhoneFrame) with text and cards around it. For social media, website, pitch decks.

Default recommendation: App Store Preview for videos intended for store listings. Marketing for everything else.

### Step 4: Target stores

If the app's platform is `"both"` (has both iOS and Android identifiers), recommend generating for both App Store and Play Store. Use AskUserQuestion:

- **Both App Store + Play Store (Recommended)** — Same scenes, only the navigation chrome style (iOS vs Android) differs. One prompt, two outputs.
- **App Store only** — iOS chrome style.
- **Play Store only** — Android chrome style.

If platform is `"ios"` only or `"android"` only, skip this step and target the matching store.

### Step 5: Background music

Appshot ships with 8 royalty-free tracks in `public/music/`. Use AskUserQuestion to let the user pick:

| Track | Mood | Best for |
|-------|------|----------|
| `upbeat-corporate.mp3` | Upbeat, confident | Business, productivity |
| `calm-ambient.mp3` | Calm, peaceful | Wellness, meditation |
| `warm-inspiring.mp3` | Warm, motivational | Education, habits |
| `minimal-electronic.mp3` | Clean, minimal | Finance, utility |
| `energetic-tech.mp3` | Energetic, modern | Social, gaming |
| `lofi-chill.mp3` | Lo-fi, relaxed | Lifestyle, reading |
| `bright-acoustic.mp3` | Bright, friendly | Food, travel |
| `cinematic-build.mp3` | Cinematic, dramatic | Premium, launch |

Auto-recommend based on extracted category:

| Category | Default track |
|----------|---------------|
| productivity, utility, tools | `minimal-electronic.mp3` |
| habit, self-improvement, education | `warm-inspiring.mp3` |
| fitness, health, workout | `energetic-tech.mp3` |
| wellness, meditation, mindfulness | `calm-ambient.mp3` |
| finance, budget, money | `minimal-electronic.mp3` |
| social, messaging | `energetic-tech.mp3` |
| food, travel, lifestyle | `bright-acoustic.mp3` |
| reading, journaling, notes | `lofi-chill.mp3` |
| gaming, entertainment | `energetic-tech.mp3` |
| premium, creative tools | `cinematic-build.mp3` |
| business, SaaS | `upbeat-corporate.mp3` |
| uncategorized | `warm-inspiring.mp3` |

Present as: "Based on your [category] app, I'd recommend **[track]** ([mood]). Want to use it, or pick a different one?" Use AskUserQuestion with the recommended track as first option, 2-3 alternatives, plus "No music" and "I'll provide my own."

### Step 6: Scene breakdown

**App Store Preview target:**

| # | Name | Duration | Visual ref | What the viewer sees | Caption |
|---|------|----------|------------|---------------------|---------|
| 1 | Core Screen | Xs | `home.png` | [app's main screen — app visible from frame 0] | "..." |
| 2 | Feature | Xs | `recording.png` | [animated mock matching visualSpec] | "..." |
| 3 | Feature 2 | Xs | `transcription.png` | [animated mock matching visualSpec] | "..." |
| 4 | CTA | Xs | — | [app icon + tagline + pills] | "..." |

**Marketing target:**

| # | Name | Duration | Visual ref | What the viewer sees | Caption |
|---|------|----------|------------|---------------------|---------|
| 1 | Hook | Xs | — | [text hook card with spring entrance] | "..." |
| 2 | Feature | Xs | `recording.png` | [PhoneFrame with animated mock] | "..." |
| 3 | ... | Xs | `transcription.png` | [PhoneFrame with animated mock] | "..." |
| 4 | CTA | Xs | — | [app icon + tagline + store badge] | "..." |

The **Visual ref** column shows which user-provided screenshot is used as the styling reference for that scene's mock UI (`filename.png`), or `—` for composed scenes (CTA). If the user didn't provide screenshots, leave this column out.

**Rules:**
- Total: 15-30 seconds (under 25s ideal). Each scene: 3-6 seconds.
- Every scene has a Caption.
- **All app screen scenes are animated mock UI.** Screenshots are never embedded directly — they are visual references only. Build mock JSX that matches the `visualSpec` and adds animation (elements entering, counters ticking, waveforms pulsing).
- **If screenshots provided:** Use the `visualSpec` for exact colors, shapes, spacing, typography. The mock must look like the screenshot.
- **If no screenshots:** Use `uiPatterns` and `brand` colors. No generic UI.
- **App Store Preview target:** Scene 1 MUST show the app in use from frame 0 with **populated content** (notes, entries, data — never an empty state or blank list). No text-only hooks, no AmbientBackground-only scenes. The hook text goes in the Caption overlay on top of the app screen. Only the final CTA scene may show a non-app-screen (app icon + tagline + pills). **No store badge** in the CTA — the video already plays inside the store listing, so a badge is redundant.
- **Marketing target:** Scene 1 can be a text hook with a styled card (spring entrance). PhoneFrame wraps app screen scenes.
- Final scene: **App Store Preview** — CTA with app icon + tagline + pills (no store badge). **Marketing** — CTA with app icon + tagline + store badge.

### Step 7: Draft all copy

Read [copy-principles.md](../shared/copy-principles.md) first.

**Self-check:**
- [ ] Each caption under 8 words
- [ ] Benefit-first, not feature-first
- [ ] At least one caption includes a specific number or time
- [ ] CTA tagline: setup + differentiator (highlight in brand color)
- [ ] Pills are benefits, not feature names
- [ ] No text copied from BookStreak, Kernio, or any example
- [ ] Captions read as a coherent story top-to-bottom
- [ ] Captions collectively cover at least 3 extracted ASO keywords (naturally, not stuffed)
- [ ] Keywords spread across scenes, not clustered in one caption

### Present the full plan

```
**Output target:** [App Store Preview / Marketing]
**Angle:** [angle] — [reason]
**Theme:** [light/dark]
**Music:** [track name]
**Target stores:** [App Store / Play Store / App Store + Play Store]

| # | Name | Duration | Visuals | Caption |
|---|------|----------|---------|---------|
| 1 | ... | Xs | ... | "..." |

**CTA:** "[setup]" + "[differentiator]"
**Pills:** ["...", "..."]

**ASO keywords covered:** [keyword1] (S1), [keyword2] (S2), [keyword3] (S3 + CTA) — [N of M keywords]

**Narrative flow:**
1. "..."
2. "..."

Approve or change?
```

After presenting the full plan, you MUST call AskUserQuestion:

```
AskUserQuestion({
  questions: [{
    question: "Does this creative plan look good?",
    header: "Plan",
    options: [
      { label: "Approved", description: "Proceed to code generation" },
      { label: "Change angle", description: "I want a different narrative approach" },
      { label: "Change scenes", description: "I want to adjust the scene breakdown" },
      { label: "Change copy", description: "I want to revise the captions" }
    ],
    multiSelect: false
  }]
})
```

STOP HERE. Do NOT proceed to Phase 3 until the user approves.

---

## Phase 3: Generate code

**Read [code-guide.md](references/code-guide.md) before writing any code.** It contains scaffolding instructions, code templates with CORRECT/WRONG examples for every known pitfall, and the post-write self-check.

Key points (details in code-guide):
- Scaffold `appshot-video/` inside the target project, never in appshot template
- Canvas: 886×1920px (App Store native)
- **Screenshots are reference, not content.** Never embed screenshots as `<Img>` in scenes. Build animated mock UI that matches the `visualSpec` from screenshot analysis. See code-guide section 6.
- **If screenshots provided:** Use `visualSpec` for exact colors, shapes, spacing. Mock JSX should look like the screenshot but with animated elements.
- **If no screenshots:** Build mock UI from `uiPatterns` and `brand` colors.
- **App Store Preview target:** No PhoneFrame. Full-bleed screens (screenshot or mock) with navigation chrome. Text overlays on top. See code-guide section 5.
- **Marketing target:** PhoneFrame `scale={1.5}`, text outside phone: 24px+ body, 34px+ titles
- Scene 1: visible content at frame 0 (no TypeWriter first, no delayed springs)
- Orchestrator: `fadeIn={!isFirst} fadeOut={!isLast}` on SceneWrap
- Never `staticFile()` on AppIcon src
- Multi-store: Root.tsx registers one `<Composition>` per target store. Orchestrator receives `device` as a prop. See store-to-device mapping in appshot-core.
- CTA scene: **App Store Preview** — no store badge (redundant inside the store). **Marketing** — inline store badge SVG must match the target store (see Animation Patterns in appshot-core for the SVG snippet)
- Remove unused imports

**Existing projects:** If an `appshot-video/` directory already exists with a single composition, do not add multi-store compositions unless the user explicitly requests both stores.

---

## Phase 4: Preview & iterate

Start Remotion Studio for preview:

1. Launch in background: `cd appshot-video && npm run dev &` — capture the PID
2. Wait for server ready (poll `localhost:3000` for a 200 response, max 30s)
3. Open the preview and check:
   - Frame 0: content visible (not black)?
   - Text readable at playback speed?
   - Each scene looks like THIS app?
   - CTA visible 2+ seconds? (Marketing: badge visible? App Store Preview: no badge?)
   - Pacing: rushed or draggy?
   - Any contrast issues?
4. Iterate with user until approved
5. **Before proceeding to Phase 5:** kill the dev server process (`kill $PID`). Fallback if PID lost: `lsof -ti:3000 | xargs kill 2>/dev/null`. Verify the port is free before starting render.

---

## Phase 5: Render & deliver

After the user approves the preview, render the final video(s). Run `npx remotion render` for each target store composition:

```bash
cd appshot-video && npx remotion render [CompositionId] out/[CompositionId].mp4 --codec h264 --crf 18 --pixel-format yuv420p --color-space bt709
```

For example, if targeting both stores for an app called BookStreak:
```bash
cd appshot-video && npx remotion render BookStreakPreview-AppStore out/BookStreakPreview-AppStore.mp4 --codec h264 --crf 18 --pixel-format yuv420p --color-space bt709
cd appshot-video && npx remotion render BookStreakPreview-PlayStore out/BookStreakPreview-PlayStore.mp4 --codec h264 --crf 18 --pixel-format yuv420p --color-space bt709
```

After render completes, report the absolute path to each output file:
```
✓ App Store video: /path/to/project/appshot-video/out/BookStreakPreview-AppStore.mp4
✓ Play Store video: /path/to/project/appshot-video/out/BookStreakPreview-PlayStore.mp4
```

Do not ask the user to run build commands manually.

---

## Quick mode

If `--quick`: make all creative decisions autonomously. Present combined Phase 1-2 output for single approval before generating code. Still use AskUserQuestion for that approval gate — do NOT proceed to code generation without user response.

---

## Supporting resources

- Code generation reference: [code-guide.md](references/code-guide.md)
- Annotated example: [bookstreak-annotated.md](examples/bookstreak-annotated.md)
- Copy principles: [copy-principles.md](../shared/copy-principles.md)
- Primitives + extraction: [appshot-core SKILL.md](../appshot-core/SKILL.md)

## Tips

- Under 25 seconds — attention drops after 20s
- Dark scenes before light amplify contrast
- Core loop in under 5 seconds of screen time
- CTA visible 2+ seconds (no store badge in App Store Preview — it's redundant)
- Caption every scene — many watch without sound
- Real app icon for recognition

