VideoFlowcodeGitHubTry itCoreRenderersReact Video EditorPlaygroundExamplesDocscodeGitHubTry it
Getting started
InstallationQuick startCore conceptsYour first video
Builder
Builder APITime formatsParallel & wait
Layers
TextImageVideoAudioCaptionsShapeGroups
Animation
Animate & keyframesEasing functionsTransitionsEffects
Renderers
Browser rendererServer rendererDOM preview
React Video Editor
QuickstartThemingUploadsCustom panelsHooks & commandsKeyboard shortcuts
API reference
Overview@videoflow/core@videoflow/renderer-browser@videoflow/renderer-server@videoflow/renderer-dom@videoflow/react-video-editor

Editor quickstart

@videoflow/react-video-editor is a drop-in editor UI — timeline, preview, inspector, keyboard shortcuts, undo/redo. You feed it a VideoJSON and it hands back a new one on every change.

Minimal example

import { VideoEditor } from '@videoflow/react-video-editor';
import '@videoflow/react-video-editor/style.css';

const initialVideo = {
  name: 'My project',
  width: 1920, height: 1080, fps: 30, duration: 10,
  layers: [],
};

export default function App() {
  return (
    <VideoEditor
      video={initialVideo}
      onChange={(next) => console.log('edited', next)}
      onSave={(video) => saveToServer(video)}
      onExportComplete={(blob) => downloadBlob(blob, 'out.mp4')}
      theme="dark"
    />
  );
}

Export. Most apps should leave onExport undefined and rely on the built-in export modal + onExportComplete to receive the rendered Blob. Set onExport only when you want to skip the modal and run your own UI / pipeline; whatever it resolves to is forwarded to onExportComplete.

Props

PropTypeNotes
videoVideoJSONInitial state. Controlled re-renders supported.
onChange(video) => voidFires on every edit. Debounced internally.
onSave`(video) => voidPromise<void>`
onExport() => Promise<unknown>Optional custom export. When set, replaces the built-in modal; whatever it resolves to is forwarded to onExportComplete.
onExportComplete(video) => voidReceives the rendered Blob from the built-in modal (or the value onExport resolved to). When set with the built-in modal, the editor skips its auto-download.
onUpload(file) => Promise<string>Resolve to a URL. See Uploads.
theme`'light''grey'
branding`ReactNodenull
components{ Titlebar, Preview, Sidebar, Timeline }Swap any panel. See Custom panels.

Sizing

The editor fills its parent. Wrap it in a block with an explicit height — typically 100vh minus your app chrome.

<section style={{ height: 'calc(100vh - 64px)' }}>
  <VideoEditor video={v} onChange={setV} theme="dark" />
</section>

SSR. The editor is client-only. Dynamically import it in Next / Remix / React Router — or guard with a useEffect.

VideoFlow

Open-source toolkit for composing videos from code.

Product

CoreRenderersReact Video EditorPlayground

Learn

DocsAPI referenceExamplesvs. Remotionvs. FFmpeg

Project

GitHubLicenseContactTermsPrivacy

From the blog

All posts →How to Automate Loom-style Product Demos with TypeScriptAutomated Podcast Audiogram Generator: Turning Audio into Viral Video with TypeScriptHow to Turn Markdown Changelogs into Automated Product Update VideosAutomating Personalized Onboarding Videos with VideoFlow and TypeScriptAutomating YouTube Shorts: Build a Vertical Video Factory in 30 Lines of TypeScriptCinematic 3D Video with TypeScript: A Guide to Perspective and RotationCinematic GLSL Effect Stacking: Building High-End Visuals with CodeDiffable Video: Versioning Your Media Pipeline with VideoJSON
© 2026 VideoFlow. Apache-2.0 core.