STUDIO
Vide LogoVIDE // DOCS

Quickstart Guide

GETTING STARTED

Vide compiles a strictly deterministic subset of JavaScript. All elements are structured as nodes with local timelines, assembled via parallel and sequence composition.

01 // NODES

Declare visual elements (`src`, `text`, `circle`, `rect`).

02 // MOTION

Attach tweens via `animate()` and `fade()`.

03 // TIMELINES

Layer with `parallel()` or sequence with `sequence()`.

04 // OUTPUT

Pass the root node to `output()` to render.

// VIDE DSL
// 1. Assets
const bg = src("./assets/river.mp4", { in: 0, out: 6 });
const title = text("VIDE MOTION", {
  x: 960,
  y: 540,
  fontSize: 64,
  fontFamily: "Rajdhani",
  fill: "#00f0ff",
  duration: 5
});

// 2. Animations
animate(title, "y", { from: 600, to: 540, duration: 1.0, at: "start", ease: "easeOutCubic" });
fade(title, { in: 0.8, out: 0.8 });

// 3. Composition
const main = parallel([
  at(0, bg),
  at(1.0, title)
]);

// 4. Output
output(main, {
  width: 1920,
  height: 1080,
  fps: 60,
  backgroundColor: "#02050b"
});

1. The 4-Step Mental Model

CORE PRINCIPLE

Vide scripts are deterministic JavaScript evaluated with Acorn into an immutable AST graph. Every video is created in four simple stages:

// VIDE DSL
// 1. ASSETS & SHAPES: Declare your visual layers
const bg = src("./assets/bg.mp4", { in: 0, out: 8 });
const title = text("CYBER CORE", { fontSize: 64, fill: "#00f0ff", duration: 5 });
const formula = math("e^{i\\theta} = \\cos\\theta + i\\sin\\theta", { fontSize: 48, fill: "#ffffff", duration: 5 });

// 2. ANIMATION: Attach tweens & transitions
animate(title, "y", { from: 600, to: 540, duration: 1.0, ease: "easeOutCubic" });
fade(title, { in: 0.8, out: 0.8 });

// 3. COMPOSITION: Layer simultaneously (parallel) or in series (sequence)
const main = parallel([
  at(0, bg),
  at(1.5, title),
  at(2.0, formula)
]);

// 4. OUTPUT: Designate root scene and render resolution
output(main, { width: 1920, height: 1080, fps: 60, backgroundColor: "#02050b" });

math(tex, options)

LATEX MATH

Renders publication-quality mathematical formulas on the 2D canvas using KaTeX.

math(tex: string, options?: MathOptions): MathNode
PARAMTYPEDESCRIPTION
texstringLaTeX mathematical expression
fontSizenumberEquation font size in pixels (default: 48)
fillstringFormula color (default: "#ffffff")
displayModebooleanRender as block display equation (default: true)
// VIDE DSL
// Euler's Formula & Derivatives
const euler = math("e^{i\\theta} = \\cos\\theta + i\\sin\\theta", {
  x: 960,
  y: 540,
  fontSize: 54,
  fill: "#00f0ff",
  duration: 6
});

const derivative = math("\\frac{d}{dx}\\left(e^x\\right) = e^x", {
  x: 960,
  y: 650,
  fontSize: 48,
  fill: "#ff9900",
  duration: 6
});

src(path, options)

MEDIA

Loads local or remote video/image assets with optional sub-second trimming and volume control.

src(path: string, options?: SrcOptions): SrcNode
PARAMTYPEDESCRIPTION
pathstringFile system relative path or URL
innumberIn-point trim timestamp in seconds
outnumberOut-point trim timestamp in seconds
volumenumberAudio volume (0.0 to 1.0)
// VIDE DSL
// Trim river.mp4 from second 2 to second 12 (calculated duration = 10s)
const video = src("./assets/river.mp4", { in: 2, out: 12, volume: 0.8 });

// Still image with 5-second duration
const logo = src("./assets/logo.png", { x: 960, y: 300, scale: 0.5, duration: 5 });

Primitive Shapes & SVG Paths

VECTORS & PATHS

High-performance geometric primitives and SVG paths drawn directly onto the 2D canvas with stroke trimming and dash offset support.

// VIDE DSL
// SVG Path with write-on trim animation
const wave = path("M -300 0 C -150 -200 150 200 300 0", {
  x: 540, y: 960,
  stroke: "#00f0ff", strokeWidth: 4, fill: "none",
  trimEnd: 0, duration: 5
});
animate(wave, "trimEnd", { from: 0, to: 1.0, duration: 2.0, ease: "easeInOutCubic" });

// Circle & Ellipse
const orb = circle(80, { x: 960, y: 540, fill: "#00f0ff", shadowColor: "#00f0ff", shadowBlur: 20 });
const badge = ellipse(120, 60, { x: 400, y: 200, stroke: "#ff9900", strokeWidth: 2 });

// Rounded Rectangle
const card = rect(400, 240, { x: 760, y: 420, cornerRadius: 16, fill: "rgba(0,240,255,0.1)", stroke: "#00f0ff" });

// Technical HUD Line with Arrowhead
const callout = line([200, 300], [500, 400], { stroke: "#00ffaa", strokeWidth: 2, arrow: "end", duration: 5 });

parallel(items, options)

LAYERING

Composites multiple visual layers simultaneously. Uses Painter’s algorithm: items at the end of the array render on top.

parallel(items: (Node | NodePlacement)[], options?: BaseNodeOptions): ParallelNode
// VIDE DSL
const main = parallel([
  at(0, backgroundVideo),
  at(1.5, titleOverlay),
  at(after(titleOverlay, -0.5), subtitleText) // Starts 0.5s before title ends
]);

sequence(items, options)

SERIAL

Plays clips and scenes in serial order back-to-back. Supports gap pauses and negative offset transitions.

sequence(items: (Node | GapItem | OffsetItem)[], options?: BaseNodeOptions): SequenceNode
// VIDE DSL
const movie = sequence([
  introScene,
  gap(0.5),     // 0.5s pause
  mainScene,
  offset(-1.0), // Starts 1.0s early for a smooth crossfade overlap
  creditsScene
]);

animate() & Path Trimming

MOTION & TRIMMING

Attach property tweens, path drawing animations (trimStart, trimEnd, dashOffset), and Penner easing curves.

// VIDE DSL
// Grow curve / write-on path from 0% to 100%
animate(curvePath, "trimEnd", { from: 0, to: 1.0, duration: 2.0, at: "start", ease: "easeInOutCubic" });

// Flowing dash traveling wave
animate(laserBeam, "dashOffset", { from: 0, to: -200, duration: 4.0, ease: "linear" });

// Slide and scale animation
animate(title, "y", { from: 700, to: 540, duration: 1.2, at: "start", ease: "easeOutCubic" });
fade(title, { in: 0.8, out: 0.8 });

Gradients & measureText()

SHADERS & SIZING

Create reusable linear/radial gradient fills and calculate dynamic text dimensions before layout.

// VIDE DSL
// Linear gradient
const neonGrad = linearGradient({
  from: [-200, 0],
  to: [200, 0],
  stops: [[0.0, "#00f0ff"], [1.0, "#00ffaa"]]
});

// Dynamic measured text bounding box
const titleString = "DYNAMIC BADGE";
const metrics = measureText(titleString, 48, "JetBrains Mono");

const box = rect(metrics.width + 40, metrics.height + 20, {
  x: 960 - (metrics.width + 40) / 2,
  y: 500,
  fill: "rgba(0,240,255,0.1)",
  stroke: "#00f0ff"
});

output(rootNode, options)

RENDER

Designates the composition root and defines the video scene configuration.

// VIDE DSL
output(main, {
  width: 1920,
  height: 1080,
  fps: 60,
  backgroundColor: "#02050b"
});

Ready-to-Use Templates

STARTER PRESETS

Copy or launch pre-composed motion design recipes straight into your workspace.

A. KINETIC CYBER TITLE

// VIDE DSL
// Kinetic Cyber Title
const glowGrad = linearGradient({
  from: [-200, 0],
  to: [200, 0],
  stops: [[0, "#00f0ff"], [0.5, "#ffffff"], [1, "#00ffaa"]]
});

const title = text("QUANTUM CORE", {
  x: 960,
  y: 540,
  fontSize: 72,
  fontFamily: "JetBrains Mono",
  fill: glowGrad,
  textAlign: "center",
  shadowColor: "#00f0ff",
  shadowBlur: 30,
  duration: 6
});

const sub = text("// 60 FPS DETERMINISTIC CANVAS //", {
  x: 960,
  y: 620,
  fontSize: 20,
  fontFamily: "JetBrains Mono",
  fill: "#ff9900",
  textAlign: "center",
  duration: 5.5
});

animate(title, "y", { from: 600, to: 540, duration: 1.2, at: "start", ease: "easeOutCubic" });
fade(title, { in: 0.8, out: 0.8 });

animate(sub, "y", { from: 650, to: 620, duration: 1.0, at: "start", ease: "easeOutCubic" });
fade(sub, { in: 1.0, out: 0.8 });

const main = parallel([
  at(0, title),
  at(0.4, sub)
]);

output(main, { width: 1920, height: 1080, fps: 60, backgroundColor: "#02050b" });

B. TELEMETRY GAUGES & COUNTERS

// VIDE DSL
// Telemetry Gauge Ring
const gauge = arc(160, 0, 6.283, {
  x: 960,
  y: 540,
  innerRadius: 150,
  fill: "#00f0ff",
  shadowColor: "#00f0ff",
  shadowBlur: 20,
  duration: 6
});

const centerText = text("100%", {
  x: 960,
  y: 540,
  fontSize: 48,
  fontFamily: "JetBrains Mono",
  fill: "#ffffff",
  textAlign: "center",
  duration: 6
});

animate(gauge, "endAngle", { from: 0.1, to: 6.283, duration: 2.0, at: "start", ease: "easeInOutCubic" });
fade(gauge, { in: 0.5, out: 0.5 });
fade(centerText, { in: 0.5, out: 0.5 });

const main = parallel([
  at(0, gauge),
  at(0, centerText)
]);

output(main, { width: 1920, height: 1080, fps: 60, backgroundColor: "#02050b" });

C. EMOTIVE CAPSULE AVATAR (MORPHING EYES)

// VIDE DSL
// ============================================================================
// VIDE EMOTIVE AVATAR // PARAMETRIC CAPSULE EYE EMOTION MORPHING
// 1920x1080 @ 60 FPS // DETERMINISTIC PROCEDURAL CHARACTER RIG
// ============================================================================

const DURATION = 16.0;
const CX = 960;
const CY = 490;
const LX = 860;
const RX = 1060;

const COLOR_CYAN = "#00f0ff";
const COLOR_FACE_BG = "#0b1220";
const COLOR_CHEEK = "rgba(255, 70, 130, 0.4)";

// ----------------------------------------------------------------------------
// 1. VISOR & HOLOGRAPHIC FACE BASE
// ----------------------------------------------------------------------------
const faceBackdrop = circle(260, {
  x: CX,
  y: CY,
  fill: COLOR_FACE_BG,
  stroke: "rgba(0, 240, 255, 0.35)",
  strokeWidth: 3,
  shadowColor: COLOR_CYAN,
  shadowBlur: 30,
  duration: DURATION
});

const telemetryRing = arc(280, 0, 5.8, {
  x: CX,
  y: CY,
  innerRadius: 276,
  fill: "rgba(0, 240, 255, 0.5)",
  duration: DURATION
});

animate(telemetryRing, "rotation", { from: 0, to: 6.283, duration: DURATION, ease: "linear" });

const cheekLeft = circle(26, { x: 770, y: 535, fill: COLOR_CHEEK, opacity: 0, duration: DURATION });
const cheekRight = circle(26, { x: 1150, y: 535, fill: COLOR_CHEEK, opacity: 0, duration: DURATION });

// Blush appears during Joy phase (11.8s to 14.2s)
animate(cheekLeft, "opacity", { from: 0, to: 0.85, duration: 0.4, at: 11.8, ease: "easeOutCubic" });
animate(cheekLeft, "opacity", { from: 0.85, to: 0, duration: 0.4, at: 14.2, ease: "easeOutCubic" });
animate(cheekRight, "opacity", { from: 0, to: 0.85, duration: 0.4, at: 11.8, ease: "easeOutCubic" });
animate(cheekRight, "opacity", { from: 0.85, to: 0, duration: 0.4, at: 14.2, ease: "easeOutCubic" });

// ----------------------------------------------------------------------------
// 2. PARAMETRIC MORPHING CAPSULE EYES
// ----------------------------------------------------------------------------
const leftEye = rect(46, 116, {
  x: LX,
  y: CY,
  anchor: "center",
  cornerRadius: 23,
  fill: COLOR_CYAN,
  shadowColor: COLOR_CYAN,
  shadowBlur: 24,
  duration: DURATION
});

const rightEye = rect(46, 116, {
  x: RX,
  y: CY,
  anchor: "center",
  cornerRadius: 23,
  fill: COLOR_CYAN,
  shadowColor: COLOR_CYAN,
  shadowBlur: 24,
  duration: DURATION
});

// --- Phase 1: Bootup & Double Blink (0.0s - 2.0s) ---
animate(leftEye, "height", { from: 0, to: 116, duration: 0.5, at: 0.0, ease: "easeOutBack" });
animate(rightEye, "height", { from: 0, to: 116, duration: 0.5, at: 0.0, ease: "easeOutBack" });

animate(leftEye, "height", { from: 116, to: 8, duration: 0.08, at: 1.10, ease: "easeInQuad" });
animate(leftEye, "height", { from: 8, to: 116, duration: 0.12, at: 1.18, ease: "easeOutBack" });
animate(rightEye, "height", { from: 116, to: 8, duration: 0.08, at: 1.10, ease: "easeInQuad" });
animate(rightEye, "height", { from: 8, to: 116, duration: 0.12, at: 1.18, ease: "easeOutBack" });

animate(leftEye, "height", { from: 116, to: 8, duration: 0.08, at: 1.50, ease: "easeInQuad" });
animate(leftEye, "height", { from: 8, to: 116, duration: 0.12, at: 1.58, ease: "easeOutBack" });
animate(rightEye, "height", { from: 116, to: 8, duration: 0.08, at: 1.50, ease: "easeInQuad" });
animate(rightEye, "height", { from: 8, to: 116, duration: 0.12, at: 1.58, ease: "easeOutBack" });

// --- Phase 2: Surprise & Curiosity (2.0s - 4.2s) -> Spherical Dilation ---
animate(leftEye, "width", { from: 46, to: 92, duration: 0.4, at: 2.0, ease: "easeOutBack" });
animate(leftEye, "height", { from: 116, to: 92, duration: 0.4, at: 2.0, ease: "easeOutBack" });
animate(leftEye, "cornerRadius", { from: 23, to: 46, duration: 0.4, at: 2.0, ease: "easeOutBack" });
animate(leftEye, "y", { from: CY, to: CY - 20, duration: 0.4, at: 2.0, ease: "easeOutCubic" });

animate(rightEye, "width", { from: 46, to: 92, duration: 0.4, at: 2.0, ease: "easeOutBack" });
animate(rightEye, "height", { from: 116, to: 92, duration: 0.4, at: 2.0, ease: "easeOutBack" });
animate(rightEye, "cornerRadius", { from: 23, to: 46, duration: 0.4, at: 2.0, ease: "easeOutBack" });
animate(rightEye, "y", { from: CY, to: CY - 20, duration: 0.4, at: 2.0, ease: "easeOutCubic" });

// --- Phase 3: Suspicion & Scanning Glance (4.2s - 6.8s) -> Slit Glances ---
animate(leftEye, "width", { from: 92, to: 64, duration: 0.4, at: 4.2, ease: "easeOutCubic" });
animate(leftEye, "height", { from: 92, to: 24, duration: 0.4, at: 4.2, ease: "easeOutCubic" });
animate(leftEye, "cornerRadius", { from: 46, to: 12, duration: 0.4, at: 4.2, ease: "easeOutCubic" });
animate(leftEye, "y", { from: CY - 20, to: CY, duration: 0.4, at: 4.2, ease: "easeOutCubic" });

animate(rightEye, "width", { from: 92, to: 64, duration: 0.4, at: 4.2, ease: "easeOutCubic" });
animate(rightEye, "height", { from: 92, to: 24, duration: 0.4, at: 4.2, ease: "easeOutCubic" });
animate(rightEye, "cornerRadius", { from: 46, to: 12, duration: 0.4, at: 4.2, ease: "easeOutCubic" });
animate(rightEye, "y", { from: CY - 20, to: CY, duration: 0.4, at: 4.2, ease: "easeOutCubic" });

animate(leftEye, "x", { from: LX, to: LX - 40, duration: 0.4, at: 4.8, ease: "easeInOutCubic" });
animate(rightEye, "x", { from: RX, to: RX - 40, duration: 0.4, at: 4.8, ease: "easeInOutCubic" });
animate(leftEye, "x", { from: LX - 40, to: LX + 40, duration: 0.5, at: 5.6, ease: "easeInOutCubic" });
animate(rightEye, "x", { from: RX - 40, to: RX + 40, duration: 0.5, at: 5.6, ease: "easeInOutCubic" });
animate(leftEye, "x", { from: LX + 40, to: LX, duration: 0.3, at: 6.4, ease: "easeOutCubic" });
animate(rightEye, "x", { from: RX + 40, to: RX, duration: 0.3, at: 6.4, ease: "easeOutCubic" });

// --- Phase 4: Combat / Anger Mode (6.8s - 9.2s) -> Inward Slanted Blades ---
animate(leftEye, "width", { from: 64, to: 48, duration: 0.4, at: 6.8, ease: "easeOutBack" });
animate(leftEye, "height", { from: 24, to: 96, duration: 0.4, at: 6.8, ease: "easeOutBack" });
animate(leftEye, "cornerRadius", { from: 12, to: 16, duration: 0.4, at: 6.8, ease: "easeOutBack" });
animate(leftEye, "rotation", { from: 0, to: 0.42, duration: 0.4, at: 6.8, ease: "easeOutBack" });

animate(rightEye, "width", { from: 64, to: 48, duration: 0.4, at: 6.8, ease: "easeOutBack" });
animate(rightEye, "height", { from: 24, to: 96, duration: 0.4, at: 6.8, ease: "easeOutBack" });
animate(rightEye, "cornerRadius", { from: 12, to: 16, duration: 0.4, at: 6.8, ease: "easeOutBack" });
animate(rightEye, "rotation", { from: 0, to: -0.42, duration: 0.4, at: 6.8, ease: "easeOutBack" });

// --- Phase 5: Sadness / Glitch Droop (9.2s - 11.8s) -> Outward Droop ---
animate(leftEye, "width", { from: 48, to: 44, duration: 0.5, at: 9.2, ease: "easeOutCubic" });
animate(leftEye, "height", { from: 96, to: 80, duration: 0.5, at: 9.2, ease: "easeOutCubic" });
animate(leftEye, "cornerRadius", { from: 16, to: 22, duration: 0.5, at: 9.2, ease: "easeOutCubic" });
animate(leftEye, "y", { from: CY, to: CY + 25, duration: 0.5, at: 9.2, ease: "easeOutCubic" });
animate(leftEye, "rotation", { from: 0.42, to: -0.32, duration: 0.5, at: 9.2, ease: "easeOutCubic" });

animate(rightEye, "width", { from: 48, to: 44, duration: 0.5, at: 9.2, ease: "easeOutCubic" });
animate(rightEye, "height", { from: 96, to: 80, duration: 0.5, at: 9.2, ease: "easeOutCubic" });
animate(rightEye, "cornerRadius", { from: 16, to: 22, duration: 0.5, at: 9.2, ease: "easeOutCubic" });
animate(rightEye, "y", { from: CY, to: CY + 25, duration: 0.5, at: 9.2, ease: "easeOutCubic" });
animate(rightEye, "rotation", { from: -0.42, to: 0.32, duration: 0.5, at: 9.2, ease: "easeOutCubic" });

// --- Phase 6: Joy & Cheeky Wink (11.8s - 14.2s) -> Left Wide, Right Wink ---
animate(leftEye, "rotation", { from: -0.32, to: 0, duration: 0.4, at: 11.8, ease: "easeOutBack" });
animate(leftEye, "y", { from: CY + 25, to: CY - 15, duration: 0.4, at: 11.8, ease: "easeOutBack" });
animate(leftEye, "width", { from: 44, to: 54, duration: 0.4, at: 11.8, ease: "easeOutBack" });
animate(leftEye, "height", { from: 80, to: 100, duration: 0.4, at: 11.8, ease: "easeOutBack" });
animate(leftEye, "cornerRadius", { from: 22, to: 27, duration: 0.4, at: 11.8, ease: "easeOutBack" });

animate(rightEye, "rotation", { from: 0.32, to: 0, duration: 0.4, at: 11.8, ease: "easeOutBack" });
animate(rightEye, "y", { from: CY + 25, to: CY - 15, duration: 0.4, at: 11.8, ease: "easeOutBack" });
animate(rightEye, "width", { from: 44, to: 60, duration: 0.4, at: 11.8, ease: "easeOutBack" });
animate(rightEye, "height", { from: 80, to: 8, duration: 0.4, at: 11.8, ease: "easeOutBack" });
animate(rightEye, "cornerRadius", { from: 22, to: 4, duration: 0.4, at: 11.8, ease: "easeOutBack" });

// --- Phase 7: Symmetrical Neutral Standby (14.2s - 16.0s) ---
animate(leftEye, "width", { from: 54, to: 46, duration: 0.4, at: 14.2, ease: "easeOutBack" });
animate(leftEye, "height", { from: 100, to: 116, duration: 0.4, at: 14.2, ease: "easeOutBack" });
animate(leftEye, "cornerRadius", { from: 27, to: 23, duration: 0.4, at: 14.2, ease: "easeOutBack" });
animate(leftEye, "y", { from: CY - 15, to: CY, duration: 0.4, at: 14.2, ease: "easeOutBack" });

animate(rightEye, "width", { from: 60, to: 46, duration: 0.4, at: 14.2, ease: "easeOutBack" });
animate(rightEye, "height", { from: 8, to: 116, duration: 0.4, at: 14.2, ease: "easeOutBack" });
animate(rightEye, "cornerRadius", { from: 4, to: 23, duration: 0.4, at: 14.2, ease: "easeOutBack" });
animate(rightEye, "y", { from: CY - 15, to: CY, duration: 0.4, at: 14.2, ease: "easeOutBack" });

// ----------------------------------------------------------------------------
// 3. EMOTION STATUS HUD READOUT & MOUTH
// ----------------------------------------------------------------------------
const statusLabel = text("// EMOTE PROTOCOL: ONLINE //", {
  x: CX,
  y: 840,
  fontSize: 20,
  fontFamily: "JetBrains Mono",
  fill: COLOR_CYAN,
  textAlign: "center",
  duration: DURATION
});

const smileMouth = arc(42, 0.2, 2.94, {
  x: CX,
  y: CY + 110,
  stroke: COLOR_CYAN,
  strokeWidth: 4,
  lineCap: "round",
  opacity: 0,
  duration: DURATION
});

animate(smileMouth, "opacity", { from: 0, to: 1.0, duration: 0.4, at: 11.8, ease: "easeOutCubic" });
animate(smileMouth, "opacity", { from: 1.0, to: 0, duration: 0.4, at: 14.2, ease: "easeOutCubic" });

const avatarGroup = group([
  faceBackdrop,
  telemetryRing,
  cheekLeft,
  cheekRight,
  leftEye,
  rightEye,
  smileMouth,
  statusLabel
], { duration: DURATION });

const main = parallel([
  at(0.0, avatarGroup)
]);

output(main, {
  width: 1920,
  height: 1080,
  fps: 60,
  backgroundColor: "#050811",
  duration: DURATION
});