| name | launch-video |
| description | Use when creating a launch, release, or announcement video for the Spool desktop app from real screen recordings. Covers the capture pipeline (Electron + native macOS window recording), the HyperFrames composition layout, common trailer-vs-PPT pitfalls, and the first-frame poster trick for social media. Invoke when the user mentions release video, launch video, announcement video, trailer, demo video, or wants to ship a video for a Spool version bump. |
| user-invocable | true |
| argument-hint | [version (e.g. v0.5.0)] |
Build a release video for a Spool version. The output is a 1080p MP4 plus a poster JPG, intended for X / Twitter. Runtime scales with feature count: 20–40s, 3–8 feature beats + brand outro, optionally an "artifact" payoff scene before the outro for releases whose centrepiece is a tangible export (PDFs, share-files, etc).
Mental model
A release video for Spool has two halves running in parallel on screen:
- Left third — a text panel that introduces the current scene (kicker
01 / 04 — POLISH, a 2-line headline, a 1–2 line sub).
- Right two-thirds — the real Spool app, recorded as a native macOS window. The camera (CSS
transform-origin + scale on the .window) zooms into the specific UI region for each feature.
Focus on the active feature is carried by one of two devices:
- Amber annotation rectangles inside
.window that track the camera — good for "look at this strip" callouts. Cheap and precise when the feature is a single bounded region.
- Spotlight mask — an SVG overlay that dims everything except 1–2 transparent "holes" punched through. Softer falloff means small coordinate drift disappears into the dim instead of reading as a misaligned outline. Dual holes let you keep the preview bright while a control on the right side lights up in sync with a click. See
references/spotlight.md.
This is not a PPT: text panel and demo coexist continuously, with hard match-cuts between feature clips. Don't reintroduce slide-style title cards.
Required preparation
Read these references before you start composing. They are not optional — each captures hard-won decisions from prior releases.
references/composition.md — the proven layout, dimensions, drop-shadow recipe, panel + annotation timing patterns, beat-sync approach, the panel-leads-spotlight rhythm rule, the optional artifact-fan payoff scene
references/capture.md — how to record native macOS windows of the Electron app, helper functions to use, per-release seed authoring, the feature-flag-at-build-time gotcha
references/cursor-overlay.md — synthetic cursor that tracks Playwright mouse + visualises clicks. Solves "Playwright doesn't move the OS cursor and screencapture only films pixels"; required whenever a scene's whole point is a click
references/spotlight.md — SVG-mask focus technique; single-hole for one target, dual-hole for cause-effect (preview always bright + active control bright); the payoff pattern (collapse secondary to redirect the eye)
references/pitfalls.md — things we tried that look bad in motion (decorative chrome, smooth camera drifts, pre-clip resets, clip-boundary gaps, etc.) and why
references/poster.md — the tpad clone trick so Twitter's auto-thumbnail grabs the hero frame instead of a leading black frame
End-to-end checklist
- Inventory the features to demo. A release video shows 3–4 features max. Pick the ones with the most visible UI change.
- Author a per-release seed. Write a
ProjectSeed[] array (see packages/app/e2e/helpers/demo-fixtures.ts for the type). Titles should be English-only and must not reference real user sessions — invent plausible session titles relevant to the release theme.
- Write an ad-hoc capture spec. A Playwright spec under
packages/app/e2e/ (not committed) that:
- Calls
launchDemoApp(seed) + setDemoWindowBounds(ctx, 1080, 740)
- Calls
installCursorOverlay(ctx.window) (from helpers/cursor-overlay.ts) before any clip is recorded so the synthetic cursor is in frame from t=0
- Records one
.mov per feature via recordNativeWindow() from helpers/native-window-capture.ts
- Uses
cursorClick(window, selector, opts) / cursorTo(...) / cursorPark(x, y) from the same helper instead of bare .click() so the cursor's path is visibly filmed
- Outputs to
videos/spool-vX.Y.Z/assets/live/ (gitignored)
- If your release gates a feature behind a Vite flag, build the app with
VITE_FEATURE_<NAME>=1 pnpm --filter @spool/app run build:electron before running the spec — import.meta.env.VITE_FEATURE_<NAME> is inlined at build time, not read at runtime
- Bump
--global-timeout if pacing is relaxed: Playwright's default 300s isn't enough for 7-beat spec runs (~50s of screencapture -V plus warmup)
- Copy
videos/launch-template/ to videos/spool-vX.Y.Z/.
- Customise the composition (
index.html):
- Update
<video> data-start, data-duration, src per clip. Verify each pair satisfies prev.data_start + prev.data_duration ≥ next.data_start + 0.10 — gaps where neither clip is playing render as a dark frame and read as a full-screen flash (see pitfalls.md #11)
- Author one text panel per scene (kicker + headline + sub)
Hard rules
- Synthetic cursor is allowed but must track real input. A floating GSAP cursor that arrives at random places looks uncanny — that rule from prior releases stands. What's not uncanny is the cursor-overlay technique in
references/cursor-overlay.md: a DOM cursor injected into the page that follows Playwright's actual mouse.move() and pulses on mousedown. If a scene's whole point is a click, draw the cursor. Don't draw a cursor for scenes where nothing's being clicked.
- Chain state across clips. Don't reset between recordings. If clip 3 ends with the editor in
Timeline / Bone / Walnut, clip 4 starts there. Pre-clip state resets (clicking different templates / papers between recordings) cause a visible "flash" at the clipCut boundary even though both clips show editor pixels. If the export beat needs a specific final look, get to it inside the recording (the user sees the click) or land it earlier in the chain so it's the natural state by the export beat.
- First frame must be the full hero state. Brand mark + panel 1 + UI window all visible at
t=0, not faded in. Twitter's auto-thumbnail grabs this frame.
- Annotations and spotlights live inside
.window, not on the outer canvas. They must move with the camera transform.
- No decorative chrome. No vignette, callsign, progress bar, or trailer-style overlay flashes. The UI is the protagonist.
- No "pull back to neutral" before the outro. End the last feature beat on its focus, then hard-cut/fade to the Spool lockup (or to the artifact-fan scene if the release earns it).
Files this skill touches
- Reads:
packages/app/e2e/helpers/{demo-fixtures,demo-launch,demo-interactions,native-window-capture,cursor-overlay}.ts
- Reads:
videos/launch-template/
- Creates:
videos/spool-vX.Y.Z/ (new release directory)
- Creates: a temporary Playwright spec under
packages/app/e2e/ (do not commit; delete or gitignore after the release ships)
- Outputs:
videos/spool-vX.Y.Z/renders/spool-vX.Y.Z-final.mp4 and .jpg poster (both gitignored)