Skip to content
Development
Skill

/promo-clip

Use when asked for a promo clip, ролик, announcement video, teaser or launch video for a product or plugin, or when a task involves Remotion.

From plugin
superpowers-v
364 skills7 agents15 commands7 hooks
Install
$ npx -y skills add procoders/superpowers-v --skill promo-clip --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/promo-clip

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when asked for a promo clip, ролик, announcement video, teaser or launch video for a product or plugin, or when a task involves Remotion.

SKILL.md

promo-clip.SKILL.md
name: promo-clip
description: Use when asked for a promo clip, ролик, announcement video, teaser or launch video for a product or plugin, or when a task involves Remotion.

Promo clips with Remotion

Overview

A promo clip is **a script approved on paper, then a Remotion composition reviewed one still per scene before anything is rendered**. Both failures we hit — three invisible scenes and a cut nobody could read — were caught by a still or by a human, never by the compiler.

Working reference, read it before writing scenes: `/Users/oleg/Dev/cv-promo/src/Promo.tsx` (9 scenes, 1920×1080, 30 fps, `TransitionSeries`, inline styles, no CSS framework). Script: `script-v5-final.md` · pain research + reference ad: `pains-v1.md` in the same repo.

Workflow

1. **Script table first, no code.** One markdown table, columns `t · frames · on screen · motion/sound`, plus a footer naming palette, fonts and spice level. Get an explicit approval on that table. Reason: rewriting a table is minutes, re-animating a scene is an hour. 2. **Scaffold, then install — the scaffold does not install.**

   npx create-video@latest --yes --blank --no-tailwind ~/Dev/cv-promo
   cd ~/Dev/cv-promo && npm install
   npm i @remotion/transitions@4.0.520   # EXACTLY the version of `remotion` in package.json

Pin the transitions package to the same version as `remotion`; a drifted pair breaks types. `--no-tailwind` because every style here is an inline `style={{}}` object — cv-promo scaffolded *with* Tailwind and never used a single class. 3. **One composition, one `<Sequence>` (or `<TransitionSeries.Sequence>`) per scene.** Scene durations live in one object; `Root.tsx` imports `FPS` and `DURATION` from it. 4. **Review stills before any render** — one frame per scene, mid-scene, at half scale:

   npx remotion still Promo out/f200.png --frame=200 --scale=0.5

Read every PNG. A full render costs minutes; a still costs seconds and shows the same bug. 5. **Render only after the stills pass.**

   npx remotion render Promo out/promo.mp4

Three traps that cost us real time

1. `<TransitionSeries>` accepts only literal children

`<TransitionSeries>` takes `<TransitionSeries.Sequence>` and `<TransitionSeries.Transition>` and nothing else. A wrapper component that renders a `Transition` throws at render time (`only accepts a list of <TransitionSeries.Sequence /> and <TransitionSeries.Transition />`), and a helper typed over a union of presentations (`fade | wipe | slide`) fails TypeScript. **Inline every transition.** Verbose beats clever:

<TransitionSeries.Sequence durationInFrames={SCENES.pains}><Pains /></TransitionSeries.Sequence>
<TransitionSeries.Transition presentation={wipe({ direction: "from-left" })}
  timing={springTiming({ config: { damping: 200 }, durationInFrames: T })} />
<TransitionSeries.Sequence durationInFrames={SCENES.contrast}><Contrast /></TransitionSeries.Sequence>

2. Paint order — wrap scene content in its own `<AbsoluteFill>`

An `<AbsoluteFill>` background rendered first paints **above** later static siblings: positioned elements paint after in-flow ones, so `<Bg />` swallows the text below it. We lost three scenes to this and only saw it in the stills. Every scene is:

<AbsoluteFill>
  <Bg tint={BLUE} />
  <AbsoluteFill style={{ justifyContent: "center", alignItems: "center" }}>
    {/* content — now positioned, so it paints after the background */}
  </AbsoluteFill>
</AbsoluteFill>

Any `position`/`transform` on the content works; a bare in-flow `<div>` does not.

3. Total duration is computed, never typed

Transitions overlap their neighbours, so the timeline is **shorter** than the sum of scenes:

const T = 12; // transition length, frames
const SCENES = { hook: 80, pains: 175, contrast: 65, v: 50, formula: 60,
                 powers: 155, regen: 50, end: 65, site: 56 };
export const DURATION = Object.values(SCENES).reduce((a, b) => a + b, 0)
                      - T * (Object.keys(SCENES).length - 1);

Hand-computing it desynchronises the audio and truncates the end card.

Readability — the pacing the maintainer actually wants

  • **~3.5 s per text screen.** A screen of six typed lines needs **~10 s** (300 frames at 30 fps).
  • The shipped 22 s cut gave the six pains 175 frames (5.8 s); the maintainer could not read it

and asked for **~35 s** total. When in doubt, slow down — nobody complains a promo was legible.

  • Retiming changes `DURATION`, so the soundtrack has to be recomposed to the new length too.

Palette — take it from the product site, never invent

Extract, don't guess: `curl -s https://amiainative.dev` and its linked CSS, then `grep -oE '#[0-9a-fA-F]{6}' | sort | uniq -c | sort -rn`. Cross-check against in-repo art (`docs/routing.svg`). Introducing a colour the brand does not own is a rejection.

| token | hex | use | |---|---|---| | NAVY / NAVY2 | `#0b0b22` / `#14143a` | background gradient | | BLUE | `#1195F2` | early nodes, mono labels | | INDIGO | `#6565F2` | mid nodes, glows | | MAGENTA | `#DC02DF` | the V, strikes, the payoff | | GOLD | `#FFC53D` | accents, the gag, "=" | | PAPER / GREY | `#f7f7fb` / `#8c8fa8` | headline text / secondary text |

**No red anywhere** — the maintainer rejected it, including the "red stamps" that were in the approved script v5. The script is not the last word; the maintainer is.

The structure that worked

hook (contrast question) → pains typed out and struck through → two-line contrast beat ("Some will … / Others …", borrowed from the Neoversity reference ad in `pains-v1.md`) → the reveal → an equation slide (Claude Code + Superpowers + V = SUPE) → feature nodes strung along a pipeline line with exactly one gag (a rogue write bouncing off, `BLOCKED`) → "Regenerates. (Crash? Resume.)" → end card → a clean final screen with the site URL and a motto.

One gag per clip. The pains are the hook; the gate is the promi

Read more
Ships withsuperpowers-v

Compound V — a multi-model coding sidekick for Superpowers, running on Claude Code. You describe a feature. Claude sizes the request, plans it, splits it into non-overlapping pieces, and hands each piece to a worker in its own isolated worktree.

Get the whole plugin

Other skills on superpowers-v.