I kept running into the same bug in video projects: the preview looked right, the editor looked right, and the export was slightly off. By the time I had a browser renderer, a server renderer, and an editing UI, I was maintaining three versions of the same logic.
The fix was to stop treating preview, editing, and rendering as separate artifacts. I moved to one VideoJSON source of truth and let different renderers consume it. That is the workflow I now reach for when I want structured, repeatable video output instead of a one-off timeline I have to babysit.
Why Video Workflows Drift
Video drift usually shows up in one of three places:
- The preview uses a different scene definition than the export.
- The editor stores state in a format that does not map cleanly to rendering.
- The server render has its own assumptions about sizing, fonts, or timing.
Once those paths split, small changes become expensive. A title changes in the editor, but the preview still shows an old layout. A thumbnail looks fine in the browser, but the server output crops it differently. The longer the project lives, the more you end up comparing versions instead of shipping new video.
The Pattern That Fixed It
VideoFlow's core idea is simple: describe the video in TypeScript, compile it into portable VideoJSON, and reuse that same structure across environments. The package docs call out browser rendering, server rendering, and a live DOM preview, which is exactly the separation I wanted. One model, multiple outputs.
Here is the smallest version of that workflow from the docs:
import VideoFlow from '@videoflow/core';
const $ = new VideoFlow({
name: 'Launch teaser',
width: 1920,
height: 1080,
fps: 30,
});
$.addText(
{ text: 'Hello, VideoFlow!', fontSize: 7, fontWeight: 800 },
{ transitionIn: { transition: 'overshootPop', duration: '500ms' } }
);
const videoJSON = await $.compile();
That videoJSON object is the important part. Once I have it, I can render it in the browser, hand it to a server renderer, or mount it in a live editor without rewriting the scene logic. The renderer becomes an implementation detail, not the place where the creative decisions live.
How I Split The Workflow
For me, the cleanest split looks like this:
- Author the scene in TypeScript so the structure is explicit and reviewable.
- Compile to VideoJSON so the scene is data, not a one-off render artifact.
- Use
@videoflow/renderer-browserfor low-friction preview and browser-side export. - Use
@videoflow/renderer-serverwhen I need batch jobs, queues, or API-driven renders. - Use
@videoflow/react-video-editorwhen the product needs an actual editing UI.
That approach also makes it easier to hand work between systems without translating the scene every time. If you want the browser/server handoff angle specifically, I went deeper on that in How I Built a Browser-to-Server Video Workflow With VideoFlow.
Why The JSON Layer Helps Maintenance
The biggest win is not just portability. It is maintenance.
When the scene is JSON-shaped, I can diff it, store it, generate it, and review it without opening a timeline app. That matters when content is produced by code, when an agent generates the initial structure, or when multiple team members need to reason about the same video without stepping on each other.
It is also the reason I like the template angle so much. Once the format becomes the product boundary, the workflow becomes easier to automate. I wrote more about that in How to Build a Video Template System Around a Single JSON Source of Truth, because the maintenance story is really the whole point.
Where This Pattern Is A Better Fit
I would use this approach when the work is structured and repeatable:
- product demos
- social clips
- onboarding videos
- reports and dashboards
- template-driven marketing assets
- app-embedded editing workflows
I would be more cautious when the job is highly bespoke motion design, because a traditional timeline editor is still better for exploratory creative work. VideoFlow is strongest when you want repeatable composition, not when you want to manually nudge every frame.
If You Want To Try It
VideoFlow is open source, and the docs are the fastest place to test the idea in practice: https://videoflow.dev/docs and https://videoflow.dev/playground. If you are building a video tool, I would start with one scene in TypeScript, compile it to VideoJSON, and see how far you can push that single model before introducing any duplication.
The short version: keep one source of truth, and let the renderers adapt to it instead of the other way around.
TL;DR: one VideoJSON document, multiple renderers, fewer mismatches.
What are you using as the source of truth for video today?




Top comments (0)