Getting started

What you can paste

JSX, TSX or plain HTML. Pasted markup is normalized before it reaches the frame, so a block copied from a browser's element inspector works as well as one copied from your editor.

Four shapes of paste
Bare JSX. Raw HTML, normalized first (class becomes className, void tags are closed, comments go). A module with export default (a function, an arrow or a const) or export { Card }. And code followed by markup, where the code runs first so its data is real. Up to 250KB: one component, not a file tree.
Imports are dropped, and a few become real elements
Every import line is removed before the paste runs. next/image renders a real <img>, next/link a real <a>, and Motion’s motion.div (or m.div) the <div> it names, box and all, with the props that only mean something to Next or Motion dropped. Nothing else is guessed: a design-system Button could render anything.
A name it can’t see becomes a stand-in
State, a data array, a config object: each unknown name is a stand-in. In text it reads as a placeholder (step.title → “Title”). Mapped as a list, it gives three wireframe items, so a grid keeps its shape. In a condition it counts as true, and called, it returns another stand-in.
A component it can’t see renders its children
An imported <Card> is dropped and what you put inside it renders in its place. Its own box is lost, since there’s no way to know what it draws. A component defined in the paste runs as written, children and all.
Hooks, state and events don’t run
useState is a stand-in like any other name, so a panel behind open && renders as if open. Effects never run, and event handlers are inert, HTML’s lowercase onclick included. ref, key and dangerouslySetInnerHTML are ignored. What you animate is the component’s markup, not its behavior.
Where it runs
Only inside a sandboxed frame with an opaque origin. The pasted code never runs in the editor itself, and nothing it does reaches your session. Images load over https, so a real avatar survives the paste.
Tailwind classes work
The frame loads Tailwind, so utility classes render as they do in your app. Semantic tokens like bg-card resolve against the stage, which is always dark, so a pasted component looks the way it would in your app’s dark theme whichever theme you browse the site in.
Animate a child as well as the root
Pick a node inside what you pasted, like a card in a list or a heading above its body copy, and it gets its own tracks. That’s how you build a stagger here: several children, one decision. Picked children are outlined on the stage so you can see what you’ve picked. The outlines hide while the animation plays and come back when you pause.
A component that needs width
Navbars, footers and full-bleed sections need a viewport to lay out properly, so an element can have an explicit width. Everything else is sized to its content.
Broken paste fails loudly
Source that won’t compile shows its error on the stage instead of rendering nothing.
Editing it later
“Edit source” reopens the same dialog for the element you already animated, so fixing a typo doesn’t cost you the timeline you built on it.
Nothing to install
There’s nothing to set up and no account needed. The editor works and exports signed out; an account saves your work and lets you share it.
Your account
Sign in with an email link or 6-digit code, Google or GitHub. The free plan keeps up to 5 saved animations; saving over one is never refused. Settings, under your avatar, is where you change your email, export everything as JSON, or delete the account and all of it.
Unsaved work
Until you save, your browser keeps a copy of what you changed, so closing the tab or signing in to save doesn’t lose it. It comes back when you open the editor again, or that saved animation, with a note on the stage. Discard, there or in ⌘K, throws it away. A template or New animation still opens as you asked, and changes older than the animation’s latest save are offered rather than put back. The copy never leaves this browser, and one made while signed in only comes back for that account.

A component that already animates

Import as tracks
Paste a component written with Motion and the dialog says what it already animates (“This component already animates 3 elements”). It’s added with that animation as tracks you can tune: the root’s tracks on the component, and each animated element inside it as a picked child with its own. One undo takes the whole import back. Uncheck it to start from a still component.
What an import reads
initial, animate and transition written as literals: numbers and pixel, degree or turn strings, keyframe arrays with times, named and cubic-bezier eases, springs with stiffness, damping and mass, per-property transitions and delays, and a blur() filter or a color with its starting color written. whileHover, whileTap, whileFocus and whileDrag become states. Where no transition is written, it uses Motion’s defaults: a spring for transforms, a 0.3s ease for the rest.
What it leaves alone
A computed value, a spread, a variant label or variants, exit, layout animation, a repeat, a spring set by its duration or bounce, or a property the editor doesn’t animate. Each is listed under “could not be read”, and its element is left exactly as written, so nothing is imported as a different animation from the one the code runs. A state’s own tween duration becomes the editor’s fixed one, and the list says so.
Exporting it again
The Motion export writes the tuned animation back onto the same elements, replacing the props they had instead of adding a second set. An element it couldn’t read keeps its own props, untouched.