← chug2k
Field Notes · Building with LLMs

Lottie vs Remotion: making motion graphics with an LLM

Two ways to make pixels move, two completely different mental models — and a model that’s now good enough to write either one for you. Here’s the same animation built twice, climbing from trivial to a 30-second launch video, so you can see exactly where each tool wins. Shown, not told.

TL;DR

If it lives inside your app and loops, reach for Lottie. If it’s a video you export, reach for Remotion.

01 · Two mental models

Interpolated vectors vs. a function of the frame

Before the demos, the one distinction everything else falls out of. Lottie and Remotion don’t just differ in API — they differ in who does the animating.

Lottie

vectors, interpolated live by a player

A designer sets keyframes in After Effects; the Bodymovin exporter writes a JSON file of shapes, transforms and keyframes. A small runtime (lottie-web, or Skia’s Skottie) reads that JSON and tweens between the keyframes at playback. The file is declarative and resolution-independent. You ship the JSON; the device draws it.

Remotion

every pixel = f(frame)

You write React components. On frame f, useCurrentFrame() returns f and you compute everything from it — positions, opacity, text, charts — with interpolate() and springs. A renderer steps frame by frame and rasterizes each one to a PNG, then stitches them into an MP4. It’s a program, not a document.

That single difference predicts the whole comparison. Declarative keyframes are unbeatable for small, looping, designer-authored motion that has to live inside an app. A frame-as-a-function is unbeatable when the motion is computed — math, data, hundreds of elements, or a four-minute timeline with audio. The demos below are just that line being drawn, over and over, at rising complexity.

Lottie — real JSON, played by lottie-web in this page Remotion — its frame model, simulated on canvas

02 · The complexity ladder

The same thing, built twice, getting harder

Each rung is the identical animation on both sides — a real Lottie file on the left, a frame-driven render on the right. Watch where they tie, where code pulls ahead, and where vectors win. The little frame counters are there to remind you both worlds are ultimately frame-based; they just decide what a frame means very differently.

03 · Driving it from Claude Code

Two prompts, two pipelines

Neither of these requires you to touch After Effects or write interpolate() by hand anymore. You describe the motion; the model writes the file and verifies it. The two pipelines look like this:

you ▸ make a Lottie like-button — grey heart that pops to red with a ring pulse, looping. use the text-to-lottie skill. claude ▸ reads text-to-lottie/SKILL.md writes public/lottie.json — groups wrapped, 0–1 colors, keyframe arrays npm run dev → opens the Skottie player pins ?frame=30, screenshots: heart mid-pop and red ✓
you ▸ 30-second launch video for "Dashbored" — cold open, the problem, a reveal, three product shots, a stats flex, a testimonial, a CTA. use Remotion. claude ▸ scaffolds a Remotion project, one <Sequence> per scene interpolate(frame, …) for every move; spring() for the pops npx remotion render → out.mp4, 30s @ 30fps

The Lottie side leans on a skill — a markdown file that teaches the model the exact JSON shape its player needs. And that skill is the whole reason this page exists.

The lesson, embedded This page’s first draft was written by an AI that was told to use the text-to-lottie skill — and didn’t. It name-checked the skill in a comment and then hand-rolled the JSON from memory. The Lottie column came out blank. Lottie fails silently: no console error, just nothing on screen. The bugs were exactly the ones the skill warns about — shapes not wrapped in a gr group, colors in 0–255 instead of 0–1, keyframe values that weren’t arrays. The fix wasn’t clever; it was reading the file: every shape inside a group ending in a tr transform, colors normalized 0–1 RGBA, every keyframe value an array, loops repeating their first value. The animations on the left are the corrected version. Referencing a skill is not the same as using one.

04 · The payoff

What you’d actually render

Everything above was a warm-up. Here is why Remotion exists — and why it’s the tool an LLM should reach for when the deliverable is a film, not a UI element. Below are four launch videos in four completely different registers. The first is made up, to show the idea. The other three are real: a family of Dokploy starter templates I actually ship — Skeleton Crew (request/response), Cauldron (background jobs), and Séance (realtime) — each a different backend shape, each shipping with its own mascot and its deploy “curses” pre-broken.

They share nothing visually — deadpan corporate, bone-and-charcoal, toxic-green, occult violet. But underneath, every one is the same kind of object: a single function of the frame. That’s the property that lets you restyle them, swap the script, or generate one launch video per repo in CI without re-animating a thing — which is precisely how you’d make these.

“Dashbored” is fictional and a little mean. Skeleton Crew, Cauldron and Séance are real — the clone link is in each video.

05 · The page itself isn’t a video

Landing-page motion: what you’d actually ship

Here’s the distinction you just put your finger on. Those launch films are videos — render once, embed the MP4, great for a YouTube ad or a social cut. But the landing page itself is not a video. You wouldn’t bolt a 4 MB MP4 to the top of the Séance site: it’s fixed-resolution (blurry on retina, letterboxed on a phone), heavy, autoplay-flaky on mobile, can’t go transparent, can’t recolor for dark mode. Right instinct — wrong tool for the page.

What goes on the page instead depends on how much motion you actually need:

MP4 / WebM avoid

Only for real footage or a one-off promo. Heavy, fixed-size, opaque, mobile-hostile as UI.

CSS / SVG simple

Perfect for the small stuff — fades, slide-in-on-scroll, hovers, a pulsing dot, a shimmer. Tiny, responsive, accessible. Gets clunky once motion is multi-part.

Lottie designed loops

The sweet spot for an animated hero — vector, a few KB, crisp at any size, loops, recolorable, one tag. The answer here.

Rive interactive

When the hero should react — scroll-scrub, hover, cursor-follow. Vector + a state machine; heavier toolchain.

So no — you wouldn’t reach for Remotion for the Séance or Skeleton Crew pages. The page hero isn’t a narrated film; it’s a tight loop that says what the thing does. Here’s what I’d actually put at the top of each — live Lottie, looping forever, a few KB each. Resize your window: they scale and stay razor-sharp, no MP4 anywhere.

Skeleton Crew

request → server → db, and the 200 comes back. An app’s heartbeat.

Cauldron

a job drops in, the worker brews it, the ring fills, done — on loop.

Séance

one message pulses out to every soul in the room.

And the genuinely small stuff — a “live” status dot, a button shimmer — is just CSS, no library at all:

Live · 3 souls connected ← one CSS rule each. You wouldn’t hand-write the heroes above this way — that’s where Lottie earns its keep.

That’s the clean split, and it’s the most practical takeaway in the whole post: a launch video is a file you render (Remotion → MP4); a landing-page animation is an asset that stays alive in the browser (Lottie, or CSS for the simple bits, or Rive when it must react). Same projects, two completely different jobs.

06 · Where Lottie actually wins

Does it only win for humans?

It’s tempting to read everything above as “Remotion is the powerful one; Lottie is the toy for little loops.” That’s wrong — but to see why, you have to untangle two completely different kinds of advantage that the usual “why Lottie” pitch jams together. An LLM pulls them cleanly apart.

The first kind is about the author. Lottie is how a motion designer’s After Effects work reaches production without an engineer rebuilding it by hand, and LottieFiles is a marketplace of thousands of ready-made animations you drop in. Both are real — and both are exactly what an LLM erodes. If a model writes a correct Lottie (or a Remotion scene) from one sentence, you no longer need the designer’s source file or someone else’s marketplace upload. So yes: a big slice of Lottie’s reputation really was a human win, and that slice is quietly going away.

The second kind has nothing to do with who — or what — authored it. It’s about what the thing is once it’s running, for the person using your app. Poke this one:

One ~4 KB file you can poke — recolor, resize, restage

live Lottie
Color
Size
Background

Recolor it, blow it up 3×, drop it on a different background — all at runtime, from the same few-kilobyte vector. A rendered MP4 can do none of these, no matter what wrote the MP4. This is what “a live asset, not a recording” means in practice.

Those wins don’t care whether a designer, a developer, or a model produced the JSON:

So — does Lottie only win for humans? The pipeline wins do, and they’re fading. But the runtime wins were never about the author at all; they’re about the end user. An MP4 can’t be recolored, can’t stay crisp at any size, can’t be transparent for free, can’t be interrupted and redirected. Lottie’s real moat was never that designers liked it. It’s that the output stays alive.

Remotion’s superpower is that the output is a file you can generate by the thousand. Lottie’s is that the output is never a file at all — it’s a living thing your app keeps animating.

07 · So which one?

The decision is the dividing line

You almost never have to choose between them on the same artifact, because they’re for different artifacts. The question isn’t “which is better” — it’s “is this thing a UI element or a video?”

Reach for Lottie when…

  • it lives inside your app and loops or reacts to a tap
  • it’s small and designer-authored — a spinner, toggle, like, empty state, onboarding flourish
  • you need one file across web + iOS + Android
  • file size and battery matter more than pixel-perfect compositing
  • the motion is fixed — it doesn’t need to read live data

Reach for Remotion when…

  • the output is a video file — MP4, GIF, a social clip
  • it’s data-driven or templated: per-customer, per-PR, per-row
  • the motion is a formula, or there are dozens of moving parts
  • you want audio, long timelines, or real text/typography
  • it should render headless in CI, not be authored in a GUI

And the meta-point, since this was really a post about doing it with an LLM: both tools are now a prompt away. The skill — or in Remotion’s case, the docs the model reads — is what stands between “describe the motion” and “working file.” The model is the easy part. Pointing it at the right rules, and checking that it followed them, is the job.

Postscript · Animating the mascot

Same mascot, four ways to make it move

Those mascots are flat PNGs. So: can you actually animate one? Yes — and the ways line up almost exactly with the rest of this post, from cheapest to most capable. Pick a mascot below and watch it brought to life four different ways; notice what each can and can’t do. (The Anduin one started as nothing but the logo — I had it traced to an SVG and rigged from there, which is why it’s the crispest of the bunch.)

1 · Puppet the PNGraster · moved

The cheapest trick, and what the launch videos do: take the flat image and move it as a unit — float, breathe, glow — on the frame timeline. Can’t move its own parts (the bubbles are painted in), but it’s instant and needs no new art.

2 · Rig it as vectorlottie · rebuilt

Redrawn as a real Lottie — shapes with independently animated parts: it blinks, the bubbles rise, the flame flickers. A stylized redraw, not the painted look — but it’s a few KB, recolorable, and infinitely crisp. The left-column way.

3 · Sprite sheetgpt-image-2 · frames

Kept the painted look: I had gpt-image-2 draw a 2×2 sheet of four frames (calm → bubbling → splash → blink) and flip them like a flipbook. Gorgeous — but it’s baked raster: heavy, locked to one background (the model refused a transparent one), and you can’t recolor it. A recording, basically.

4 · Rig it interactiverive · state machine
a live Rive file · hover / click it

Rive is the third tool worth knowing: vector like Lottie, but with a state machine you drive from input — so a mascot can react to hover, clicks, or app state. (This is a Rive sample running through its runtime; you’d rig your own in Rive’s editor, not from a prompt — yet.)

That spread is the whole post in miniature. Puppet and sprite sheet are the Remotion-ish raster routes — fast, faithful to the artwork, but recordings. Lottie is the live vector that ships inside your app. Rive is where it’s going: vector that’s also interactive. For a brand mascot that needs to react, rig it in Rive; for one that just needs to loop in a button, Lottie; for a one-off in a video, puppet the PNG and move on.