Motion canvas skill

Complete production-ready guide for Motion Canvas with ESM/CommonJS workarounds, full setup templates, and troubleshooting for programmatic video creation using TypeScript

by davila7·MIT license·★ 32,299 Stars on the repo·GitHub ↗

Use now

Files of Motion canvas

davila7/main1 file shown
SKILL.md
Show the full text360 lines

Motion Canvas - Production-Ready Video Creation with TypeScript

Complete production-ready skill for creating programmatic videos using Motion Canvas, including critical ESM/CommonJS workarounds, full configuration templates, and comprehensive troubleshooting.

⚠️ CRITICAL: ESM/CommonJS Interoperability Issue

IMPORTANT: The @motion-canvas/vite-plugin package is distributed as CommonJS, which causes import errors in modern ESM projects. The standard import motionCanvas from '@motion-canvas/vite-plugin' WILL NOT WORK.

You MUST use the createRequire workaround documented in the Setup section below.

When to use

Use this skill whenever you are dealing with Motion Canvas code to obtain domain-specific knowledge about:

  • Creating animated videos using TypeScript and generator functions
  • Building animations with signals and reactive values
  • Working with vector graphics and Canvas API
  • Synchronizing animations with voice-overs and audio
  • Using the real-time preview editor for instant feedback
  • Implementing procedural animations with flow control
  • Creating informative visualizations and diagrams
  • Animating text, shapes, and custom components
  • Setting up Motion Canvas projects from scratch with correct configuration
  • Troubleshooting common setup and build errors

Core Concepts

Motion Canvas allows you to create videos using:

  • Generator Functions: Describe animations using JavaScript generators with yield* syntax
  • Signals: Reactive values that automatically update dependent properties
  • Real-time Preview: Live editor with instant preview powered by Vite
  • TypeScript-First: Write animations in TypeScript with full IDE support
  • Canvas API: Leverage 2D Canvas for high-performance vector rendering
  • Audio Synchronization: Sync animations precisely with voice-overs

Complete Setup Guide

Step 1: Initialize Project
# Create project directory
mkdir my-motion-canvas-project
cd my-motion-canvas-project

# Initialize package.json
npm init -y
Step 2: Configure package.json for ESM

CRITICAL: Add "type": "module" to enable ESM imports.

{
  "name": "my-motion-canvas-project",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  }
}
Step 3: Install ALL Required Dependencies

CRITICAL: Must include @motion-canvas/ui - the plugin will fail without it.

npm install --save-dev @motion-canvas/core @motion-canvas/2d @motion-canvas/vite-plugin @motion-canvas/ui vite typescript
Step 4: Create Project Structure
my-motion-canvas-project/
├── package.json          # "type": "module" required
├── vite.config.js        # Use .js NOT .ts (see Step 5)
├── tsconfig.json         # TypeScript configuration
├── index.html            # HTML entry point
└── src/
    ├── project.ts        # Project configuration with scenes
    └── scenes/
        └── example.tsx   # Animation scene
Step 5: Create vite.config.js with ESM/CommonJS Workaround

CRITICAL: Use vite.config.js (NOT .ts) with the createRequire workaround.

File: vite.config.js

import {defineConfig} from 'vite';
import {createRequire} from 'module';

// WORKAROUND: @motion-canvas/vite-plugin is CommonJS, must use require
const require = createRequire(import.meta.url);
const motionCanvasModule = require('@motion-canvas/vite-plugin');
const motionCanvas = motionCanvasModule.default || motionCanvasModule;

export default defineConfig({
  plugins: [
    motionCanvas({
      project: './src/project.ts',
    }),
  ],
});

Why .js instead of .ts?

  • Vite config runs before TypeScript compilation
  • The createRequire workaround works reliably in plain JavaScript
  • Avoids additional type resolution complexity
Step 6: Create tsconfig.json

CRITICAL: Include esModuleInterop and allowSyntheticDefaultImports.

File: tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ES2020",
    "lib": ["ES2020", "DOM"],
    "jsx": "react-jsx",
    "jsxImportSource": "@motion-canvas/2d/lib",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}
Step 7: Create index.html

File: index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Motion Canvas Project</title>
</head>
<body>
  <div id="root"></div>
  <script type="module" src="/src/project.ts"></script>
</body>
</html>
Step 8: Create src/project.ts

File: src/project.ts

import {makeProject} from '@motion-canvas/core';
import example from './scenes/example?scene';

export default makeProject({
  scenes: [example],
});
Step 9: Create First Animation Scene

File: src/scenes/example.tsx

import {makeScene2D} from '@motion-canvas/2d/lib/scenes';
import {Circle} from '@motion-canvas/2d/lib/components';
import {createRef} from '@motion-canvas/core/lib/utils';
import {all} from '@motion-canvas/core/lib/flow';

export default makeScene2D(function* (view) {
  const circleRef = createRef<Circle>();

  view.add(
    <Circle
      ref={circleRef}
      size={70}
      fill="#e13238"
    />,
  );

  // Animate circle size and position
  yield* circleRef().size(140, 1);
  yield* circleRef().position.x(300, 1);
  yield* circleRef().fill('#e6a700', 1);

  // Parallel animations
  yield* all(
    circleRef().scale(1.5, 0.5),
    circleRef().rotation(360, 1)
  );
});
Step 10: Run Development Server
npm run dev

Open browser at http://localhost:5173 to see the Motion Canvas editor.

Troubleshooting

Error: TypeError: motionCanvas is not a function

Cause: ESM/CommonJS interoperability issue with @motion-canvas/vite-plugin

Solution: Use the createRequire workaround in vite.config.js (see Step 5)

// ❌ WRONG - Will not work
import motionCanvas from '@motion-canvas/vite-plugin';

// ✅ CORRECT - Use createRequire
import {createRequire} from 'module';
const require = createRequire(import.meta.url);
const motionCanvasModule = require('@motion-canvas/vite-plugin');
const motionCanvas = motionCanvasModule.default || motionCanvasModule;
Error: Cannot find module '@motion-canvas/ui'

Cause: Missing required dependency

Solution: Install the UI package:

npm install --save-dev @motion-canvas/ui
Error: Property 'default' does not exist on type ...

Cause: TypeScript configuration missing ESM interop settings

Solution: Add to tsconfig.json:

{
  "compilerOptions": {
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true
  }
}
Warning: The CJS build of Vite's Node API is deprecated

Status: This is a known warning and can be safely ignored. It appears because @motion-canvas/vite-plugin is CommonJS. The workaround ensures functionality despite the warning.

Error: Failed to resolve import "*.tsx?scene"

Cause: Vite plugin not properly loaded or configured

Solution:

  1. Verify vite.config.js has the correct workaround
  2. Check project path points to correct file: './src/project.ts'
  3. Ensure scene imports use ?scene suffix: import example from './scenes/example?scene';
Build fails with TypeScript errors

Solution:

  1. Verify tsconfig.json includes all required options (see Step 6)
  2. Check jsxImportSource is set to @motion-canvas/2d/lib
  3. Ensure all dependencies are installed

How to use

Read individual rule files for detailed explanations and code examples:

Core Animation Concepts

For additional topics like scenes, shapes, text rendering, audio synchronization, and advanced features, refer to the comprehensive Motion Canvas official documentation.

Complete Working Example

This is a complete, tested project structure that works out of the box:

my-motion-canvas-project/
├── package.json
│   {
│     "name": "my-motion-canvas-project",
│     "type": "module",
│     "scripts": {
│       "dev": "vite",
│       "build": "vite build"
│     },
│     "devDependencies": {
│       "@motion-canvas/core": "^3.0.0",
│       "@motion-canvas/2d": "^3.0.0",
│       "@motion-canvas/vite-plugin": "^3.0.0",
│       "@motion-canvas/ui": "^3.0.0",
│       "vite": "^5.0.0",
│       "typescript": "^5.0.0"
│     }
│   }
│
├── vite.config.js (with createRequire workaround)
├── tsconfig.json (with esModuleInterop)
├── index.html
└── src/
    ├── project.ts (makeProject with scenes array)
    └── scenes/
        └── example.tsx (makeScene2D with animations)

Best Practices

  1. Always use the createRequire workaround - Don't try standard ESM imports for the Vite plugin
  2. Use vite.config.js not .ts - Avoids additional compilation complexity
  3. Include all dependencies - Don't forget @motion-canvas/ui
  4. Use generator functions - All scene animations should use function* and yield* syntax
  5. Leverage signals - Create reactive dependencies between properties
  6. Think in durations - Specify animation duration in seconds as the second parameter
  7. Use refs for control - Create references to nodes for precise animation control
  8. Preview frequently - Take advantage of the real-time editor for instant feedback
  9. Organize scenes - Break complex animations into multiple scenes
  10. Type everything - Use TypeScript for better IDE support and fewer errors

Common Pitfalls to Avoid

  1. ❌ Forgetting "type": "module" in package.json
  2. ❌ Using standard import for @motion-canvas/vite-plugin
  3. ❌ Not installing @motion-canvas/ui
  4. ❌ Missing esModuleInterop in tsconfig.json
  5. ❌ Using vite.config.ts instead of vite.config.js
  6. ❌ Forgetting ?scene suffix in scene imports

Resources

1---
2name: motion-canvas
3description: Complete production-ready guide for Motion Canvas with ESM/CommonJS workarounds, full setup templates, and troubleshooting for programmatic video creation using TypeScript
4version: 2.0.0
5author: motion-canvas
6repo: https://github.com/motion-canvas/motion-canvas
7license: MIT
8tags: [Video, TypeScript, Animation, Motion Canvas, Signals, Generators, Canvas API, Vector, Audio Sync, Vite, ESM]
9dependencies: ["@motion-canvas/core>=3.0.0", "@motion-canvas/2d>=3.0.0", "@motion-canvas/ui>=3.0.0", "@motion-canvas/vite-plugin>=3.0.0"]
10---
11 
12# Motion Canvas - Production-Ready Video Creation with TypeScript
13 
14Complete production-ready skill for creating programmatic videos using Motion Canvas, including critical ESM/CommonJS workarounds, full configuration templates, and comprehensive troubleshooting.
15 
16## ⚠️ CRITICAL: ESM/CommonJS Interoperability Issue
17 
18**IMPORTANT**: The `@motion-canvas/vite-plugin` package is distributed as CommonJS, which causes import errors in modern ESM projects. The standard `import motionCanvas from '@motion-canvas/vite-plugin'` **WILL NOT WORK**.
19 
20You MUST use the `createRequire` workaround documented in the Setup section below.
21 
22## When to use
23 
24Use this skill whenever you are dealing with Motion Canvas code to obtain domain-specific knowledge about:
25 
26- Creating animated videos using TypeScript and generator functions
27- Building animations with signals and reactive values
28- Working with vector graphics and Canvas API
29- Synchronizing animations with voice-overs and audio
30- Using the real-time preview editor for instant feedback
31- Implementing procedural animations with flow control
32- Creating informative visualizations and diagrams
33- Animating text, shapes, and custom components
34- **Setting up Motion Canvas projects from scratch with correct configuration**
35- **Troubleshooting common setup and build errors**
36 
37## Core Concepts
38 
39Motion Canvas allows you to create videos using:
40- **Generator Functions**: Describe animations using JavaScript generators with `yield*` syntax
41- **Signals**: Reactive values that automatically update dependent properties
42- **Real-time Preview**: Live editor with instant preview powered by Vite
43- **TypeScript-First**: Write animations in TypeScript with full IDE support
44- **Canvas API**: Leverage 2D Canvas for high-performance vector rendering
45- **Audio Synchronization**: Sync animations precisely with voice-overs
46 
47## Complete Setup Guide
48 
49### Step 1: Initialize Project
50 
51```bash
52# Create project directory
53mkdir my-motion-canvas-project
54cd my-motion-canvas-project
55 
56# Initialize package.json
57npm init -y
58```
59 
60### Step 2: Configure package.json for ESM
61 
62**CRITICAL**: Add `"type": "module"` to enable ESM imports.
63 
64```json
65{
66 "name": "my-motion-canvas-project",
67 "version": "1.0.0",
68 "type": "module",
69 "scripts": {
70 "dev": "vite",
71 "build": "vite build",
72 "preview": "vite preview"
73 }
74}
75```
76 
77### Step 3: Install ALL Required Dependencies
78 
79**CRITICAL**: Must include `@motion-canvas/ui` - the plugin will fail without it.
80 
81```bash
82npm install --save-dev @motion-canvas/core @motion-canvas/2d @motion-canvas/vite-plugin @motion-canvas/ui vite typescript
83```
84 
85### Step 4: Create Project Structure
86 
87```
88my-motion-canvas-project/
89├── package.json # "type": "module" required
90├── vite.config.js # Use .js NOT .ts (see Step 5)
91├── tsconfig.json # TypeScript configuration
92├── index.html # HTML entry point
93└── src/
94 ├── project.ts # Project configuration with scenes
95 └── scenes/
96 └── example.tsx # Animation scene
97```
98 
99### Step 5: Create vite.config.js with ESM/CommonJS Workaround
100 
101**CRITICAL**: Use `vite.config.js` (NOT `.ts`) with the `createRequire` workaround.
102 
103**File: `vite.config.js`**
104```javascript
105import {defineConfig} from 'vite';
106import {createRequire} from 'module';
107 
108// WORKAROUND: @motion-canvas/vite-plugin is CommonJS, must use require
109const require = createRequire(import.meta.url);
110const motionCanvasModule = require('@motion-canvas/vite-plugin');
111const motionCanvas = motionCanvasModule.default || motionCanvasModule;
112 
113export default defineConfig({
114 plugins: [
115 motionCanvas({
116 project: './src/project.ts',
117 }),
118 ],
119});
120```
121 
122**Why .js instead of .ts?**
123- Vite config runs before TypeScript compilation
124- The `createRequire` workaround works reliably in plain JavaScript
125- Avoids additional type resolution complexity
126 
127### Step 6: Create tsconfig.json
128 
129**CRITICAL**: Include `esModuleInterop` and `allowSyntheticDefaultImports`.
130 
131**File: `tsconfig.json`**
132```json
133{
134 "compilerOptions": {
135 "target": "ES2020",
136 "module": "ES2020",
137 "lib": ["ES2020", "DOM"],
138 "jsx": "react-jsx",
139 "jsxImportSource": "@motion-canvas/2d/lib",
140 "moduleResolution": "node",
141 "esModuleInterop": true,
142 "allowSyntheticDefaultImports": true,
143 "strict": true,
144 "skipLibCheck": true,
145 "resolveJsonModule": true,
146 "isolatedModules": true,
147 "noEmit": true
148 },
149 "include": ["src/**/*"],
150 "exclude": ["node_modules"]
151}
152```
153 
154### Step 7: Create index.html
155 
156**File: `index.html`**
157```html
158<!DOCTYPE html>
159<html lang="en">
160<head>
161 <meta charset="UTF-8">
162 <meta name="viewport" content="width=device-width, initial-scale=1.0">
163 <title>Motion Canvas Project</title>
164</head>
165<body>
166 <div id="root"></div>
167 <script type="module" src="/src/project.ts"></script>
168</body>
169</html>
170```
171 
172### Step 8: Create src/project.ts
173 
174**File: `src/project.ts`**
175```typescript
176import {makeProject} from '@motion-canvas/core';
177import example from './scenes/example?scene';
178 
179export default makeProject({
180 scenes: [example],
181});
182```
183 
184### Step 9: Create First Animation Scene
185 
186**File: `src/scenes/example.tsx`**
187```typescript
188import {makeScene2D} from '@motion-canvas/2d/lib/scenes';
189import {Circle} from '@motion-canvas/2d/lib/components';
190import {createRef} from '@motion-canvas/core/lib/utils';
191import {all} from '@motion-canvas/core/lib/flow';
192 
193export default makeScene2D(function* (view) {
194 const circleRef = createRef<Circle>();
195 
196 view.add(
197 <Circle
198 ref={circleRef}
199 size={70}
200 fill="#e13238"
201 />,
202 );
203 
204 // Animate circle size and position
205 yield* circleRef().size(140, 1);
206 yield* circleRef().position.x(300, 1);
207 yield* circleRef().fill('#e6a700', 1);
208 
209 // Parallel animations
210 yield* all(
211 circleRef().scale(1.5, 0.5),
212 circleRef().rotation(360, 1)
213 );
214});
215```
216 
217### Step 10: Run Development Server
218 
219```bash
220npm run dev
221```
222 
223Open browser at `http://localhost:5173` to see the Motion Canvas editor.
224 
225## Troubleshooting
226 
227### Error: `TypeError: motionCanvas is not a function`
228 
229**Cause**: ESM/CommonJS interoperability issue with `@motion-canvas/vite-plugin`
230 
231**Solution**: Use the `createRequire` workaround in `vite.config.js` (see Step 5)
232 
233```javascript
234// ❌ WRONG - Will not work
235import motionCanvas from '@motion-canvas/vite-plugin';
236 
237// ✅ CORRECT - Use createRequire
238import {createRequire} from 'module';
239const require = createRequire(import.meta.url);
240const motionCanvasModule = require('@motion-canvas/vite-plugin');
241const motionCanvas = motionCanvasModule.default || motionCanvasModule;
242```
243 
244### Error: `Cannot find module '@motion-canvas/ui'`
245 
246**Cause**: Missing required dependency
247 
248**Solution**: Install the UI package:
249```bash
250npm install --save-dev @motion-canvas/ui
251```
252 
253### Error: `Property 'default' does not exist on type ...`
254 
255**Cause**: TypeScript configuration missing ESM interop settings
256 
257**Solution**: Add to `tsconfig.json`:
258```json
259{
260 "compilerOptions": {
261 "esModuleInterop": true,
262 "allowSyntheticDefaultImports": true
263 }
264}
265```
266 
267### Warning: `The CJS build of Vite's Node API is deprecated`
268 
269**Status**: This is a known warning and can be safely ignored. It appears because `@motion-canvas/vite-plugin` is CommonJS. The workaround ensures functionality despite the warning.
270 
271### Error: `Failed to resolve import "*.tsx?scene"`
272 
273**Cause**: Vite plugin not properly loaded or configured
274 
275**Solution**:
2761. Verify `vite.config.js` has the correct workaround
2772. Check `project` path points to correct file: `'./src/project.ts'`
2783. Ensure scene imports use `?scene` suffix: `import example from './scenes/example?scene';`
279 
280### Build fails with TypeScript errors
281 
282**Solution**:
2831. Verify `tsconfig.json` includes all required options (see Step 6)
2842. Check `jsxImportSource` is set to `@motion-canvas/2d/lib`
2853. Ensure all dependencies are installed
286 
287## How to use
288 
289Read individual rule files for detailed explanations and code examples:
290 
291### Core Animation Concepts
292- **[references/generators.md](references/generators.md)** - Generator functions for describing animations
293- **[references/signals.md](references/signals.md)** - Reactive signals for dynamic properties and dependencies
294- **[references/animations.md](references/animations.md)** - Tweening properties and creating smooth animations
295 
296For additional topics like scenes, shapes, text rendering, audio synchronization, and advanced features, refer to the comprehensive [Motion Canvas official documentation](https://motioncanvas.io/docs).
297 
298## Complete Working Example
299 
300This is a complete, tested project structure that works out of the box:
301 
302```
303my-motion-canvas-project/
304├── package.json
305│ {
306│ "name": "my-motion-canvas-project",
307│ "type": "module",
308│ "scripts": {
309│ "dev": "vite",
310│ "build": "vite build"
311│ },
312│ "devDependencies": {
313│ "@motion-canvas/core": "^3.0.0",
314│ "@motion-canvas/2d": "^3.0.0",
315│ "@motion-canvas/vite-plugin": "^3.0.0",
316│ "@motion-canvas/ui": "^3.0.0",
317│ "vite": "^5.0.0",
318│ "typescript": "^5.0.0"
319│ }
320│ }
321│
322├── vite.config.js (with createRequire workaround)
323├── tsconfig.json (with esModuleInterop)
324├── index.html
325└── src/
326 ├── project.ts (makeProject with scenes array)
327 └── scenes/
328 └── example.tsx (makeScene2D with animations)
329```
330 
331## Best Practices
332 
3331. **Always use the createRequire workaround** - Don't try standard ESM imports for the Vite plugin
3342. **Use vite.config.js not .ts** - Avoids additional compilation complexity
3353. **Include all dependencies** - Don't forget `@motion-canvas/ui`
3364. **Use generator functions** - All scene animations should use `function*` and `yield*` syntax
3375. **Leverage signals** - Create reactive dependencies between properties
3386. **Think in durations** - Specify animation duration in seconds as the second parameter
3397. **Use refs for control** - Create references to nodes for precise animation control
3408. **Preview frequently** - Take advantage of the real-time editor for instant feedback
3419. **Organize scenes** - Break complex animations into multiple scenes
34210. **Type everything** - Use TypeScript for better IDE support and fewer errors
343 
344## Common Pitfalls to Avoid
345 
3461. ❌ Forgetting `"type": "module"` in package.json
3472. ❌ Using standard import for `@motion-canvas/vite-plugin`
3483. ❌ Not installing `@motion-canvas/ui`
3494. ❌ Missing `esModuleInterop` in tsconfig.json
3505. ❌ Using `vite.config.ts` instead of `vite.config.js`
3516. ❌ Forgetting `?scene` suffix in scene imports
352 
353## Resources
354 
355- **Documentation**: https://motioncanvas.io/docs
356- **Repository**: https://github.com/motion-canvas/motion-canvas
357- **Examples**: https://motioncanvas.io/docs/quickstart
358- **Community**: Discord and GitHub Discussions
359- **License**: MIT
360 

Discussion