$ man how-to/build-remotion-video-system
CLI Toolsadvanced
How to Build a React Video Rendering System with Remotion
No GPU, no After Effects — React components that render to MP4 inside your monorepo
What Remotion Is and Why It Fits
Remotion is a React framework that renders video frame by frame. You write JSX components. Remotion evaluates each frame at your target FPS and encodes the result to MP4, WebM, or GIF. No GPU required. No timeline editor. No After Effects. The entire pipeline runs in Node.js on a standard laptop. The key advantage for a monorepo setup is that video components can import the same shared packages as your websites. Design tokens, data objects, color palettes, and type definitions are shared across the entire codebase. Change a hex value in the shared package and the websites and videos all update on the next build.
PATTERN
Multi-Aspect-Ratio Architecture
Define aspect ratio presets as a constant object: linkedin (1080x1350, 4:5), reels (1080x1920, 9:16), landscape (1920x1080, 16:9). Create a useScale() hook that normalizes all rendering to a base resolution (1080x1350) and scales proportionally. Each brand gets three compositions in Root.tsx — one per aspect ratio — sharing the same component tree. Nine total compositions from one codebase: three brands times three formats. The composition registry is the single source of truth for what gets rendered. Adding a new brand means adding three lines to Root.tsx, not rebuilding any components.
CODE
Scene-Based Composition with TransitionSeries
Each video is a sequence of scenes connected by TransitionSeries from @remotion/transitions. Each scene is a React component with a fixed frame count defined in a central timing config file. The V3 timing config defines four scenes totaling 310 frames at 30fps (roughly 10 seconds): Hook (36 frames), BootWikiBlitz (110 frames), Progression (100 frames), CtaNetwork (94 frames), with 10-frame overlaps between scenes for smooth transitions. The timing file is the single control point for video rhythm. Changing one number changes the entire pacing without touching any component code.
PATTERN
Deterministic Animation with Perlin Noise
Remotion requires deterministic rendering. Math.random() produces different values per frame and breaks the render. The solution is Perlin noise from @remotion/noise. The noise2D function takes a seed string, x, and y coordinates and returns a deterministic float. Seed the noise by component instance (column index, particle index) and drive it with the frame number. MatrixRain uses noise for character selection, column drift, and opacity shimmer. ParticleField uses two independent noise streams for x and y drift plus a third for pulse. TypewriterText uses simple frame math for character reveal. Same seed, same output, every render. Organic animation that is fully reproducible.
PATTERN
SceneWrapper and Visual Treatment
A SceneWrapper component applies consistent visual treatment to every scene: dark canvas background, radial vignette for edge darkening, accent color wash at low opacity, ambient particle field, film grain via SVG feTurbulence, and scanline overlay for a CRT aesthetic. The wrapper accepts an accent color prop that tints the entire scene. The BootWikiBlitz scene cycles through the brand palette as wiki cards flip — green, teal, amber, purple — giving each card a distinct feel while maintaining visual consistency. Design tokens live in a tokens.ts file that maps brand names to colors and defines the shared font stack.
PRO TIP
Rendering and Deployment Pipeline
Run npm run render:all to generate all nine variants. Remotion renders each composition to frames then encodes to MP4. Outputs go to website/apps/video/out/ and get deployed to each site public/video/ directory. The SQLite content index tracks all video files with their brand, aspect ratio, format, and deployment status. The entire pipeline runs locally on a MacBook. No cloud render farm. No external service. The monorepo CI can trigger renders on push if needed, but for iteration speed, local rendering at 30fps for 10-second videos takes seconds, not minutes.
related guides