The thing on screen is the thing in the file
On the left is the real source of a Motion Code video: the first fifteen seconds of a 28-scene explainer. On the right, that exact code runs: the video plays scene by scene, avatar and captions off, with the prompt behind each screen underneath. Nothing is being streamed. The code on the left is the video on the right, an HTML document with a GSAP timeline, running live in your browser.
Because it's code, you can click any element and change its text, its color, its size; drag it; or tell the model "make this calmer" and have it rewrite just that element. None of that is possible with pixels. With pixels you re-render. The reframe isn't cosmetic. It changes what an edit is.
<!-- a scene is one self-contained document --> <div class="stage" data-od-component="Stage Canvas"> <h1 data-od-component="Headline">LangGraph</h1> <svg class="graph"> ... nodes + edges ... </svg> </div> <script> const tl = gsap.timeline(); // joins the ONE global clock tl.from(".graph .node", {opacity:0, scale:.8, stagger:.08}); </script>
An LLM is, at its core, a code engine. Pixel generation fights that. Video-as-code turns the model's weakness into its strength.
There is exactly one clock
This is the keystone. GSAP automatically aggregates every tween created anywhere on the page
into a single globalTimeline. Motion Code leans its entire architecture on that one fact. That single
object is, simultaneously:
- what the editor pauses and resumes when you click the canvas,
- what a drag gesture freezes, so the animation can't fight your cursor,
- what the caption overlay's tweens automatically join. The caption script never talks to the renderer. It just makes tweens, and they are already on the clock,
- and what the renderer registers and drives, frame by frame, by seeking.
And here's what the one clock buys: determinism, for free. The renderer registers the timeline,
pauses it, and drives time by seeking to each frame. Nothing runs on Date.now() or
requestAnimationFrame. Seek to t = 2.0s, screenshot, repeat. The same scene renders
byte-for-byte identically every time, on any machine. A stochastic, model-generated artifact becomes a
deterministic function of time.
Editing a document that is rewriting itself
Here's the problem nobody expects. The scene's timeline is continuously overwriting each
element's transform, sixty times a second. So when you drag an element, you can't write to
transform, because the next animation frame stomps it.
The fix is the good part. Motion Code moves elements through a channel the animation never
touches: HTML elements move via layout left/top plus the individual scale/rotate
CSS properties; SVG elements get a dedicated <g> wrapper carrying the offset as data-attributes.
The element's own animated transform then composes on top of your move, instead of clobbering it.
Move the layer, not the pixels. It's the Figma model, rebuilt on an adversarial substrate.
Try it. The element below is animating right now. Drag it. Grab the corner and resize it.
The float never stops while you edit, because your drag writes to left/top, your resize writes to the
scale property, and the animation owns transform. Three orthogonal channels, composed by the browser.
The AI-edit path is just as disciplined. "Describe a change" does not regenerate the
scene. A hand-written balanced-tag scanner finds the exact character span of the selected element, and only that
span is replaced, so the GSAP <script> that drives everything stays byte-for-byte intact.
Regenerating would be the easy path; it would also sever the animation wiring. So it's refused, by both a parser and
a prompt.
The line between what the model decides and what code guarantees
The single most important lesson in the codebase is a boundary, and it was found the hard way. It's even written down, in a comment:
"A mechanical per-item timing job belongs in a pure, unit-tested function, not a prompt."
The team tried making the model do word-by-word caption timing. Models are unreliable at "apply this to every one of N items." So that work was moved across the boundary into deterministic code. The same pattern recurs three times, each a mechanical guarantee layered under an unreliable generative process:
| The model is unreliable at… | …so a pure function guarantees it |
|---|---|
| Per-word caption timing across N words | Character timing → words → lines, unit-tested, one shared source for preview and export so they can't drift |
| Leaving no element accidentally static | An orphan-revival pass grafts ambient motion onto any element the model forgot to animate, no regeneration needed |
| Avoiding render-breaking infinite loops | Every "forever" loop is mechanically rewritten to a large-but-finite one before render |
The model brings the judgment: what the scene should look like, which specialist to call. Code brings the guarantees: timing, determinism, safety. Knowing exactly where that line sits, from experiment rather than theory, is most of what makes this reliable.
Determinism, earned the hard way
Frame-seeking a browser sounds simple until the scene refuses to hold still. AI scenes love "forever" loops for ambient motion. Perfect in a browser, poison for a renderer that needs the page to settle before each screenshot. And they come in two forms, one of which is a genuine trap:
| Loop form | The trap |
|---|---|
GSAP repeat:-1 | On the global clock, so pausing the clock stops it. Rewritten to repeat:20 anyway, so a seek never lands on an infinite tween. |
Native SVG SMIL repeatCount="indefinite" (a feTurbulence "boil") | Pausing the GSAP clock does NOT stop it. SMIL runs on its own native clock, so the page never settles and the render hangs. "Confirmed empirically: every scene with this pattern hung." |
The counter-measure is belt-and-suspenders: the craft prompt teaches the model to avoid these, and the renderer mechanically rewrites both forms to finite loops regardless. You defend a determinism boundary at the layer where the mistake is made and at the layer where it would bite.
One brief, many looks
The same "TaskFlow" brief, rendered in different styles. Every tile below is a real Motion Code scene, live. What makes each look read as professional isn't a bigger model. It's a hand-tuned craft skill: a page of expert direction on palette, line weight, lighting, and motion personality, injected into generation.
And the economic bet underneath it: because the craft skill is doing the quality work, the model's own hidden "thinking" budget is set to zero. That halves the cost, from roughly ₹139 down to ₹70 per one-minute video, at full quality. The intelligence lives in a curated, versioned prompt asset, and the model's reasoning budget is bought back. Move the smarts into the prompt, and stop paying the model to re-derive them.
Bring your own style
Every look you just saw is a file. Behind each style is a skill.md: a page of written
direction on palette, line weight, motion and mood. So a new style is not a model retrain. It is a new document.
Hand Motion Code a reference image or a link you like, and it reads that into a fresh skill.md, which
then drives generation exactly like the built-in nine. Your brand becomes a skill, and every future video inherits it.
# Warm Editorial palette: amber · slate · paper line: hand-inked, 2px motion: settle, then breathe mood: confident, dry
with warmth.
What a minute costs
Photoreal models bill by the second, and you pay the whole thing again on every re-render. These are their live rates. Motion Code produces the same minute for about ₹70, a little over ₹1 a second, because it draws code instead of sampling pixels. And an edit is a text change, not a new render, so fixing one word never buys the minute twice.
The line it won't cross
Cheap and editable comes from one constraint: everything is drawn in code. That is also the honest limit. Motion Code cannot render a photograph of a real person, or literal live-action footage, because it does not sample pixels. If a brief needs a hyper-real human face or real camera footage, this is the wrong tool, on purpose.
- UI, product and dashboard mockups
- Diagrams, flows and state machines
- Kinetic type and data-viz
- Hand-drawn, isometric, cinematic, neon looks
- Photoreal human faces
- Live-action or real camera footage
- Literal photography of a place or product
- Hyper-real 3D and heavy VFX
Crash-consistency, on a laptop
The render pipeline runs on one machine, but it's engineered like a small distributed system, because the failure modes are the same:
| What goes wrong | What the system does |
|---|---|
| Laptop dies mid-render | A content-hashed cache lives beside the script, never in temp. On restart, already-rendered scenes are reused. Publish is atomic: render to a temp file, then same-directory rename, so a crash can't leave a half-written clip. |
| A render logic change ships | CACHE_VERSION bumps and invalidates every entry at once, so a code change can never silently reuse a stale clip. |
| One scene hangs forever | A timeout race: the render is raced against a timer, because a cancellation signal alone can't force a stuck await to return. After one retry, a deliberately-simple placeholder card renders for that scene only (never cached, so the next export retries it), so one bad scene can't sink a 52-scene render. |
| An interrupted render orphans a headless Chrome | A reaper GCs leftover processes on startup and before each export, gated on live-PID probes, so it can never kill a render that's actually running. |
The whole pipeline
Everything above is one path: from a line of intent to a deterministic MP4.
Where the honesty is
Good architecture means naming its edges:
- Export is deliberately local. The cloud render worker was built and measured. It wasn't faster at 2 vCPU and it lost the durable cache, so rendering stays on the machine, on purpose. A measured choice, not a missing feature.
- Captions "for free" is an ElevenLabs property, not a universal one. Because ElevenLabs returns character-level timing with the audio, captions need no transcription. The Google voice path does transcribe. It runs speech-to-text on its own synthesized audio, then rebuilds a character grid to match ElevenLabs' shape, so the caption code downstream never knows the difference. Same interface, a round-trip behind it.