Create stunning 3D animated explainer videos with code.
A production-ready framework combining Remotion + React Three Fiber for building programmatic 3D explainer videos. Write your scenes in React, render to MP4.
git clone https://github.com/htekdev/explainer-3d.git
cd explainer-3d
npm install
npm start # Opens Remotion Studio at http://localhost:3000- 10 reusable 3D components — boxes, arrows, particles, beams, labels, cameras
- Scene-based composition — break videos into scenes with automatic crossfades
- Bloom postprocessing — cinematic glow effects out of the box
- Deterministic rendering — seeded RNG for reproducible particle systems
- Animated camera — keyframe-based camera paths with smooth interpolation
- 60fps @ 1080p — production quality output
- GitHub Actions CI — automated testing, linting, and video rendering
- AI-friendly — Copilot instructions included for generating new videos
All components import from src/components:
| Component | Purpose | Key Props |
|---|---|---|
Scene3D |
Foundational wrapper — ThreeCanvas + lighting + bloom | camera, bloom, backgroundColor |
SystemBox |
Rounded 3D box representing a system/service | position, label, color, animateIn |
TokenStream |
Animated text tokens flowing in a direction | tokens, direction, speed, startFrame |
DataFlow |
Particle stream between two 3D points | from, to, color, particleCount |
Arrow3D |
Animated directional arrow | from, to, animated, startFrame |
FloatingLabel |
Billboard text label (always faces camera) | text, position, fontSize, animateIn |
GlowOrb |
Pulsing sphere with emissive glow | position, color, pulseSpeed, intensity |
ConnectionBeam |
Laser/beam connecting two points | from, to, color, pulseSpeed |
GridFloor |
Infinite ground grid | yPosition, fadeDistance, color |
ParticleField |
Ambient floating particles | count, spread, speed, seed |
AnimatedCamera |
Camera with keyframe animation | keyframes: [{ frame, position, lookAt }] |
Break your concept into 3–5 scenes, each 7–15 seconds (420–900 frames at 60fps).
src/compositions/MyVideo/
├── MyVideo.tsx # Main composition with Sequence + crossfades
├── scenes/
│ ├── IntroScene.tsx
│ ├── MainScene.tsx
│ └── OutroScene.tsx
└── index.ts
import React from 'react';
import { AbsoluteFill } from 'remotion';
import { Scene3D, SystemBox, FloatingLabel, GridFloor, AnimatedCamera } from '../../components';
export const IntroScene: React.FC = () => (
<AbsoluteFill>
<Scene3D camera={{ position: [0, 3, 8] }}>
<AnimatedCamera keyframes={[
{ frame: 0, position: [0, 3, 10], lookAt: [0, 0, 0] },
{ frame: 120, position: [2, 2, 7], lookAt: [0, 0.5, 0] },
]} />
<GridFloor />
<FloatingLabel text="Hello World" position={[0, 2, 0]}
animateIn={{ startFrame: 0, durationFrames: 30 }} />
<SystemBox position={[0, 0.5, 0]} label="My Service" color="#4A90D9"
animateIn={{ startFrame: 15, durationFrames: 30 }} />
</Scene3D>
</AbsoluteFill>
);Add to src/Root.tsx:
<Composition id="MyVideo" component={MyVideo}
durationInFrames={1800} fps={60} width={1920} height={1080} />npm start # Preview in Remotion Studio
npm run render -- MyVideo out/MyVideo.mp4 # Render to MP4This repo includes .github/copilot-instructions.md with full component documentation. AI coding assistants (GitHub Copilot, Cursor, etc.) can generate complete scenes by describing what you want:
"Create a scene showing three microservices communicating through a message queue, with data flowing between them"
The AI knows every component, its props, and the conventions for positioning, timing, and color.
# Render a specific composition
npm run render:ai-dev-flow
# Render all compositions
npm run render:all
# Render with custom options
npx remotion render src/index.ts AIDevFlow out/video.mp4 --codec h264 --gl=swangleRender on AWS Lambda for faster, parallelized rendering without local GPU dependencies.
-
Deploy the Remotion Lambda function (one-time):
npx remotion lambda functions deploy --memory 2048 --disk 2048 --timeout 240
-
Set environment variables:
export AWS_ACCESS_KEY_ID=your-key export AWS_SECRET_ACCESS_KEY=your-secret export REMOTION_LAMBDA_FUNCTION_NAME=remotion-render-4-0-429-mem2048mb-disk2048mb-240sec export REMOTION_LAMBDA_REGION=us-east-1 # optional, defaults to us-east-1 export REMOTION_LAMBDA_SITE_NAME=explainer-3d # optional, defaults to explainer-3d
-
Render:
npm run render:lambda # All compositions npm run render:lambda -- --composition AIDevFlow # Single composition npx tsx src/renderer/render-all.ts --lambda --composition AIDevFlow # Direct
See the aws/ directory for required IAM policies:
remotion-lambda-role-policy.json— Attach to the Lambda execution role (S3, CloudWatch)remotion-lambda-user-policy.json— Attach to the IAM user deploying/invoking Lambda
The render.yml workflow:
- Triggers on push to
main(when source files change) or manual dispatch - Supports local and lambda render modes (select via workflow_dispatch)
- Local mode: renders in a headless environment with xvfb + Mesa
- Lambda mode: bundles, deploys to S3, renders on AWS Lambda (no GPU needed)
- Uploads the video as a GitHub Actions artifact (30-day retention)
- Optionally uploads to S3 (configure
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,S3_BUCKETsecrets)
Required secrets for Lambda mode: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, REMOTION_LAMBDA_FUNCTION_NAME
Optional vars: REMOTION_LAMBDA_REGION (default: us-east-1)
explainer-3d/
├── aws/ # IAM policies for Lambda rendering
│ ├── remotion-lambda-role-policy.json
│ └── remotion-lambda-user-policy.json
├── src/
│ ├── components/ # Reusable 3D components
│ │ ├── Scene3D.tsx # ThreeCanvas wrapper + lighting + bloom
│ │ ├── SystemBox.tsx # Labeled 3D box
│ │ ├── TokenStream.tsx # Flowing text tokens
│ │ ├── DataFlow.tsx # Particle stream between points
│ │ ├── Arrow3D.tsx # Animated directional arrow
│ │ ├── FloatingLabel.tsx# Billboard text label
│ │ ├── GlowOrb.tsx # Pulsing glowing sphere
│ │ ├── ConnectionBeam.tsx# Beam between points
│ │ ├── GridFloor.tsx # Infinite ground grid
│ │ ├── ParticleField.tsx# Ambient particles
│ │ ├── AnimatedCamera.tsx# Keyframe camera
│ │ └── index.ts # Barrel exports
│ ├── compositions/ # Video compositions
│ │ └── AIDevFlow/ # "How AI Dev Works" example
│ │ ├── AIDevFlow.tsx
│ │ ├── scenes/
│ │ │ ├── SystemPromptScene.tsx
│ │ │ ├── SkillsMergeScene.tsx
│ │ │ ├── ModelProcessScene.tsx
│ │ │ └── OutputScene.tsx
│ │ └── index.ts
│ ├── hooks/ # Animation hooks
│ │ ├── useAnimatedValue.ts
│ │ └── useScene.ts
│ ├── utils/ # Utilities
│ │ ├── colors.ts # Theme palette
│ │ ├── easing.ts # Custom easing functions
│ │ ├── layout.ts # 3D positioning helpers
│ │ ├── random.ts # Seeded RNG
│ │ └── types.ts # Shared types
│ ├── renderer/ # Batch rendering
│ │ ├── compositions.ts
│ │ ├── lambda.ts # AWS Lambda rendering
│ │ └── render-all.ts
│ ├── Root.tsx # Remotion root
│ └── index.ts # Entry point
├── tests/ # Vitest test suite
├── .github/
│ ├── workflows/
│ │ ├── ci.yml # Test + lint
│ │ └── render.yml # Video rendering
│ └── copilot-instructions.md
├── remotion.config.ts
├── vitest.config.ts
├── tsconfig.json
└── package.json
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage report (80% threshold)
npm run build # Type-check
npm run lint # ESLint| Color | Hex | Usage |
|---|---|---|
| 🔵 Primary | #4A90D9 |
Systems, connections |
| 🟣 Secondary | #7B61FF |
AI, models, processing |
| 🟢 Accent | #00D4AA |
Data, tokens, output |
| 🟡 Warning | #FFB800 |
Arrows, highlights |
| 🔴 Error | #FF4757 |
Alerts |
| 🌸 Pink | #FF6B9D |
Special elements |
| ⬛ Background | #0A0A1A |
Scene background |
- Fork the repository
- Create a feature branch (
git checkout -b feat/my-composition) - Add your composition in
src/compositions/ - Register it in
Root.tsxandrenderer/compositions.ts - Add tests
- Submit a PR
MIT — Hector Flores Rocha (htekdev)