Migrating from dotlottie-js

A code-for-code guide to moving a project from dotlottie-js to dotlottie-io, covering API differences, package changes, and what's new.

Migrating from dotlottie-js

This guide is for teams with an existing dotlottie-js integration who want to move to dotlottie-io.

Why migrate

dotlottie-io does the same job as dotlottie-js — creating, reading, and manipulating .lottie files — with a Rust core exposed through Node.js and WebAssembly bindings. Compared to dotlottie-js, it offers:

  • A fully synchronous API for local file operations (no Promise-based build() step)

  • A lazy reader (DotLottieReader) for inspecting large archives without loading everything into memory

  • Password-protected, AES-256 encrypted archives

  • Cross-reference query methods (which animations use this theme/asset/state machine)

  • A shared Rust core with other parts of the dotLottie ecosystem

dotlottie-io will supersede dotlottie-js, so it's best to migrate earlier rather than later.

1. Package name change

This is the easiest thing to miss: the npm scope changes.

- npm install @dotlottie/dotlottie-js
+ npm install @lottiefiles/dotlottie-io
- import { DotLottie } from '@dotlottie/dotlottie-js'
+ const { DotLottie } = require('@lottiefiles/dotlottie-io')

dotlottie-io's Node.js package is CommonJS-first (require), though it also works with import under Node's interop. The browser build is ESM-only and requires an explicit init() call — see Platform Notes.

2. At a glance

Aspectdotlottie-jsdotlottie-io
CorePure JavaScript/TypeScriptRust, with Node (N-API) and WASM bindings
API styleAsync, single fluent DotLottie classSync, split across DotLottie / DotLottieBuilder / DotLottieReader / DotLottieMerger
Build stepRequired: await dotlottie.build() before exportNot required — DotLottieBuilder.build() is the construction step itself, and is synchronous
URL fetchingBuilt in (addAnimation({ url }))Not built in — fetch yourself, then pass the bytes
Browser downloadBuilt in (.download(filename))Not built in — build a Blob from toBytes() yourself
Lazy/low-memory readingDotLottieReader
Password protection✅ AES-256, via a password argument on I/O methods
Cross-reference queriesanimationsUsingTheme, animationsUsedByStateMachine, assetReferences, animationsUsingAsset
Merge collision handlingmerge() throws on any duplicate IDDotLottieMerger with a chosen MergeStrategy (Rename/Skip/Fail)
Standalone asset attachmentNot exposed on DotLottie — assets come from animation JSON onlyaddImage/addFont/addAudio as first-class methods on DotLottie
Font assetsExtracted from animation JSON onlySame, plus explicit addFont/getFont/fontFilenames

3. Code-for-code examples

Creating and saving a file

dotlottie-js:

import { DotLottie } from "@dotlottie/dotlottie-js";

const dotlottie = new DotLottie();
dotlottie.addAnimation({ id: "hero", data: heroLottieJson });
await dotlottie.build();

const buffer = await dotlottie.toArrayBuffer();
await writeFile("output.lottie", Buffer.from(buffer));

dotlottie-io:

const { DotLottieBuilder } = require("@lottiefiles/dotlottie-io");
const { writeFileSync } = require("node:fs");

const builder = new DotLottieBuilder();
builder.addAnimation("hero", JSON.stringify(heroLottieJson));

const dl = builder.build(); // synchronous
writeFileSync("output.lottie", dl.toBytes()); // synchronous

Note the different construction pattern: dotlottie-js mutates a new DotLottie() in place and finalizes it with build(); dotlottie-io queues content on a DotLottieBuilder and build() produces a DotLottie.

Loading and inspecting a file

dotlottie-js:

import { DotLottie } from "@dotlottie/dotlottie-js";

const dotlottie = await new DotLottie().fromArrayBuffer(arrayBuffer);
console.log(dotlottie.animations.length);

dotlottie-io:

const { DotLottie } = require("@lottiefiles/dotlottie-io");

const dl = DotLottie.fromBytes(buffer); // synchronous, no await
console.log(dl.animationIds().length);

Adding a theme

dotlottie-js:

dotlottie.addTheme({
  id: "dark",
  data: { colors: { primary: "#FFFFFF" } },
});

dotlottie-io:

dl.addTheme("dark", "Dark Theme", JSON.stringify({ rules: [] }));

Note the theme data shape itself differs too — dotlottie-io (and dotLottie V2 generally) expects a { rules: [...] } structure, not the ad hoc { colors: {...} } shape some dotlottie-js examples use. Check your theme JSON against the V2 theming spec if you're carrying data over directly.

Merging files

dotlottie-js:

const merged = dl1.merge(dl2, dl3); // throws on any duplicate ID
await merged.build();

dotlottie-io:

const { DotLottieMerger, MergeStrategy } = require("@lottiefiles/dotlottie-io");

const merger = new DotLottieMerger(MergeStrategy.Rename); // choose collision behavior
const merged = merger.merge(dl1, [dl2, dl3]); // synchronous, ready immediately

4. What doesn't carry over directly

  • addAnimation({ url: '...' })dotlottie-js fetches the URL during build(). dotlottie-io has no network layer at all: fetch the JSON yourself (fetch(url).then(r => r.arrayBuffer()) or Node's http/https), then call addAnimation(id, buffer).

  • .download(filename)dotlottie-io doesn't touch the DOM. In the browser, build the download yourself from the bytes toBytes() returns:

    const bytes = dl.toBytes();
    const blob = new Blob([bytes], { type: "application/zip" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "output.lottie";
    a.click();
    URL.revokeObjectURL(url);
  • Author/description/keywords metadata — these were dotlottie-js v1 (pre-1.0.0) fields (setAuthor, setDescription, setKeywords, setRevision). They were already dropped from dotlottie-js's own v2 manifest schema, so if you're migrating from a dotlottie-js v2 project this doesn't change anything. If you're still on pre-1.0.0 dotlottie-js, see its own migration guide first for the v1→v2 manifest changes, since the same fields are absent from dotlottie-io's manifest too.

  • Playback fields on animations (autoplay, loop, speed, direction, hover, intermission, themeColor) — also already dropped in dotlottie-js v2's AnimationOptions in favor of player-side configuration; dotlottie-io's AnimationOptions matches this (see Managing Animations).

5. New capabilities worth adopting

Once the port is functionally complete, consider using what dotlottie-io adds:

General recommendations

  1. Update the package name and import style first, then run your existing test suite against the new synchronous API shape — most failures will be awaits that need removing or restructuring, not logic changes.

  2. Replace any addAnimation({ url }) usage with an explicit fetch step.

  3. Replace any .download() usage with the Blob/anchor pattern shown above.

  4. If you use themes, verify their JSON shape matches the { rules: [...] } structure dotlottie-io expects.

Next up: API Reference

Last updated: August 5, 2026 at 11:47 AMEdit this page