The Three-Renderer Rule: Architecture for Portable Video Pipelines
July 8, 2026 · By VideoFlowLearn how to architect portable video pipelines using the Three-Renderer Rule. Decouple composition from rendering for byte-for-byte consistency across browser and server.
The Three-Renderer Rule: Architecture for Portable Video Pipelines
Building a video pipeline is usually a one-way street. You pick a stack—FFmpeg shell scripts, a proprietary SaaS API, or a React-based framework—and you’re locked in. If you need to move from a server-side batch process to a client-side export, you're often looking at a total rewrite.
This architectural fragmentation is the single biggest bottleneck in modern video automation. It’s why we built VideoFlow around the Three-Renderer Rule: the principle that a single, portable video definition should render byte-for-byte identically across the browser, the server, and a live preview environment.
In this guide, we’ll explore how to architect portable video pipelines that decouple composition from rendering, allowing your videos to live anywhere your code does.

The Problem: The Composition/Rendering Tangle
Most video tools conflate what the video is with how it is rendered. In Remotion, your video is a React component tree; to render it, you need a React runtime. In FFmpeg, your video is a string of commands; to render it, you need a specific binary environment.
This coupling makes it impossible to build truly portable video pipelines. If you want to let a user preview a video in their browser and then render the high-quality MP4 on a server, you have to maintain two separate logic paths.
VideoFlow solves this by introducing VideoJSON—a declarative, resolution-agnostic schema that describes your timeline. Your code (the builder) produces the JSON, and the renderers consume it.
Rule 1: Composition as Data
The first step to portability is treating your video as data. When you use the @videoflow/core builder, you aren't rendering frames; you're building a manifest.
import VideoFlow from '@videoflow/core';
const $ = new VideoFlow({ width: 1920, height: 1080, fps: 30 });
// Composition logic is pure data definition
$.addImage({ fit: 'cover' }, { source: 'https://assets.site.com/bg.jpg' });
const title = $.addText({ text: 'Portable Video', fontSize: 8 });
title.fadeIn('500ms');
$.wait('3s');
// This produces a portable JSON document
const videoJson = await $.compile();
Because this JSON is serializable, you can store it in a database, version control it, or pass it between services. This is why LLMs need portable VideoJSON—it’s a format they can reason about without needing to execute code.
Rule 2: The Three-Renderer Matrix
The "Three-Renderer Rule" states that your pipeline should support three distinct modes of execution using the exact same source data:
- The DOM Renderer (
@videoflow/renderer-dom): For frame-accurate, 60fps live previews. This allows for instant feedback loops in your UI without waiting for a full encode. - The Browser Renderer (
@videoflow/renderer-browser): For in-tab MP4 export via WebCodecs. This eliminates server costs for user-generated content. - The Server Renderer (
@videoflow/renderer-server): For headless, high-concurrency batch jobs in Node.js.
By following this rule, you can build a "Compose Once, Render Anywhere" architecture. You can preview the video in a React dashboard, let the user tweak a parameter, and then choose whether to export the MP4 locally in their browser or queue it for a background server job.

Rule 3: Resolution Independence
A portable pipeline must be resolution-agnostic. If you define a text layer at x: 500, y: 500, it will look different on a 720p canvas versus a 4K canvas.
VideoFlow enforces normalized coordinates (0 to 1) and em-based sizing (where 1em = 1% of project width). This ensures that your videoJson renders identically whether it's being exported as a 1080p social ad or a 4K hero video.
// Positioning is normalized (0.5 is center)
// fontSize is in em (8% of project width)
$.addText({
text: 'Agile Layout',
position: [0.5, 0.4],
fontSize: 8
});
How VideoFlow Handles Portability
VideoFlow was designed from the ground up to support these portable video pipelines. Unlike alternatives that require a specific framework or a heavy binary dependency, VideoFlow's core logic is a lightweight TypeScript library.
@videoflow/core: The Apache-2.0 licensed engine that compiles your fluent builder calls into VideoJSON.@videoflow/renderer-server: A headless Chromium-based renderer for Node.js that works without FFmpeg by default, making it perfect for serverless environments.@videoflow/renderer-browser: A worker-accelerated renderer that leverages the browser's native WebCodecs for lightning-fast, zero-cost exports.
Whether you are building a SaaS recap video feature or an automated YouTube factory, adhering to the Three-Renderer Rule ensures your architecture stays flexible as your product grows.
Get Started with Portable Video
Ready to build your first portable pipeline?
- Experiment in the Playground: See how the DOM renderer handles live updates as you change your code.
- Read the Docs: Dive into the Core Concepts of VideoJSON.
- Explore the GitHub Repo: Check out the source for all three renderers and start building.
By decoupling your creative logic from the rendering engine, you aren't just making videos—you're building a scalable video infrastructure.