Figma Motion → real code

Animate in Figma.
Ship it everywhere.

Blinn Motion turns a Figma Motion timeline into a tinyMotionDoc and plays it with a pure-JS engine — the same motion, frame for frame, on every platform.

renders identically on
DOMCanvasReactReact Native
card.motion60 fpsLIVE
0.00s
springcubic-bézierloop
The pipeline

From Figma timeline
to a tree of pure numbers

No black box in the middle. Your animation becomes an open document, then a deterministic render tree — the same maths everywhere it plays.

01
Figma Motion

Animate on the timeline

Keyframes, easing curves and springs live in node.animations — raw data, never rasterized.

02
@blinn-motion/figma-plugin

Export, don't bake

The plugin reads the timeline and emits a tiny MotionDoc — no PNGs, no video, just your motion.

03
@blinn-motion/core

sample(doc, t)

The pure render method walks the doc, solves every track at time t, returns a resolved tree of final numbers.

one resolved tree · four thin adapters
DOMdivs · CSS · SVG
Canvaspure-JS 2D
React<BlinnMotion /> component
React Nativenative <View> / <Text>
Adapters

One document.
Every platform, frame for frame.

Every adapter paints the same resolved render tree, so an animation looks and times identically wherever it runs. The adapters are thin; the engine does the thinking.

DOM

@blinn-motion/dom
full fidelity

Full-fidelity CSS adapter — nested divs, gradients, SVG vector paths with arrowheads, clip-path stars, masks and procedural shaders.

import { create } from "@blinn-motion/dom";
create(el, doc, { loop: true }).play();

Canvas

@blinn-motion/canvas
zero DOM

A pure-JS 2D canvas painter for the very same resolved tree — one immediate-mode draw per frame, no DOM nodes.

import { create } from "@blinn-motion/canvas";
create(el, doc, { loop: true }).play();

React

@blinn-motion/react
component + hook

A declarative component and hook. Switch the painter with one prop; play, pause and seek through a ref.

<BlinnMotion doc={doc} renderer="canvas" loop autoplay />

React Native

@blinn-motion/react-native
native views

The same timing on native <View> / <Text>. No native module, no Skia dependency — just the shared core maths.

<BlinnMotionView doc={doc} loop />
The render engine

One pure method does the work

@blinn-motion/core is time-based and DOM-free. The whole engine hangs off a single deterministic function — everything else is a thin painter.

core/sample.ts
// THE render method — pure, DOM-free
export function sample(doc: MotionDoc, t: number) return doc.layers.map((layer) =>
    resolve(layer, t)   // walk + sample every track
  );


// each track, eased + composed over the base
const v = ease(key.easing, local);
node[p] = op === "offset"
  ? base + lerp(a, b, v)   // additive
  : lerp(a, b, v);          // replace

// → resolved RenderNode tree (final numbers)
easing solvers
linearconstant rate
holdstep / no tween
cubicBezierNewton-Raphson
springdamped approx.
Time-based, in seconds

The core speaks one language: t in seconds. The playback clock is shared, so play / pause / seek / loop behave the same everywhere.

Composes stacked tracks

Multiple tracks per property compose over the base value — set replaces, offset adds — so springs and curves layer cleanly.

Returns final numbers

Every transform, RGBA color and shape vertex comes out resolved. Adapters never re-interpret intent; they just paint.

Why Blinn Motion

Everything the render engine gives you

A small core with a sharp focus: resolve motion to numbers, then paint it the same way on every surface you ship to.

Pure-JS render core

The maths is DOM-free and unit-tested. Only the adapters touch a platform — the engine runs anywhere JS does.

Springs & curves, solved

Linear, hold, cubic-bezier (Newton-Raphson) and damped springs — sampled per frame, not pre-baked.

MotionDoc — open format

A small, readable JSON document you own. Inspectable, diffable, versionable — no proprietary blob.

Identical timing everywhere

Same resolved tree, same shared clock. An animation times the same on DOM, Canvas, React & Native.

Scrub · seek · loop · speed

Drive playback frame-accurately: seek(s), seekFraction(0…1), loop and variable speed — all from the core.

Gradients, masks, shaders

Nested transforms, linear & radial gradients, SVG vector paths, clip-path stars, masks and procedural shaders.

Tiny & framework-agnostic

No runtime dependencies in the core. Drop it into vanilla JS, React or React Native without ceremony.

First-class Figma plugin

Select an animated frame, preview it live, and download the MotionDoc — straight from the Motion timeline.

Use it in code

Three lines to motion

Hand the engine a MotionDoc and a host element. Pick a renderer, press play. The control surface — play, pause, seek, seekFraction, loop — is identical across every adapter.

install
npm i @blinn-motion/dom
import { create } from "@blinn-motion/dom";
import doc from "./card.motion.json";

const player = create(
  document.getElementById("stage")!,
  doc,
  { loop: true }
);

player.play();          // pause(), toggle()
player.seek(0.8);       // seconds
player.seekFraction(0.5); // 0…1
import { create } from "@blinn-motion/canvas";
import doc from "./card.motion.json";

// same call, a pure-JS 2D painter
const player = create(canvasHost, doc, {
  loop: true,
});

player.play();
import { BlinnMotion } from "@blinn-motion/react";
import doc from "./card.motion.json";

export default function Hero() {
  return (
    <BlinnMotion
      doc={doc}
      renderer="canvas"  // or "dom"
      loop
      autoplay
    />
  );
}
import { BlinnMotionView } from "@blinn-motion/react-native";
import doc from "./card.motion.json";

export function Splash() {
  return <BlinnMotionView doc={doc} loop autoplay />;
}
Lottie, but not Lottie

Inspired by Lottie.
Built differently.

Lottie proved the idea: ship motion as data, not video. Blinn Motion takes that idea to the Figma Motion era with its own format and its own runtime — so you own the whole pipeline.

LottieBlinn Motion
Authoring sourceAfter Effects (Bodymovin)Figma Motion timeline
Document formatLottie JSONMotionDoc — small, readable, yours
Render engineMature, feature-rich runtimePure-JS core, DOM-free maths
AdaptersSVG · Canvas · HTML playersDOM · Canvas · React · React Native
Cross-platform timingPer-playerOne shared clock & resolved tree
SpringsVia AE expressionsFirst-class spring easing

Lottie is a trademark of its respective owners. Blinn Motion is an independent, MIT-licensed project — not affiliated.

Open source · MIT

Ship motion that looks
identical everywhere.

Export from Figma Motion, drop the MotionDoc into your app, and let the engine do the rest — on the web, in React, on native.

$ npm i @blinn-motion/dom @blinn-motion/core