Building Video Components: A Guide to Layer Grouping in VideoFlow
September 1, 2026 · By VideoFlowLearn how to build reusable, composable video components using VideoFlow's GroupLayer. Master nested timelines, shared transitions, and efficient scene management.
Building Video Components: A Guide to Layer Grouping in VideoFlow
When you're building a complex video pipeline, you quickly run into the "flat list" problem. Managing dozens of individual layers—each with its own timing, position, and transition—becomes a maintenance nightmare. If you've ever tried to move a 'Lower Third' graphic composed of three shapes and two text layers, you know the pain of updating five different position arrays just to shift the whole thing 10% to the left.
In modern web development, we solve this with components. In VideoFlow, we solve it with Layer Grouping.
The Component Mental Model for Video
VideoFlow's $.group() method is more than just a folder for layers. It creates a private sub-project with its own coordinate system and its own timeline. When you author layers inside a group, their position: [0.5, 0.5] refers to the center of the group, not the center of the main canvas.
This encapsulation allows you to treat complex visual assemblies as single units. You can animate the entire group, apply a single transition to it, or even run a GLSL effect over the composite result without affecting the rest of the scene.

How to Build a Reusable UI Card
Let's look at a concrete example. Suppose you're building a SaaS dashboard recap video and you need to show a series of "Metric Cards." Instead of manual frame math for every element, you can define a group.
import VideoFlow from '@videoflow/core';
const $ = new VideoFlow({ width: 1920, height: 1080 });
// Create a reusable component using $.group
const metricCard = $.group(
{ position: [0.5, 0.5], perspective: 20 },
{
transitionIn: { transition: 'zoom', duration: '600ms' },
transitionOut: { transition: 'fade', duration: '400ms' },
},
() => {
// Background Shape
$.addShape(
{ width: 40, height: 25, fill: '#0e1524', cornerRadius: 2 },
{ shapeType: 'rectangle' }
);
// Label
$.addText({
text: 'ACTIVE USERS',
fontSize: 1.8,
color: '#FF5A1F',
position: [0.5, 0.4]
});
// Value
$.addText({
text: '12,480',
fontSize: 8,
fontWeight: 900,
color: '#ffffff',
position: [0.5, 0.6]
});
$.wait('3s'); // The group lives for 3 seconds
}
);
// Animate the whole card with one call
metricCard.animate(
{ rotation: [-5, 0, 0] },
{ rotation: [5, 0, 0] },
{ duration: '3s', easing: 'easeInOut', wait: false }
);
In this snippet, the zoom transition applies to the entire card. You don't have to worry about the background zooming in while the text fades; they arrive together as a single visual unit. This is the core of the VideoFlow builder API.
Nested Timelines and Local Origin
One of the most powerful features of groups is local timing. When you call $.wait() inside a group's callback, it only advances the timeline for that group. This makes it trivial to create staggered animations within a component without affecting the global flow of your video.
Imagine a 'Price Tag' component where the price appears 200ms after the label. By using $.wait('200ms') inside the group, you ensure that the internal delay is baked into the component itself. No matter where you place that component on the main timeline, the internal stagger remains perfect.

Why This Beats FFmpeg and Remotion
If you're coming from an FFmpeg shell script background, the advantage is obvious: you're moving from string-concatenated filter graphs to a typed, hierarchical structure. But even compared to Remotion, VideoFlow's approach offers a unique benefit: JSON Portability.
Because VideoFlow compiles your builder calls into a standard VideoJSON document, your "components" can be stored in a database, sent over an API, or generated by an LLM. You aren't shipping a React runtime; you're shipping a portable manifest that renders identically across the three official renderers.
This architecture follows the Three-Renderer Rule: use the same component logic for a live preview in the browser, a client-side export via WebCodecs, and a headless server render in Node.
Practical Tips for Grouping
- Use
perspective: If you're rotating groups in 3D space, set aperspectivevalue (e.g.,20) in the group's properties to give the child layers realistic depth. - Wait: false: When animating the group container itself (like the subtle drift in the example above), use
{ wait: false }so the animation doesn't block the internal flow of the group. - Composite Effects: If you want to apply a
bloomorvhsDistortioneffect to a whole scene, put the scene in a group and add the effect to the group'seffectsarray. It’s significantly more performant than adding the effect to every individual layer.
Get Started with Groups
Grouping is the secret to building maintainable, professional-grade video automation. It turns your video scripts from a sequence of commands into a library of reusable assets.
Ready to try it out? Head over to the VideoFlow Playground to see groups in action, or dive into our Layer Groups Guide for a deeper look at the technical implementation. If you find a bug or have a feature request, we'd love to see you on GitHub.
Happy rendering!