
Remotion Best Practices
Embed Three.js / React Three Fiber 3D scenes in Remotion compositions without flicker during video render.
Install
npx skills add https://github.com/remotion-dev/html-in-canvas --skill remotion-best-practicesWhat is this skill?
- Install @remotion/three via `npx remotion add` (npm/bun/yarn/pnpm variants)
- Wrap all 3D content in `<ThreeCanvas>` with explicit `width` and `height` from `useVideoConfig()`
- Require ambient + directional lighting inside ThreeCanvas
- Ban self-animating shaders/models—only `useCurrentFrame()`-driven motion (not raw `useFrame()` for render sync)
- Follow standard R3F/Three.js patterns with Remotion-specific exceptions documented in SKILL.md
Adoption & trust: 8 installs on skills.sh; 182 GitHub stars; 2/3 security scanners passed (skills.sh audits).
Recommended Skills
Video Editagentspace-so/runcomfy-agent-skills
Image To Videoagentspace-so/runcomfy-agent-skills
Image Editagentspace-so/runcomfy-agent-skills
Flux Kontextagentspace-so/runcomfy-agent-skills
Nano Banana 2agentspace-so/runcomfy-agent-skills
Nano Banana Editagentspace-so/runcomfy-agent-skills
Journey fit
Common Questions / FAQ
Is Remotion Best Practices safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Remotion Best Practices
# Using Three.js and React Three Fiber in Remotion Follow React Three Fiber and Three.js best practices. Only the following Remotion-specific rules need to be followed: ## Prerequisites First, the `@remotion/three` package needs to be installed. If it is not, use the following command: ```bash npx remotion add @remotion/three # If project uses npm bunx remotion add @remotion/three # If project uses bun yarn remotion add @remotion/three # If project uses yarn pnpm exec remotion add @remotion/three # If project uses pnpm ``` ## Using ThreeCanvas You MUST wrap 3D content in `<ThreeCanvas>` and include proper lighting. `<ThreeCanvas>` MUST have a `width` and `height` prop. ```tsx import { ThreeCanvas } from "@remotion/three"; import { useVideoConfig } from "remotion"; const { width, height } = useVideoConfig(); <ThreeCanvas width={width} height={height}> <ambientLight intensity={0.4} /> <directionalLight position={[5, 5, 5]} intensity={0.8} /> <mesh> <sphereGeometry args={[1, 32, 32]} /> <meshStandardMaterial color="red" /> </mesh> </ThreeCanvas>; ``` ## No animations not driven by `useCurrentFrame()` Shaders, models etc MUST NOT animate by themselves. No animations are allowed unless they are driven by `useCurrentFrame()`. Otherwise, it will cause flickering during rendering. Using `useFrame()` from `@react-three/fiber` is forbidden. ## Animate using `useCurrentFrame()` Use `useCurrentFrame()` to perform animations. ```tsx const frame = useCurrentFrame(); const rotationY = frame * 0.02; <mesh rotation={[0, rotationY, 0]}> <boxGeometry args={[2, 2, 2]} /> <meshStandardMaterial color="#4a9eff" /> </mesh>; ``` ## Using `<Sequence>` inside `<ThreeCanvas>` The `layout` prop of any `<Sequence>` inside a `<ThreeCanvas>` must be set to `none`. ```tsx import { Sequence } from "remotion"; import { ThreeCanvas } from "@remotion/three"; const { width, height } = useVideoConfig(); <ThreeCanvas width={width} height={height}> <Sequence layout="none"> <mesh> <boxGeometry args={[2, 2, 2]} /> <meshStandardMaterial color="#4a9eff" /> </mesh> </Sequence> </ThreeCanvas>; ``` import {loadFont} from '@remotion/google-fonts/Inter'; import {AbsoluteFill, spring, useCurrentFrame, useVideoConfig} from 'remotion'; const {fontFamily} = loadFont(); const COLOR_BAR = '#D4AF37'; const COLOR_TEXT = '#ffffff'; const COLOR_MUTED = '#888888'; const COLOR_BG = '#0a0a0a'; const COLOR_AXIS = '#333333'; // Ideal composition size: 1280x720 const Title: React.FC<{children: React.ReactNode}> = ({children}) => ( <div style={{textAlign: 'center', marginBottom: 40}}> <div style={{color: COLOR_TEXT, fontSize: 48, fontWeight: 600}}> {children} </div> </div> ); const YAxis: React.FC<{steps: number[]; height: number}> = ({ steps, height, }) => ( <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', height, paddingRight: 16, }} > {steps .slice() .reverse() .map((step) => ( <div key={step} style={{ color: COLOR_MUTED, fontSize: 20, textAlign: 'right', }} > {step.toLocaleString()} </div> ))} </div> ); const Bar: React.FC<{ height: number; progress: number; }> = ({height, progress}) => ( <div style={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end', }} > <div style={{ width: '100%', height, backgroundColor: COLOR_BAR, borderRadius: '8px 8px 0 0', opacity: progress, }} /> </div> ); const XAxis: React.FC<{ children: React.ReactNode; labels: string[]; height: number; }> = ({children, labels, height}) => ( <div style={{flex: 1, display: 'flex', flexDirection: 'column'}}> <div style={{ display: 'flex', alignItems: 'flex-end', gap: 16, height,