Remotion best practices
Universal AI development toolkit. 74 production-ready skills for every coding agent. Works with Claude Code, Cursor, Codex.
npx -y skills add medy-gribkov/arcana --skill remotion-best-practicesAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Video creation in React using Remotion. Covers animations, compositions, audio sync, text effects, 3D integration with Three.js, and rendering. Use when building dynamic video generators, editing timelines, or optimizing Remotion renders.
SKILL.md
5.5 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it
You are a Remotion expert. All animations must be frame-driven via useCurrentFrame(). CSS transitions and Tailwind animation classes are FORBIDDEN in Remotion, they will not render correctly.
When to use
- Building programmatic videos with React
- Creating animated intros, demos, promo videos
- Generating data-driven video content
- Working with captions, charts, or text animations
Core Pattern
Every Remotion component follows this structure:
import { useCurrentFrame, useVideoConfig, interpolate, spring } from "remotion";
export const MyScene: React.FC = () => {
const frame = useCurrentFrame();
const { fps, width, height } = useVideoConfig();
const opacity = interpolate(frame, [0, 1.5 * fps], [0, 1], {
extrapolateRight: "clamp",
});
const scale = spring({ frame, fps, config: { damping: 12 } });
return (
<div style={{ opacity, transform: `scale(${scale})` }}>
Content here
</div>
);
};
Always use seconds * fps, never raw frame numbers:
// BAD
const opacity = interpolate(frame, [0, 45], [0, 1]);
// GOOD
const opacity = interpolate(frame, [0, 1.5 * fps], [0, 1]);
Composition Setup
// src/Root.tsx
import { Composition } from "remotion";
import { MyVideo, MyVideoProps } from "./MyVideo";
export const RemotionRoot = () => (
<Composition
id="MyVideo"
component={MyVideo}
durationInFrames={30 * 30} // 30s at 30fps
fps={30}
width={1920}
height={1080}
defaultProps={{ title: "Demo" } satisfies MyVideoProps}
/>
);
Use type for props (not interface) to ensure defaultProps type safety.
Sequencing Scenes
import { Sequence } from "remotion";
export const MyVideo: React.FC = () => (
<>
<Sequence from={0} durationInFrames={150}>
<Intro />
</Sequence>
<Sequence from={150} durationInFrames={240}>
<MainContent />
</Sequence>
<Sequence from={390} durationInFrames={150}>
<Outro />
</Sequence>
</>
);
Inside each <Sequence>, useCurrentFrame() resets to 0. Design components to start at frame 0.
Animation Patterns
Spring (natural motion, 0 to 1):
const scale = spring({ frame, fps, config: { mass: 1, damping: 10, stiffness: 100 } });
Interpolate (map frame range to value range):
import { interpolate, Easing } from "remotion";
const translateY = interpolate(frame, [0, 2 * fps], [50, 0], {
extrapolateRight: "clamp",
easing: Easing.out(Easing.cubic),
});
Staggered items:
{items.map((item, i) => {
const delay = i * 5; // 5 frame stagger
const progress = spring({ frame: frame - delay, fps });
return (
<div key={i} style={{ opacity: progress, transform: `translateY(${(1 - progress) * 20}px)` }}>
{item}
</div>
);
})}
Audio
import { Audio, interpolate } from "remotion";
import { staticFile } from "remotion";
<Audio
src={staticFile("music.mp3")}
startFrom={30} // trim start (frames)
endAt={300} // trim end (frames)
volume={(f) =>
interpolate(f, [0, 30], [0, 1], { extrapolateRight: "clamp" })
}
/>
Assets
Always use staticFile() for local assets in public/:
// BAD
<Img src="/logo.png" />
// GOOD
import { staticFile } from "remotion";
<Img src={staticFile("logo.png")} />
For Google Fonts:
import { loadFont } from "@remotion/google-fonts/Inter";
const { fontFamily } = loadFont();
Anti-patterns
BAD:
// CSS transition (won't render in video)
<div style={{ transition: "opacity 0.3s" }}>
// Tailwind animate class (won't render)
<div className="animate-bounce">
// Raw frame numbers (unreadable)
const x = interpolate(frame, [0, 90], [0, 100]);
// useEffect for animation (breaks determinism)
useEffect(() => { setOpacity(1); }, []);
GOOD:
// Frame-driven opacity
const opacity = interpolate(frame, [0, 3 * fps], [0, 1], {
extrapolateRight: "clamp",
});
// Spring for natural motion
const scale = spring({ frame, fps });
// All state derived from frame, never useState for animation
Rendering
# Preview
npx remotion preview
# Render to MP4
npx remotion render MyVideo out/video.mp4
# Render specific frames
npx remotion render MyVideo --frames=0-150 out/preview.mp4
# Render as GIF
npx remotion render MyVideo out/video.gif --image-format=png
Deep Dive References
For detailed patterns, load the relevant rule file:
| Topic | File |
|---|---|
| Compositions, stills, folders | rules/compositions.md |
| Interpolation and springs | rules/timing.md |
| Scene transitions | rules/transitions.md |
| Text animations | rules/text-animations.md |
| Captions and subtitles | rules/subtitles.md |
| Charts and data viz | rules/charts.md |
| 3D with Three.js | rules/3d.md |
| Video embedding | rules/videos.md |
| Audio and sound | rules/audio.md |
| Parametrizable videos (Zod) | rules/parameters.md |
| TailwindCSS setup | rules/tailwind.md |
| Maps (Mapbox) | rules/maps.md |
| Transparent video export | rules/transparent-videos.md |
What ships with it: 36 files
97.7 KB alongside SKILL.md
rules/
- 3d.md2.2 KB
- animations.md790 B
- assets/charts-bar-chart.tsx3.3 KB
- assets.md1.6 KB
- assets/text-animations-typewriter.tsx2.1 KB
- assets/text-animations-word-highlight.tsx2.3 KB
- audio.md3.5 KB
- calculate-metadata.md2.9 KB
- can-decode.md1.5 KB
- charts.md2.9 KB
- compositions.md3.6 KB
- display-captions.md5.3 KB
- extract-frames.md5.4 KB
- fonts.md3.4 KB
- get-audio-duration.md1.3 KB
- get-video-dimensions.md1.6 KB
- get-video-duration.md1.3 KB
- gifs.md3.6 KB
- images.md2.7 KB
- import-srt-captions.md2.2 KB
- light-leaks.md2.3 KB
- lottie.md1.7 KB
- maps.md11.0 KB
- measuring-dom-nodes.md974 B
- measuring-text.md2.9 KB
- parameters.md2.3 KB
- sequencing.md2.7 KB
- subtitles.md922 B
- tailwind.md422 B
- text-animations.md700 B
- timing.md3.8 KB
- transcribe-captions.md1.9 KB
- transitions.md5.7 KB
- transparent-videos.md2.2 KB
- trimming.md1.2 KB
- videos.md3.4 KB
Gives 0 of the 12 instructions most video audio skills give in ~1.5k tokens
Counted across 622 of the 795 authors here whose files we hold, read 2026-08-07
- read individual rule files for detailed explanationsin 21 of 622, across 10 files
- render final videoin 13 of 622, across 6 files
- Use WAV PCM 16kHz mono audio formatin 12 of 622, across 3 files
- Use this skill when dealing with Remotion codein 11 of 622, across 4 files
- save generated audio to a WAV filein 11 of 622, across 4 files
- handle conversion errors gracefullyin 10 of 622, across 6 files
- add captions to videos alwaysin 10 of 622, across 4 files
- generate music from text descriptions using MusicGenin 9 of 622, across 2 files
- do not skip pipeline layersin 9 of 622, across 3 files
- do not make one tool do everythingin 9 of 622, across 3 files
- use azure document intelligence for complex pdfsin 9 of 622, across 4 files
- never ask the user to paste their full API keyin 9 of 622, across 3 files
Said here and by no other author read
- multiply seconds by fps for timings
- use type for component props
- design sequence components to start at frame 0
- derive animation state from frame
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.