Skip to content

Architecture

ONDA is a Rust workspace with a small TypeScript/React authoring layer on top. Its defining principle: the scene graph is the universal language, and the renderer is the platform — everything else (React, the CLI, AI) is an adapter that produces or consumes the scene graph.

React / JSON / AI
Scene Graph (onda-scene — plain, serde JSON)
Animation Runtime (onda-animation — evaluate a timeline at a frame → static Scene)
Native Renderer (onda-vello on GPU, or onda-renderer on CPU)
GPU
Frame Buffer
Encoder (GIF: pure Rust · MP4: ffmpeg)
Video

No DOM. No Chromium. No screenshot pipeline. No browser layout engine.

These are enforced by the crate boundaries:

  1. The engine is the source of truth. Everything consumes the engine; nothing inside it depends on external consumers.
  2. No core crate may depend on React, the browser, the DOM, or AI APIs. The runtime is framework-agnostic. onda-scene, onda-animation, and onda-core are pure serde-serializable data and logic.
  3. React is a consumer of ONDA, not ONDA itself. The same runtime serves React, hand-written JSON, AI, and the CLI without modification.

ONDA’s Rust crates live under packages/*-rs (and packages/wasm). The crates that are real and in the build today:

CrateRole
onda-coreTiny shared primitives: Vec2, Size, Color, Transform (translate + scale; linear-space color helpers). Dependency-light; everything builds on it.
onda-sceneThe scene graph: Scene, Composition, Node, NodeKind (Group / Text / Image / Video / Audio / Shape / Svg), ShapeGeometry (Rect / Ellipse / Path), Gradient, Stroke, clip, matte, blend, effects, camera3d / transform3d / extrude, and layout. Plain serde data — the universal language.
onda-animationThe animation runtime: a Timeline of keyframe Tracks targeting nodes by id; evaluate_frame collapses it to a static Scene. Easings + springs over opacity/translate/scale.
onda-typographyShaping, layout, and glyph rasterization via cosmic-text + swash. Bundles Open Sans (SIL OFL 1.1) for deterministic, host-independent text; hands back coverage masks and per-glyph layout.
onda-rendererThe CPU reference rasterizer (tiny-skia): deterministic, dependency-light, the correctness oracle. AA fills/strokes, rounded rects, paths, linear/radial gradients, text, images, and the render-to-texture effect chain — byte-identical to Vello; only rotation/clip/blend/3D-tilt deferred to the GPU. Parallel frame rendering via rayon.
onda-velloThe GPU-native vector backend (Vello on wgpu): AA fills/strokes, rounded rects, paths, gradients, clips, per-glyph vector text, the effect chain, blend modes, true 3D + extruded solids. Offscreen render + readback.
onda-audioAudio: decode + FFT spectrum + beat/onset detection (symphonia + rustfft), and a declarative AudioGraph synth. Shared by browser + native via @onda-engine/wasm-audio.
onda-svgSVG import: usvg → flattened Path nodes (import_svg / expand_svg).
onda-cliThe onda command-line adapter: render / export / export-frames / render-frame / contact-sheet / lint, backend + encoder selection, GIF/MP4 encoding.
onda-wasmThe CPU engine compiled to WebAssembly for the browser.
bench-rsBenchmarks (compared continuously against Remotion).
PackageRole
@onda-engine/reactA custom React renderer (built on react-reconciler) that compiles JSX into scene-graph JSON. Provides the components, hooks, interpolate/spring, <Sequence>/<Series>/<Loop>, and the renderToScene* / renderFrames* functions.

The reconciler maps each component to a host element, then serializes the tree to JSON that round-trips into onda-scene exactly (matching field names, snake_case, and the internally-tagged enums). That JSON is what the onda CLI renders.

  • Determinism — the CPU path is bit-identical across machines (with the bundled font); no time-API patching or compositor warmup.
  • Concurrency — one process with shared GPU buffers (vs a full browser per worker) means far higher render concurrency per machine.
  • AI-native — because the scene graph is plain JSON, a prompt can produce a scene directly, without generating source code.

For where this stands against Remotion and the Rust rendering state of the art, see Why not Remotion?.