Building Reusable Programmatic Video Components with Layer Groups
July 8, 2026 · By VideoFlowLearn how to build reusable programmatic video components using VideoFlow's Layer Groups. Master composition, nested timelines, and encapsulated animations.
When you're building a simple video script, you can get away with a flat list of layers. But as soon as you move into building a programmatic video engine—like an automated social media factory or a personalized SaaS dashboard—your code starts to look like spaghetti. You find yourself manually calculating frame offsets for twenty different layers just to move a single 'card' across the screen.
This is where the architecture of your video pipeline matters. To scale, you need reusable programmatic video components. In VideoFlow, this is achieved through Layer Groups—a powerful primitive that lets you encapsulate logic, timing, and cinematic effects into portable, nestable blocks.

The Problem with Flat Timelines
Most video-as-code tools force you to think in global coordinates and global timestamps. If you want to create a 'User Profile' widget with an avatar, a name, and a background, you have to position each layer relative to the main canvas. If you decide to move that widget 100 pixels to the left, you're updating three different position properties.
Even worse is timing. If your widget has a subtle entrance animation, and you want to delay the entire widget by 2 seconds, you're manually adding 2.0 to every layer's startTime. This approach is fragile, hard to debug, and makes code reuse nearly impossible.
Encapsulation with Layer Groups
VideoFlow's Layer Group guide introduces $.group(). A group is a container that creates a private, project-sized surface. Everything inside the group is composited onto this surface first, and then the group itself is treated as a single visual layer by the parent project.
This provides three massive advantages for building reusable components:
- Local Coordinates: Children are positioned relative to the group's internal surface.
- Relative Timing: A child's
startTimeof0means the exact moment the group begins, not the start of the video. - Atomic Transforms: You can rotate, scale, or apply a GLSL effect to the entire group as if it were a single image.
Pattern: The 'Card' Component
Let's look at how to wrap this into a reusable function. This pattern allows you to stamp out dozens of identical widgets with different data.
import VideoFlow from '@videoflow/core';
function createStatCard($, { label, value, x, color }) {
return $.group(
{ position: [x, 0.5], scale: 1 },
{
transitionIn: { transition: 'overshootPop', duration: '600ms' },
transitionOut: { transition: 'fade', duration: '400ms' },
},
(group) => {
// Background
$.addShape(
{ width: 30, height: 20, fill: '#1c2233', cornerRadius: 2 },
{ shapeType: 'rectangle' }
);
// Label text
$.addText({
text: label,
fontSize: 1.5,
color: '#94a3b8',
position: [0.5, 0.35]
});
// Value text
$.addText({
text: value,
fontSize: 5,
color: color,
position: [0.5, 0.6]
});
$.wait('3s');
}
);
}

Orchestrating the Flow
Once you have your component function, you can orchestrate complex scenes using the VideoFlow Core builder. Because groups return a layer instance, you can still animate the entire component from the outside.
const $ = new VideoFlow({ width: 1920, height: 1080 });
// Stagger three cards
const cardA = createStatCard($, { label: 'REVENUE', value: '$12k', x: 0.25, color: '#FF5A1F' });
$.wait('200ms');
const cardB = createStatCard($, { label: 'USERS', value: '4.2k', x: 0.50, color: '#4ecdc4' });
$.wait('200ms');
const cardC = createStatCard($, { label: 'CHURN', value: '0.8%', x: 0.75, color: '#a78bfa' });
// Apply a global drift to one specific card without touching its children
cardB.animate(
{ rotation: -2 },
{ rotation: 2 },
{ duration: '4s', easing: 'easeInOut', wait: false }
);
In this example, cardB drifts back and forth. The text and shape inside the group stay perfectly aligned because they are part of the group's local coordinate system. If you were doing this without groups, you would have to calculate the sine-wave rotation for every individual layer in the widget.
Why This Beats React-based Approaches
If you're coming from a Remotion background, you might be used to using React components for this. While React is great for UI, it couples your video logic to a specific UI library and a heavy runtime.
VideoFlow's approach uses standard JavaScript functions and a portable VideoJSON schema. This means you can build your component library once and use it anywhere: in a high-concurrency Node.js backend using @videoflow/renderer-server, or directly in a customer's browser via @videoflow/renderer-browser for zero-server-cost exports.
Start Building Your Library
Treating your video layers as components isn't just about cleaner code—it's about building a scalable asset library. By encapsulating complex animations and GLSL stacks into simple function calls, you turn a complex rendering task into a simple composition exercise.
Ready to try it out? Head over to the VideoFlow Playground and try nesting a few $.group() calls. You'll quickly see how much faster it is to build cinematic scenes when you aren't fighting global coordinates.
For a deeper dive into the API, check out the official documentation or join the community on GitHub.