Communitygithub.com

ThomasHMD/motion-design

THE WORKSHOP of the kit: the only Remotion project (scenes, lower thirds, quotes and site demos rendered for the `overlays` skill, in `src/illustration/`), the theme (colors, fonts), the synthesized sound palette (synth recipes, gesture vocabulary, levels), music written as code and the mix to a target loudness.

What is motion-design?

motion-design is a Claude Code agent skill that tHE WORKSHOP of the kit: the only Remotion project (scenes, lower thirds, quotes and site demos rendered for the `overlays` skill, in `src/illustration/`), the theme (colors, fonts), the synthesized sound palette (synth recipes, gesture vocabulary, levels), music written as code and the mix to a target loudness.

Works with✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ThomasHMD/premiere-rough-cut/tree/HEAD/skills/motion-design

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

motion-design: the workshop (Remotion, theme, sounds, music)

Everything is local and deterministic: same code = same MP4. No image or video generated by AI.

The stack

PieceToolWhere
AnimationRemotion 4.0.529 (React / TSX), versions pinned in package.jsonsrc/; npx remotion add <package> for one more module
Themecolors, fonts, sizes, marginssrc/illustration/theme.ts (read by the C and F constants of src/illustration/scenes/kit.tsx), fonts in public/fonts/
Remotion modulestransitions, effects, gsap, three, noise, paths, shapes, motion-blur, light-leaks, starburst, rough-notation, captions, layout-utils, lottiepackage.json
Graphics compositionsBrandedVideo (full-screen scenes), LowerThirdTrack (lower thirds, section titles), Screencast (site demos), Scene (scene catalog), ControleTexte (text check), FondAnime (looping animated background; its grain is made by scripts/make-grain.py)src/illustration/, declared by Compositions.tsx, wired in src/Root.tsx
Shared cueskey times in seconds, read by the animation AND by the soundsrc/<project>/cues.json
Musica score written in Python on a numpy synth (scripts/synth.py: FM electric piano, pad, bass, percussion, vinyl crackle, reverb)music/<project>.py, model: music/example_pad.py
Sound effectssynthesized palette: read reference/sound-palette.md before any sound. Synth recipes scripts/make-sfx.py -> public/sfx/*.wav + palette.json; gesture vocabulary scripts/son.py (a plan names a gesture, never a file; lists are one placed card per item by default, son.LISTES; son.releve: a numbered list of the sounds of a video, to be reviewed by number); scripts/palette-import.py (a palette of real recordings, same file names, falls back to the default); scripts/sfx.py (a few extra sounds: shutter, focus tick, whoosh)scripts/
Mixmusic + sound effects + voice, music ducked under the voice, EBU R128 target loudness, true peak limited to -1.5 dBTP (oversampled limiter, only when it overshoots)scripts/mix.py
Checkstonal balance per octave, loudnessscripts/ltas.py, mix.py

Licenses. Remotion is free for individuals and for companies of up to 3 employees; beyond that a company license is required (remotion.pro). Read its LICENSE.md before using the kit commercially in a larger company. The fonts Inter and Source Serif 4 are under the OFL (public/fonts/OFL-*.txt); the sounds and the example music are synthesized here, with no third-party rights. Music found elsewhere: check its license (no CC-BY-NC on a monetized channel).

Setup, and what the node_modules line does

The plugin installs once with:

bash "${CLAUDE_PLUGIN_ROOT}/install.sh" --data "${CLAUDE_PLUGIN_DATA}"

(Claude Code replaces both variables with real paths when it reads this file.) Why a data folder: the plugin folder is replaced at every plugin update, and node_modules weighs about 1 GB. So npm ci runs once in the plugin's data folder (${CLAUDE_PLUGIN_DATA}), which survives updates, and skills/motion-design/node_modules is a symlink to it. If node_modules is missing after a plugin update (the new plugin folder has no link), rerun the line above: it only does what is missing and relinks in a second.

Manual install (the four skills/ folders copied side by side into ~/.claude/skills/): bash install.sh from the kit root; node_modules is then a normal folder installed by npm ci. Python side: python3 -m pip install numpy scipy soundfile pillow, and brew install ffmpeg. Details and a check of the whole chain: INSTALL.md of the kit.

Run every command of this skill from the workshop folder (skills/motion-design).

Pipeline of a whole motion-design video

  1. Frame it: duration, format (1920x1080 at 30 fps by default; 1080x1920 for a vertical reel; 1080x1080 for a square), use, platform constraints. Write src/<project>/cues.json: the key times drive both picture and sound.
  2. Animate: one composition per deliverable in src/<project>/, declared in src/Root.tsx, props typed with zod. Everything derives from useCurrentFrame(): never a free CSS animation, never Math.random() (random(seed) or noise2D). Theme colors and fonts only.
  3. Check the picture without waiting for a render: npx remotion still src/index.ts <Id> out.png --frame=N on the key frames, then a contact sheet of the MP4 (ffmpeg tile). Judge at phone size: the image reduced to 390 px wide must stay legible.
  4. Voice-over (if any): recorded by the user (48 kHz WAV), placed with --voice-at. The kit does not clone voices.
  5. Music and sound effects: python3 music/<project>.py <duration> music.wav; sounds through son.py, placed on the same instants as the picture (the plan calls son.releve(...) to write the numbered list to listen to); check with python3 scripts/ltas.py music.wav (no hole deeper than about 6 dB against a gentle slope).
  6. Mix: python3 scripts/mix.py --music ... --sfx ... [--voice ... --voice-at s] --lufs -16 --out public/audio/<project>_mix.wav (-14 for a reel, -16 for YouTube; --sfx-voix-ref -22 rescales the sound effects on the real voice).
  7. Render: npx remotion render src/index.ts <Id> out.mp4 --props='{"audio":"audio/<project>_mix.wav"}' --codec=h264 --crf=16 --audio-bitrate=320k.
  8. Deliver without overwriting an existing deliverable (suffix -v2), with a preview.

Renders placed in Premiere (graphics)

  • No logo in a scene, a full-screen graphic or a lower third: it loads the image for nothing.
  • A file meant for a 29.97 fps sequence must cover ALL of its clip: n sequence frames last n x 1.001 / 30 s. The compositions of src/illustration/ accept tailFrames: the TenirFin component (src/illustration/tenir-fin.tsx) plays the animation over its duration, then holds the last frame; exit animations do not move. The overlays skill's scripts/render-segments.py computes tailFrames.
  • The graphics compositions are rendered by scripts/render-segments.py, scripts/screencast-render.py and scripts/montage-tella.py of the overlays skill (work folder = this workshop, PNG frames, 4 cores), never by hand outside a remotion still check. Media called through staticFile go in public/scenes/<video>/.

Make it yours (change the theme)

The kit ships with a neutral theme: blue accent #2F5BEA, Inter and Source Serif 4, one theme file, src/illustration/theme.ts. To use your own brand:

  1. Colors: src/illustration/theme.ts (color: base, contrast, inkSoft, muted, surface, line, accent, accentDark, accentWash, darkBg, paperWarm); the scenes read it through C. The accent and its light tints are still hard-coded in a few places: grep -rn "#6B8CFF\|rgba(47,91,234\|rgba(214,224,252" src/ (highlights in preuves.tsx, Screencast.tsx, the PALETTES variants of compositions/FondAnime.tsx), to match the new accent. One accent, used as a signal, never as a fill.
  2. Fonts: drop the .woff2 files in public/fonts/, then change the file names and family names in the loading lists (src/illustration/scenes/kit.tsx, compositions/BrandedVideo.tsx, compositions/LowerThirdTrack.tsx, compositions/Screencast.tsx) and in theme.ts (font.display, font.sans). Check that the font has digits and accents (a "latin-ext" subset alone has neither digits nor base letters, and everything falls back to Georgia). Family name without a digit (or quoted in CSS).
  3. Animation curve: easeStd in scenes/kit.tsx and EASING in scripts/make-sfx.py go together (the sound follows the picture's curve).
  4. Check: npx tsc --noEmit, then a remotion still of each composition (quote, lower third, section card, number...), then --force on the next render-segments.py run (its cache already follows the code of src/illustration/).

Add a scene or a sound

  • Scene: a component in src/illustration/scenes/opaque.tsx (full-screen) or alpha.tsx (overlay), its data contract as a comment above it, one line in the registry scenes/Scene.tsx, one line in the catalog of the overlays SKILL.md. Every instant comes from the cues. Check: remotion still at several frames, the overlay composited on a frame of the clip.
  • Sound: reference/sound-palette.md, "Add or tweak a sound".

Synced folders trap

If the workshop lives in a synced folder (Dropbox, iCloud, Drive...), another machine can send back an old version of a file and rename the good one "conflicted copy". Symptom: Could not find composition with ID .... Reflex: find . -name '*conflicted copy*' -not -path './node_modules/*', compare, keep the most recent version. The webpack cache (node_modules/.cache) can conflict too: delete it, Remotion rebuilds it. Better: keep node_modules out of the sync.

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

Related Skills