---
name: nawneet77-launch-film
title: launch film
kind: skill
version: 1.0.0
description: >
  Build a SaaS product launch video the way Cursor, Notion, Linear and
  Higgsfield build theirs — from the real product, in Remotion, cut to a music
  bar grid, with every UI surface rebuilt as a component (never a cropped
  screenshot) and every number coming from real data. Use when someone asks for
  a launch video, product film, feature reveal, promo, or "make a video like the
  Cursor/Higgsfield ones" for a web app they have the code for. Covers reference
  study, footage and data sourcing, the Remotion kit, scene grammar, the
  stem-based score, the anti-slop rules, QA by contact sheet, and the founder
updated: 2026-09-24
authored_by: nawneet77
author_url: https://github.com/nawneet77
source_url: https://github.com/nawneet77/launch-film
brought_by: SD
license: MIT
---

# launch-film

A method, a component kit and a set of hard rules for making a launch video that looks like it came
from a top product studio, using Claude Code + Remotion + ffmpeg. It was distilled from seventeen
reviewed cuts of one real launch film. The rules below are the ones that survived review.

Read this file fully before starting. Then read `references/grammar.md` and `references/anti-slop.md`.
Everything else is loaded on demand.

## What you will produce

- `out/<name>-vN.mp4` — 1920×1080, 60 fps, H.264 CRF 17, audio two-pass loudnormed to −14 LUFS / −1 dBTP.
- A Remotion project (`templates/remotion` is the starter) whose `Film.tsx` is a timeline on a **music bar grid**.
- A score arranged from separated stems that follows the scenes (`scripts/stemscore2.py`).
- Contact sheets in `qa/` proving every beat before you show it.
- A `README.md` log: one section per version, what changed and why. Versions are never overwritten.

## The workflow

Work in this order. Each phase has a gate. Do not skip the gate because the phase "looks done".

### Phase 0 — Study the references (30–45 min, do it every time)

Download 4–6 launch films the user admires (`yt-dlp` works for x.com). Make dense frame sheets
(`scripts/frame_sheet.sh <mp4> <fps>`) and read them frame by frame. Write down, per film:
cut count, average shot length, the grammar devices used, how UI is framed, how text appears,
how colour changes between beats, how the music is cut. `references/grammar.md` holds the
findings from Cursor Router, Cursor Automate, Notion AI and two Higgsfield films; add yours.

Gate: you can name the five devices you will borrow and the three you will not.

### Phase 1 — Source real material (never placeholders)

Order of preference, all of them real:

1. **The codebase.** Build demo routes with fixture data (`app/demo/*`), record them with
   Playwright (light and dark), and export 2× stills. Measure event times in the mp4 by frame
   difference, never trust the script's timestamps.
2. **The database, internal accounts only.** Saved ads, generated assets, product images, real
   briefs. Join on the internal-users table so no customer data is used. Download to `public/real/`,
   trim videos to ≤7 s at 540×960, downscale stills to ≤1400 px.
3. **The brand deck.** Crop the mark, read the palette and type, copy the taglines verbatim.
4. **Rebuild the UI as React components** from the design tokens (`references/real-data.md`).
   Screenshots are allowed only as *full windows* in a tour; never crop an element out of one.

Gate: every pixel on screen is either the product, real data from the product, or type. If you
catch yourself drawing a "generated result" in CSS, stop and go get a real one.

### Phase 2 — Lock the grid, then the story

Pick the music first (Phase 4 has the how), detect its BPM, and define `B(k) = k × bar`. Every
scene starts on a bar. Every click lands on a downbeat. The one big moment (the "drop") is the
`ANCHOR`. Write the story as a list of bars:

```
B0  brand stamp (dark)          B14 the click (drop)
B2  statement (light)           B16 next chapter (colour flip)
B4  the ask (composer types)    ...
B8  the answer (chat canvas)    B28 closer (dark) + credit
```

Two or three chapters, each 2 bars, is the rhythm that worked. Nothing static for more than
~1.5 s. Light/dark/colour alternate between chapters so no two consecutive scenes share a look.

Gate: read the bar list aloud as a story. If a bar is "show the dashboard", it has no story and
gets cut or captioned into one.

### Phase 3 — Build in Remotion with the kit

`templates/remotion/src/kit/` has the primitives that survived review:

| primitive | use |
|---|---|
| `Rise`, `WordReveal`, `StreamText` | the only entrances: fade + 12–24 px rise, 70 ms stagger; text streams at 60–70 cps |
| `Composer`, `Bubble` | the product's composer and user message, rebuilt |
| `Card`, `Row`, `Spark`, `Bars`, `LineChart` | answer cards with live micro-visuals; lines draw with `strokeDashoffset` |
| `Cursor2` | keyframed cursor: arrive → pause ≥ 0.6 s → click dip 15 %/80 ms → the page reacts → camera follows |
| `ProcessButton` | Apply → "Applying" spinner (0.65 s) → check draws → status line → toast. A state swap is never a cut |
| `OrangeBurst` | a disc grows out of the button you just clicked into a full-colour frame, types one line, wipes up |
| `Wall` | a masonry of real videos pouring in (stagger 4 f, blur→sharp), spotlight on one |
| `Tour` | full windows, one per beat, camera settles + 4 % push-in, label + one-line caption |
| `OpenDark`, `CloseDark` | brand bookends: mark, wordmark typing with echo outlines, mono taglines, tiny credit |
| `Flow2` | node → mark → cycling node, lines draw, arrow always lands with a gap |

Camera is one `scale()` on an `AbsoluteFill` with a moving `transformOrigin`: lean 1.04–1.10
toward what matters next, never tilt, never 3D. Scroll is a single `translateY` on a tall canvas.

Gate: `npx tsc --noEmit` clean; half-scale draft render; contact sheet of every beat
(`scripts/contact_sheet.py`) read by you before anyone else sees it.

### Phase 4 — Score that plays as one piece

`references/music.md` has the full method. Short version: generate 30 s takes (MusicGen) or take a
licensed track, separate stems with Demucs, then `scripts/stemscore2.py` loops whole bars and
arranges bass/drums/other per scene with **static per-scene gain, bar-quantized changes, long
ramps (0.8–1.0 s), one suck-out → hit at the ANCHOR, at most two soft accents elsewhere**. Six
level states in a minute is plenty; more and it "isn't one piece". Time-stretch the stems to the
grid BPM at 1 ms accuracy rather than moving your grid.

Gate: listen. If you can hear where the arrangement changes, smooth it.

### Phase 5 — QA, deliver, log

1. Full render → two-pass `loudnorm` (`scripts/loudnorm2pass.sh`) → verify −14 ± 0.5 LUFS.
2. Contact sheets of the moments that changed since last version. Look for: cursor off the
   button, element cut by a crop, text arriving after the scene it belongs to, anything static.
3. Name the file `<Project>_Launch-Video-vN.mp4`. Never overwrite a previous version.
4. Append a README section: the feedback quoted, what changed, the grid, the score settings.

Gate: the last frame you looked at is the last frame of the film.

## Hard rules

- **No placeholders.** No gradient tiles with fake brand names, no CSS "generated result", no lorem.
- **No cropped elements.** A crop that cuts through a border looks like a beginner's edit. Rebuild the component.
- **No slides.** A headline beside a UI card, a colour column with a claim, three stills in a row — all read as PowerPoint. Content must move as one continuous canvas or the camera must move.
- **Reading time.** Dwell ≥ 0.6 s + 0.3 s per word, then move. But nothing static longer than ~1.5 s.
- **Clicks are choreography.** Arrive, pause, dip, page reacts, then the camera follows. Every click on a downbeat.
- **State changes are processes.** Loading → progress → result. Show the product's real loading UI.
- **Transitions are motivated.** The next scene grows out of the thing you just touched.
- **Every loader resolves.** If two tiles start spinning, two tiles land.
- **Numbers are real and consistent.** The question, the sentence and the chart must agree.
- **Brand is the deck's, not yours.** Upright wordmark if the deck is upright; their taglines, their mono voice.
- **One shadow tier per surface.** No glow, burst, glitch, dither, shake, speed lines, tilted windows.
- **A tiny credit** in the closer if the maker wants one — 15 px, visible before the fade.

## The review loop

Show every version. Log what changed per version in the README. Treat vague review notes as precise
diagnoses: "looks generated" means a placeholder or a generic loading state; "feels like slides"
means a static composition; "looks pasted" means a state swap instead of a process; "the music
doesn't feel like one piece" means too many level changes. Never re-litigate a rejected device;
remove it and find a better one.

## Files

- `references/grammar.md` — reference-film grammar, device by device
- `references/anti-slop.md` — the visual rules with the exact numbers
- `references/music.md` — MusicGen → Demucs → stemscore, BPM matching, loudnorm
- `references/real-data.md` — how to get real footage, data and assets safely
- `scripts/` — `stemscore2.py`, `musicgen.py`, `frame_sheet.sh`, `contact_sheet.py`, `loudnorm2pass.sh`, `tempo.py`
- `templates/remotion/` — the Remotion starter with the kit and an example Film
