Mastering Flow: How to Use $.wait, $.parallel, and $.group in VideoFlow
August 12, 2026 · By VideoFlowLearn how to move beyond manual frame math. Master VideoFlow's timing primitives like $.wait, $.parallel, and $.group to build complex, maintainable video timelines.
Mastering Flow: How to Use $.wait, $.parallel, and $.group in VideoFlow
Most video-as-code libraries force you to think in absolute frames or manual timestamps. You find yourself calculating that "Layer B should start at frame 120 because Layer A lasts 4 seconds at 30fps." This brittle approach breaks the moment you change a single duration.
In VideoFlow, we treat video like a program. Instead of manual frame math, you use high-level flow primitives—$.wait, $.parallel, and $.group—to compose complex timelines that are readable, maintainable, and resolution-agnostic.
The Sequential Default
By default, the @videoflow/core builder operates sequentially. When you add a layer or call an animation method, the internal "flow pointer" advances.
import VideoFlow from '@videoflow/core';
const $ = new VideoFlow();
// 1. Text appears and we wait 2 seconds
$.addText({ text: 'Step One' });
$.wait('2s');
// 2. This text starts exactly at the 2s mark
$.addText({ text: 'Step Two' });
This is intuitive for simple slideshows, but real-world videos require overlapping elements and complex compositions. This is where parallelism comes in.
Branching the Timeline with $.parallel
If you want to trigger multiple actions at the exact same time without advancing the main flow pointer, use $.parallel. This is essential for creating "scenes" where a background appears while multiple text elements animate in simultaneously.

$.parallel(($) => {
// These two layers start at the same timeline position
$.addText({ text: 'Left Side', position: [0.2, 0.5] });
$.addText({ text: 'Right Side', position: [0.8, 0.5] });
});
// The flow pointer hasn't moved!
// The next element still starts at the same time as the parallel block.
$.addShape({ fill: '#FF5A1F' }, { shapeType: 'rectangle' });
In this example, both text layers and the rectangle start at the same time. The $.parallel block acts as a "snapshot" point where you can stack as many layers as you need without pushing the rest of your video later into the timeline.
Encapsulation with $.group
As your project grows, you'll want to treat multiple layers as a single entity. The $.group method creates a GroupLayer that acts as a container. Children inside the group use coordinates and timing relative to the group itself.

Groups are incredibly powerful because you can apply transitions and effects to the entire group at once. If you apply a blurResolve transition to a group, every child inside that group will blur in together as a single composite unit.
const card = $.group(
{ opacity: 0.8 },
{ transitionIn: { transition: 'blurResolve', duration: '800ms' } },
($) => {
$.addShape({ fill: '#222' }, { shapeType: 'rectangle' });
$.addText({ text: 'Grouped Title', fontSize: 5 });
}
);
Why Your Video Pipeline Should Be Programmable
By using these primitives, you move away from the "After Effects mindset" of static layers and toward a dynamic, data-driven architecture. This is why VideoFlow is the preferred choice for developers building automated content factories or SaaS recap videos.
Unlike Remotion, which ties your scene logic to a React component tree, VideoFlow compiles your builder calls into a portable VideoJSON document. This JSON can be rendered identically across our three official renderers: in the browser via WebCodecs, on the server via headless Chromium, or as a live preview in your React app.
Summary: The Three-Step Timing Rule
- Use $.wait for sequential storytelling.
- Use $.parallel to stack independent layers at the same timestamp.
- Use $.group to encapsulate complex sub-scenes and apply shared effects.
You can experiment with these patterns right now in the VideoFlow Playground or dive deeper into the Parallel and Wait guide in our documentation.
Ready to build? Check out the source on GitHub and start composing your next video with code.