View raw

Editor#

@clipkit/editor is an embeddable, open-source timeline editor — a full visual editor over the Clipkit Protocol that you drop into your React app as a single component.

It reads and writes the same CKP/1.0 Source that the runtime, the MCP server, the CLI, and the render service all consume. Whatever an AI agent or a human produces in the editor is the same JSON your renderer eats — one schema, two surfaces.

Install#

npm install @clipkit/editor

It ships as a React 19 component (react and react-dom are peer dependencies), licensed Apache-2.0.

Drop it in#

import { Editor, ADVANCED_CONFIGURATION } from '@clipkit/editor';
import type { Source } from '@clipkit/protocol';

function MyVideoTool({ project }: { project: Source }) {
  return (
    <Editor
      initialSource={project}
      configuration={ADVANCED_CONFIGURATION}
      onSourceChange={(source) => save(source)}
    />
  );
}

initialSource is the only required prop. Persist edits from onSourceChange — it fires with the full Source on every change.

Configurations#

The same component tree ships as two configurations; pass one in, or build your own:

  • ADVANCED_CONFIGURATION — the full surface: every panel, keyframes, expressions. This is the default when you omit the prop.
  • BASIC_CONFIGURATION — a streamlined editor with the essential views and controls.
import { Editor, BASIC_CONFIGURATION } from '@clipkit/editor';

<Editor initialSource={project} configuration={BASIC_CONFIGURATION} />;

A configuration is data — it decides which views and controls render over the same underlying store (the EditorConfiguration type). One tree, configurations decide.

Props#

PropTypeNotes
initialSourceSourceRequired. The composition to open.
configurationEditorConfigurationDefaults to ADVANCED_CONFIGURATION.
onSourceChange(source: Source) => voidFires on every edit — persist the JSON here.
assetStoreAssetStoreWhere uploaded media lives. Defaults to local browser storage.
onRender(source, request) => voidCalled when the user exports — wire it to your render endpoint.
theme'light' | 'dark'Defaults to 'dark'; follows the prop live.
backend'auto' | 'webgpu' | 'webgl2'Preview backend. Defaults to 'auto'.

Assets and storage#

Media the user adds (images, video, audio) flows through an injected AssetStore port — the editor library itself has zero database code. Two implementations ship in the box:

import { createLocalAssetStore, createMemoryAssetStore } from '@clipkit/editor';

const assetStore = createLocalAssetStore(); // browser IndexedDB — the default
  • createLocalAssetStore() — persists to the browser (IndexedDB). Used automatically if you pass no assetStore.
  • createMemoryAssetStore() — ephemeral, in-memory (handy for tests).

To put assets in S3, Supabase, or your own API, implement the AssetStore interface and pass it as assetStore.

Preview and export#

Preview runs live in the browser via @clipkit/runtime (WebGPU, with a WebGL2 fallback), and the editor can export MP4 directly in the browser. For server-side or heavier renders, point onRender at:

  • a local @clipkit/renderer instance,
  • the hosted API at api.clipkit.dev, or
  • your own infrastructure running @clipkit/renderer.

Editing runs free in the user's browser; rendering is the part you might host or charge for — on your own terms.

Using it outside React#

@clipkit/editor is a React 19 component. If your app is already React — Next.js, Vite, Remix — it's a one-component drop-in. For a non-React page you can mount it imperatively with ReactDOM.createRoot(el).render(<Editor … />), or wrap it through a React-interop bridge for Vue, Svelte, or Angular. There is no separate web-component build today.

License#

Apache-2.0 — self-host, fork, and embed it. Source on GitHub.