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) => void | Promise<void>Fires on Cmd+S / titlebar Save. Setting it makes a Save button appear and the editor tracks an isSaved flag.
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' | 'dark' | 'night'Defaults to 'dark'. See Theming.
brandingReactNode | null | falseLeading brand node for the titlebar (logo + wordmark). Omit / pass null to fall back to the project-name input.
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

GitHubLicenseContact

Legal

TermsPrivacy
© 2026 VideoFlow. Apache-2.0 core.