npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lottiefiles/dotlottie-io

v0.0.4

Published

Rust library for creating, modifying and updating .lottie files. Contains bindings for Node and WASM.

Readme

dotlottie-io

Rust-powered library for creating, reading, and modifying .lottie files — with native Node.js (N-API) and WebAssembly (WASM) bindings.

A .lottie file is a ZIP archive containing a manifest, Lottie JSON animations, themes, state machines, images, fonts, and audio. This library gives you a complete read/write API over that format from both Node.js and the browser.


Installation

Node.js

npm install @lottiefiles/dotlottie-io
# or
yarn add @lottiefiles/dotlottie-io

The correct prebuilt native binary for your platform is selected automatically — no build toolchain required.

Supported platforms

| Platform | Architecture | | -------- | -------------------------------------------- | | macOS | x64, arm64 (Apple Silicon) | | Linux | x64, arm64, armv7 (glibc); x64, arm64 (musl) | | Windows | x64, arm64 | | Browser | WebAssembly |

Web (WASM)

npm install @lottiefiles/dotlottie-io

Two pre-built bundles are included — pick whichever fits your setup:

| Bundle | File | Use when | | ------ | -------------------------------------- | -------------------------------------------- | | ESM | @lottiefiles/dotlottie-io/web | Vite, webpack, Rollup, or any modern bundler | | IIFE | release/browser/dotlottie-io.iife.js | Vanilla <script> tag, no build step |

See the Web API section below for usage.


ZIP layout

| Path | Content | Notes | | --------------- | ---------------- | ---------------------------------- | | manifest.json | Package manifest | Always present | | a/{id}.json | Lottie animation | v2; v1 used animations/{id}.json | | t/{id}.json | Theme | v2 only | | s/{id}.json | State machine | v2 only | | i/{filename} | Image asset | v2; v1 used images/{filename} | | f/{filename} | Font asset | v2 only | | u/{filename} | Audio asset | v2; v1 used audio/{filename} |

The library reads both v1 and v2 path layouts. It always writes v2.


Building from source

Prerequisites

  • Rust (stable toolchain)
  • Node.js ≥ 18
  • Yarn
  • binaryen (already listed as a devDependency — provides wasm-opt)
git clone https://github.com/lottiefiles/dotlottie-io.git
cd dotlottie-io
yarn install

Build commands

# Native Node.js binding for the current platform (release)
yarn build

# Native binding, unoptimized (faster compile, useful during development)
yarn build:debug

# WebAssembly target only
yarn build:wasm

yarn build:wasm runs three steps internally:

  1. Compiles the Rust crate to wasm32-unknown-unknown via wasm-pack (requires wasm-pack — install with cargo install wasm-pack)
  2. Post-processes the output with wasm-opt --enable-bulk-memory --enable-nontrapping-float-to-int -O4 (the Rust compiler emits bulk-memory and non-trapping float-to-int instructions that need these flags)
  3. Bundles the JS glue layer with esbuild into the ESM and IIFE outputs

Other scripts

yarn test          # run the test suite with ava
yarn bench         # run benchmarks
yarn format        # format JS, Rust, and TOML sources
yarn lint          # lint with oxlint

Releasing

Releases are driven by Changesets and the Release workflow (.github/workflows/release.yml). Publishing is fully automated — you never run npm publish by hand.

1. Add a changeset with your change

On your feature branch, after making your changes:

yarn changelog          # changeset add — pick patch/minor/major and write a summary

This writes a file under .changeset/. Commit it alongside your code and open a PR. To check whether a branch already has one:

yarn changelog:check    # changeset status --since=main

2. Merge your PR to main

The Release workflow runs and the Changesets action opens (or updates) a "chore: update versions" PR. That PR consumes all pending changesets — bumping the version in package.json and updating CHANGELOG.md. No packages are published yet.

3. Merge the "chore: update versions" PR

Merging it triggers the publish run, which:

  1. Builds every target — the build matrix cross-compiles all 9 native .node binaries (macOS, Linux glibc + musl, Windows), and build-wasm builds the browser/WASM bundle.
  2. Assembles the packagesnapi create-npm-dirs scaffolds the per-platform packages, yarn artifacts drops each .node into its package, and the WASM bundle is restored into release/browser/.
  3. Publisheschangeset publish publishes everything to npm, then re-publishes to GitHub Packages, and creates a GitHub Release.

You can also start a run manually from the Actions tab (workflow_dispatch).

What gets published

| Package | Contents | | ----------------------------------------- | -------------------------------------------------------------------- | | @lottiefiles/dotlottie-io | JS loader (. → Node), WASM bundle (./web), and type definitions | | @lottiefiles/dotlottie-io-<platform> ×9 | one prebuilt .node binary each, wired in as optionalDependencies |

All 10 packages are created automatically on first publish — there is nothing to pre-create on npm. Installing the main package pulls in only the matching platform binary via optionalDependencies.

Required secrets

| Secret | Used for | | -------------- | --------------------------------------------------------------------------------------------------- | | NPMJS_TOKEN | publishing to npm — must be an Automation token with publish rights to the @lottiefiles scope | | GITHUB_TOKEN | GitHub Packages + GitHub Releases (provided automatically by Actions) |


API Reference — Node.js

const {
  DotLottie,
  DotLottieBuilder,
  DotLottieMerger,
  DotLottieReader,
  MergeStrategy,
} = require('@lottiefiles/dotlottie-io')

JSON payloads are passed into the API as Buffer and returned from the API as string. Use JSON.parse() directly on the returned value.


DotLottie

The core class representing a loaded or built .lottie package.

Static methods

DotLottie.fromFile(path: string, password?: string): DotLottie

Load a .lottie file directly from a filesystem path. Pass password to open a password-protected archive.

DotLottie.fromBytes(data: Buffer, password?: string): DotLottie

Load a .lottie file from raw bytes (e.g. the result of fs.readFileSync). Pass password to decrypt a password-protected archive.

Serialization

dotlottie.toBytes(password?: string): Buffer

Serialize the package to a .lottie ZIP Buffer. Pass password to produce an AES-256 encrypted archive. Write to disk with fs.writeFileSync.

Animations

dotlottie.addAnimation(id: string, jsonData: Buffer | string, options?: AnimationOptions): void
dotlottie.removeAnimation(id: string): void
dotlottie.getAnimationJson(id: string): string | null
dotlottie.animationIds(): string[]

getAnimationJson returns null if the ID does not exist. removeAnimation throws for unknown IDs.

When a Lottie JSON contains embedded base64 assets (images, fonts, audio), addAnimation automatically extracts them into the appropriate ZIP directories and rewrites the asset references in the JSON to point to the stored files.

AnimationOptions
interface AnimationOptions {
  name?: string // display name in the manifest
  initialTheme?: string // ID of the theme applied by default
  background?: string // background colour hint
  themes?: string[] // IDs of themes associated with this animation
}

Themes

dotlottie.addTheme(id: string, name: string | null, jsonData: Buffer | string): void
dotlottie.removeTheme(id: string): void
dotlottie.getThemeJson(id: string): string | null
dotlottie.themeIds(): string[]

name is an optional human-readable display name. Pass null to omit it.

State machines

dotlottie.addStateMachine(id: string, name: string | null, jsonData: Buffer | string): void
dotlottie.removeStateMachine(id: string): void
dotlottie.getStateMachineJson(id: string): string | null
dotlottie.stateMachineIds(): string[]

Assets

Assets (images, fonts, audio) are stored as raw binary files inside the ZIP. All three add* methods return the actual filename stored, which may differ from the requested name if a collision occurred (see Filename deduplication below).

dotlottie.addImage(filename: string, data: Buffer): string
dotlottie.getImage(filename: string): Buffer | null
dotlottie.imageFilenames(): string[]

dotlottie.addFont(filename: string, data: Buffer): string
dotlottie.getFont(filename: string): Buffer | null
dotlottie.fontFilenames(): string[]

dotlottie.addAudio(filename: string, data: Buffer): string
dotlottie.getAudio(filename: string): Buffer | null
dotlottie.audioFilenames(): string[]

Only .mp3 is supported for audio. addAudio throws InvalidAudioFormat for any other extension.

Filename deduplication

When the requested filename already exists in the package, the asset is stored under a renamed key rather than throwing an error. The rename follows the pattern {stem}_{n}.{ext}, incrementing n until a free slot is found:

const first = dl.addImage('logo.png', data) // → 'logo.png'
const second = dl.addImage('logo.png', data) // → 'logo_1.png'
const third = dl.addImage('logo.png', data) // → 'logo_2.png'

The returned string is the key to use with getImage / getFont / getAudio. This matches the behavior of MergeStrategy.Rename and the asset extraction that runs during addAnimation.

Query methods

Cross-reference queries over the archive contents.

dotlottie.animationsUsingTheme(themeId: string): string[]

Returns animation IDs whose manifest entry references the given theme (via initialTheme or the themes array).

dotlottie.animationsUsedByStateMachine(stateMachineId: string): string[]

Returns all unique animation IDs referenced by PlaybackState entries in the given state machine. Returns an empty array if the state machine is not found.

dotlottie.assetReferences(animationId: string): { images: string[], fonts: string[], audio: string[] }

Returns categorised external asset filenames referenced by the animation's Lottie JSON. Filenames are bare basenames (e.g. "image_0.png", "cartoon.ttf"). Returns empty arrays if the animation is not found.

dotlottie.animationsUsingAsset(filename: string): string[]

Reverse lookup: returns animation IDs that reference the given asset filename in their Lottie JSON.

Manifest

dotlottie.getManifestJson(): string

Returns the full manifest as a JSON string.

dotlottie.setInitial(animationId?: string | null, stateMachineId?: string | null): void

Set which animation or state machine the player loads first. Pass null to clear.

dotlottie.getInitialAnimationId(): string | null

Returns the ID of the initial animation declared in the manifest, or null if unset.

dotlottie.getInitialAnimation(): string | null

Returns the Lottie JSON source of the initial animation as a string, or null if no initial animation is set.

Example

const { readFileSync, writeFileSync } = require('node:fs')
const { DotLottie, DotLottieBuilder } = require('@lottiefiles/dotlottie-io')

// Build a package from scratch
const builder = new DotLottieBuilder()
builder.generator('my-tool')
builder.addAnimation('hero', Buffer.from(JSON.stringify(myLottieJson)))
builder.addTheme('dark', 'Dark Theme', Buffer.from(JSON.stringify({ rules: [] })))
const dl = builder.build()

// Add assets
const storedName = dl.addImage('logo.png', readFileSync('logo.png'))
console.log(storedName) // 'logo.png' (or 'logo_1.png' if that name was taken)

dl.addAudio('click.mp3', readFileSync('click.mp3'))

// Save to disk
writeFileSync('output.lottie', dl.toBytes())

// Load back and inspect — by path or by bytes
const loaded = DotLottie.fromFile('output.lottie')
// const loaded = DotLottie.fromBytes(readFileSync('output.lottie')) // equivalent
console.log(loaded.animationIds()) // ['hero']
console.log(loaded.imageFilenames()) // ['logo.png']
console.log(loaded.audioFilenames()) // ['click.mp3']

const imgData = loaded.getImage('logo.png') // Buffer

DotLottieReader

A lightweight, read-only view over a .lottie archive. Only the manifest is parsed on construction — all other entries are read on demand when you call a getter. Use this instead of DotLottie when you only need to inspect or extract specific entries without loading the whole archive into memory.

  • open(path) — holds a live file handle via s-zip; each getter seeks directly to the requested entry. The file is never fully read into memory.
  • fromBytes(buffer) — holds the raw buffer; each getter re-reads the ZIP central directory (~microseconds) and decompresses only the one requested entry.

Static constructors

DotLottieReader.open(path: string, password?: string): DotLottieReader

Open a .lottie file from a filesystem path. Only the manifest is read; the file handle stays open for subsequent getter calls. Pass password to open a password-protected archive (file is read into memory in that case).

DotLottieReader.fromBytes(data: Buffer, password?: string): DotLottieReader

Load from a Buffer. Only the manifest is parsed on construction. Pass password to decrypt a password-protected archive.

Manifest

reader.getManifestJson(): string
reader.animationIds(): string[]
reader.themeIds(): string[]
reader.stateMachineIds(): string[]

These are served directly from the eagerly-loaded manifest — no ZIP reads after construction.

On-demand entry getters

Each method reads exactly one ZIP entry and returns null if the entry is not present.

reader.getAnimationJson(id: string): string | null
reader.getThemeJson(id: string): string | null
reader.getStateMachineJson(id: string): string | null
reader.getImage(filename: string): Buffer | null
reader.getFont(filename: string): Buffer | null
reader.getAudio(filename: string): Buffer | null

Both v1 (animations/, images/, audio/) and v2 (a/, i/, u/) path layouts are supported.

Query methods

reader.animationsUsingTheme(themeId: string): string[]

Returns animation IDs whose manifest entry references the given theme. Reads from the manifest only — no ZIP I/O.

reader.animationsUsedByStateMachine(stateMachineId: string): string[]

Returns all unique animation IDs referenced by PlaybackState entries in the given state machine. Reads one ZIP entry; throws on I/O error.

reader.assetReferences(animationId: string): { images: string[], fonts: string[], audio: string[] }

Returns categorised external asset filenames referenced by the animation's Lottie JSON. Reads one ZIP entry; throws on I/O error.

reader.animationsUsingAsset(filename: string): string[]

Reverse lookup: returns animation IDs that reference the given asset filename. Reads every animation ZIP entry (O(n) reads); throws on I/O error. Use intoDotLottie() first if you need to call this repeatedly.

Example

const { readFileSync } = require('node:fs')
const { DotLottieReader } = require('@lottiefiles/dotlottie-io')

// From a file path — file handle stays open, nothing else is read yet
const reader = DotLottieReader.open('package.lottie')
console.log(reader.animationIds()) // from manifest, free
console.log(reader.stateMachineIds()) // from manifest, free

// Only this entry is decompressed and returned
const animJson = reader.getAnimationJson('hero')
if (animJson) {
  console.log(JSON.parse(animJson).nm)
}

// From a buffer — useful when you already have the bytes in memory
const reader2 = DotLottieReader.fromBytes(readFileSync('package.lottie'))
const font = reader2.getFont('MyFont.ttf') // Buffer | null

DotLottieBuilder

A stateful builder for constructing .lottie packages. Configure it with the methods below, then call build() to produce a DotLottie.

Constructor

new DotLottieBuilder()

Configuration

builder.version(v: string): void

Set the manifest version string.

builder.generator(g: string): void

Set the generator field in the manifest (e.g. your tool name and version).

builder.mergeStrategy(strategy: MergeStrategy): void

Collision strategy when source animations share IDs. Defaults to MergeStrategy.Rename. See MergeStrategy for values.

builder.initialAnimation(id: string): void
builder.initialStateMachine(id: string): void

Set which animation or state machine the player loads first.

Adding content

builder.addAnimation(id: string, jsonData: Buffer | string, options?: AnimationOptions): void
builder.addTheme(id: string, name: string | null, jsonData: Buffer | string): void
builder.addStateMachine(id: string, name: string | null, jsonData: Buffer | string): void
builder.addImage(filename: string, data: Buffer): void
builder.addFont(filename: string, data: Buffer): void
builder.addAudio(filename: string, data: Buffer): void

The builder queues all additions and resolves filename collisions at build() time using the same deduplication logic as the direct API (see Filename deduplication).

Building

builder.build(): DotLottie

Consumes the builder configuration and returns a DotLottie instance. Throws if any content is invalid (e.g. a non-MP3 audio file).

Example

const { DotLottieBuilder } = require('@lottiefiles/dotlottie-io')

const builder = new DotLottieBuilder()
builder.generator('my-tool v1.0')
builder.initialAnimation('intro')
builder.addAnimation('intro', Buffer.from(JSON.stringify(introJson)))
builder.addAnimation('hero', Buffer.from(JSON.stringify(heroJson)))
builder.addAudio('click.mp3', clickMp3Buffer)

const dl = builder.build()
console.log(dl.animationIds()) // ['intro', 'hero']
console.log(dl.audioFilenames()) // ['click.mp3']

MergeStrategy

An exported enum used by both DotLottieMerger and DotLottieBuilder.mergeStrategy().

const { MergeStrategy } = require('@lottiefiles/dotlottie-io')

MergeStrategy.Rename // appends _1, _2, … on collision (default)
MergeStrategy.Skip // silently drops the incoming item on collision
MergeStrategy.Fail // throws on any collision

DotLottieMerger

Merges one or more .lottie packages into a base package, with configurable collision handling.

Constructor

new DotLottieMerger(strategy?: MergeStrategy)  // defaults to MergeStrategy.Rename

Collision strategies

| Strategy | Animations / Themes / State Machines | Assets (images, fonts, audio) | | ---------------------- | ---------------------------------------- | -------------------------------- | | MergeStrategy.Rename | Appends _1, _2, … to the incoming ID | Same — renames the incoming file | | MergeStrategy.Skip | Silently drops the incoming item | Silently drops the incoming file | | MergeStrategy.Fail | Throws on any collision | Throws on any collision |

Asset path references inside animation JSON are automatically updated to point to renamed files.

Merging

merger.merge(base: DotLottie, others: DotLottie[]): DotLottie

Merges all packages in others into base and returns the combined result.

Example

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

function build(id) {
  const b = new DotLottieBuilder()
  b.addAnimation(id, Buffer.from(JSON.stringify(lottieJson)))
  return b.build()
}

const merger = new DotLottieMerger(MergeStrategy.Rename)
const result = merger.merge(build('hero'), [build('hero'), build('outro')])
console.log(result.animationIds()) // ['hero', 'hero_1', 'outro']

API Reference — Rust

Add dotlottie-io to your Cargo.toml (it re-exports all the input/option types):

[dependencies]
dotlottie-io = "0.1"

Enable the native-fs feature for streaming file I/O. With it, to_file and from_file use a streaming ZIP implementation that keeps peak RAM usage around 5 MB regardless of archive size, and DotLottieReader::open becomes available.

[dependencies]
dotlottie-io = { version = "0.1", features = ["native-fs"] }

DotLottie

The core struct representing a loaded or built .lottie archive.

Constructors

DotLottie::from_file(path: impl AsRef<Path>, password: Option<&str>) -> Result<Self, DotLottieError>

Load a .lottie archive from disk. Pass Some("password") to open a password-protected archive. Without native-fs, the whole file is read into memory; with native-fs and no password, streaming reads are used.

DotLottie::from_bytes(bytes: &[u8], password: Option<&str>) -> Result<Self, DotLottieError>

Parse a .lottie archive from a byte slice.

Serialization

dotlottie.to_file(path: impl AsRef<Path>, password: Option<&str>) -> Result<(), DotLottieError>

Write the archive to a file. With native-fs enabled and no password, uses streaming compression (low peak RAM). Otherwise uses ZipWriter written directly to a File. Pass Some("password") to produce an AES-256 encrypted archive.

dotlottie.to_bytes(password: Option<&str>) -> Result<Vec<u8>, DotLottieError>

Serialize the archive to a byte buffer. Pass Some("password") to produce an AES-256 encrypted archive.

Animations

dotlottie.add_animation(anim: LottieAnimation, opts: Option<AnimationOptions>) -> Result<(), DotLottieError>
dotlottie.remove_animation(id: &str) -> Result<(), DotLottieError>
dotlottie.get_animation(id: &str) -> Option<&LottieAnimation>
dotlottie.animation_ids() -> Vec<&str>

When a LottieAnimation contains embedded base64 assets, add_animation extracts them into the appropriate ZIP directories and rewrites asset references in the JSON.

Themes

dotlottie.add_theme(id: impl Into<String>, name: Option<String>, theme: Theme) -> Result<(), DotLottieError>
dotlottie.remove_theme(id: &str) -> Result<(), DotLottieError>
dotlottie.get_theme(id: &str) -> Option<&Theme>
dotlottie.theme_ids() -> Vec<&str>

State machines

dotlottie.add_state_machine(id: impl Into<String>, name: Option<String>, sm: StateMachineDefinition) -> Result<(), DotLottieError>
dotlottie.remove_state_machine(id: &str) -> Result<(), DotLottieError>
dotlottie.get_state_machine(id: &str) -> Option<&StateMachineDefinition>
dotlottie.state_machine_ids() -> Vec<&str>

Assets

All add_* methods return the actual filename stored, which may differ from the requested name if a collision was resolved by appending a numeric suffix (e.g. logo_1.png).

dotlottie.add_image(filename: impl Into<String>, data: Vec<u8>) -> Result<String, DotLottieError>
dotlottie.get_image(filename: &str) -> Option<&[u8]>
dotlottie.image_filenames() -> Vec<&str>

dotlottie.add_font(filename: impl Into<String>, data: Vec<u8>) -> Result<String, DotLottieError>
dotlottie.get_font(filename: &str) -> Option<&[u8]>
dotlottie.font_filenames() -> Vec<&str>

dotlottie.add_audio(filename: impl Into<String>, data: Vec<u8>) -> Result<String, DotLottieError>
dotlottie.get_audio(filename: &str) -> Option<&[u8]>
dotlottie.audio_filenames() -> Vec<&str>

Only .mp3 is supported for audio. add_audio returns Err(InvalidAudioFormat) for any other extension.

Query methods

dotlottie.animations_using_theme(theme_id: &str) -> Vec<String>
dotlottie.animations_used_by_state_machine(state_machine_id: &str) -> Vec<String>
dotlottie.asset_references(animation_id: &str) -> AssetReferences  // { images, fonts, audio }
dotlottie.animations_using_asset(filename: &str) -> Vec<String>

Manifest

dotlottie.manifest() -> &Manifest
dotlottie.set_initial(animation_id: Option<String>, state_machine_id: Option<String>) -> Result<(), DotLottieError>
dotlottie.initial_animation_id() -> Option<String>
dotlottie.initial_animation_json() -> Option<String>

Example

use dotlottie_io::{DotLottie, DotLottieBuilder};
use dotlottie_io::AnimationSource;
use std::path::PathBuf;

// Load an existing archive
let dl = DotLottie::from_file("input.lottie", None)?;
println!("{:?}", dl.animation_ids());

// Build a new archive from a Lottie JSON file
let dl = DotLottieBuilder::new()
    .generator("my-tool")
    .add_animation(
        AnimationSource::JsonFile { id: "hero".into(), path: PathBuf::from("hero.json") },
        None,
    )
    .build()?;

// Write to disk — to_file is always available, streaming when native-fs is enabled
dl.to_file("output.lottie", None)?;

// Round-trip with password protection
dl.to_file("protected.lottie", Some("s3cr3t"))?;
let loaded = DotLottie::from_file("protected.lottie", Some("s3cr3t"))?;

DotLottieReader

A lightweight lazy view over a .lottie archive. Only manifest.json is parsed on construction; all other entries are read on demand.

// Requires the `native-fs` feature — file handle stays open, getters seek directly to each entry
DotLottieReader::open(path: impl AsRef<Path>, password: Option<&str>) -> Result<Self, DotLottieError>

// Always available — holds the buffer; getters re-parse the central directory on each call
DotLottieReader::from_bytes(bytes: Vec<u8>, password: Option<&str>) -> Result<Self, DotLottieError>

Manifest (free — no ZIP I/O after construction)

reader.manifest  // pub field: &Manifest
reader.initial_animation_id() -> Option<String>
reader.animations_using_theme(theme_id: &str) -> Vec<String>

On-demand entry getters

Each method reads exactly one ZIP entry and returns Ok(None) if the entry is not present.

reader.animation(id: &str) -> Result<Option<LottieAnimation>, DotLottieError>
reader.theme(id: &str) -> Result<Option<Theme>, DotLottieError>
reader.state_machine(id: &str) -> Result<Option<StateMachineDefinition>, DotLottieError>
reader.image(filename: &str) -> Result<Option<Vec<u8>>, DotLottieError>
reader.font(filename: &str) -> Result<Option<Vec<u8>>, DotLottieError>
reader.audio(filename: &str) -> Result<Option<Vec<u8>>, DotLottieError>
reader.initial_animation_json() -> Result<Option<String>, DotLottieError>

Query methods

reader.animations_used_by_state_machine(state_machine_id: &str) -> Result<Vec<String>, DotLottieError>
reader.asset_references(animation_id: &str) -> Result<AssetReferences, DotLottieError>
reader.animations_using_asset(filename: &str) -> Result<Vec<String>, DotLottieError>  // O(n) ZIP reads

Promotion

reader.into_dotlottie() -> Result<DotLottie, DotLottieError>

Eagerly loads the full archive into a DotLottie when mutation or full access is needed.


DotLottieBuilder

A builder for constructing .lottie archives from various sources.

DotLottieBuilder::new() -> Self

Configuration

builder.version(v: impl Into<String>) -> Self
builder.generator(g: impl Into<String>) -> Self
builder.initial_animation(id: impl Into<String>) -> Self
builder.initial_state_machine(id: impl Into<String>) -> Self
builder.merge_strategy(strategy: MergeStrategy) -> Self

Adding content

builder.add_animation(src: AnimationSource, opts: Option<AnimationOptions>) -> Self
builder.add_theme(id: impl Into<String>, name: Option<String>, src: ThemeSource) -> Self
builder.add_state_machine(id: impl Into<String>, name: Option<String>, src: StateMachineSource) -> Self
builder.add_image(src: ImageSource) -> Self
builder.add_font(src: FontSource) -> Self
builder.add_audio(src: AudioSource) -> Self

AnimationSource variants: JsonBytes { id, data }, JsonFile { id, path }, LottieFile { path }. The LottieFile variant merges an entire .lottie archive using the configured MergeStrategy.

Building

builder.build() -> Result<DotLottie, DotLottieError>

DotLottieMerger

Merges one or more .lottie archives into a base archive with configurable collision handling. See MergeStrategy for values.

DotLottieMerger::new(strategy: MergeStrategy) -> Self
merger.merge(base: DotLottie, others: impl IntoIterator<Item = DotLottie>) -> Result<DotLottie, DotLottieError>

MergeStrategy

use dotlottie_io::MergeStrategy;

MergeStrategy::RenameOnCollision  // appends _1, _2, … (default)
MergeStrategy::SkipOnCollision    // silently drops the incoming item
MergeStrategy::FailOnCollision    // returns Err on any collision

API Reference — Web (WASM)

The API surface is identical to Node.js — the same classes (DotLottie, DotLottieBuilder, DotLottieMerger, DotLottieReader) with the same methods and signatures. The WASM module must be initialized once before the classes are usable.

DotLottieReader is available in the browser via DotLottieReader.fromBytes(uint8Array). The open(path) method is not available in WASM as there is no filesystem.

ESM (bundler — Vite, webpack, Rollup)

import { init } from '@lottiefiles/dotlottie-io/web'

const { DotLottie, DotLottieBuilder, DotLottieMerger } = await init()

The bundler automatically copies dotlottie-io.wasm to your output directory and resolves the URL via import.meta.url — no extra configuration needed.

IIFE (vanilla <script> tag)

<script src="node_modules/dotlottie-io/release/browser/dotlottie-io.iife.js"></script>
<script>
  ;(async () => {
    const { DotLottie, DotLottieBuilder, DotLottieMerger } = await DotLottieIO.init()
    // classes are ready
  })()
</script>

dotlottie-io.wasm must be served from the same directory as the IIFE script. Pass an explicit URL to override:

const { DotLottie } = await DotLottieIO.init('/assets/dotlottie-io.wasm')

Memory management

The wasm-bindgen runtime manages WASM memory automatically. Pass Uint8Array values directly — no manual allocation needed:

const { DotLottie } = await init()

// Load from a FileReader result
const dotlottie = DotLottie.fromBytes(new Uint8Array(fileReaderResult))

// Add an animation from a fetched buffer
const json = await fetch('/animations/hero.json').then((r) => r.arrayBuffer())
dotlottie.addAnimation('hero', new Uint8Array(json))

Web example

See example/index.html for a complete interactive .lottie editor running in the browser. It supports:

  • Drag-and-drop loading of .lottie packages
  • Adding animations (.json), themes, state machines, images, and audio (.mp3)
  • An Assets tab showing image thumbnails, live font previews, and audio players for all embedded assets
  • Export to .lottie

To run it, start a local HTTP server from the repo root:

npx serve .
# then open http://localhost:3000/example/

Password-protected archives

All I/O methods accept an optional password parameter. When provided, all ZIP entries (including manifest.json) are encrypted with AES-256.

Node.js

const { DotLottie, DotLottieReader } = require('@lottiefiles/dotlottie-io')
const { writeFileSync, readFileSync } = require('fs')

// Write an encrypted archive
const dl = DotLottie.fromFile('source.lottie')
const encrypted = dl.toBytes('my-secret-password')
writeFileSync('protected.lottie', encrypted)

// Read an encrypted archive
const loaded = DotLottie.fromBytes(readFileSync('protected.lottie'), 'my-secret-password')
console.log(loaded.animationIds())

// Lazy inspection via DotLottieReader
const reader = DotLottieReader.open('protected.lottie', 'my-secret-password')
console.log(reader.animationIds())

Rust

use dotlottie_io::{DotLottie, DotLottieReader};

// Write an encrypted archive — to_file and to_bytes both accept a password
let dl = DotLottie::from_file("source.lottie", None)?;
dl.to_file("protected.lottie", Some("my-secret-password"))?;
// or: let bytes = dl.to_bytes(Some("my-secret-password"))?;

// Read an encrypted archive
let loaded = DotLottie::from_file("protected.lottie", Some("my-secret-password"))?;
println!("{:?}", loaded.animation_ids());

// Lazy inspection via DotLottieReader (requires `native-fs` feature for open)
let reader = DotLottieReader::open("protected.lottie", Some("my-secret-password"))?;
println!("{:?}", reader.manifest.animations);

// Or from bytes (always available)
let bytes = std::fs::read("protected.lottie")?;
let reader = DotLottieReader::from_bytes(bytes, Some("my-secret-password"))?;

Errors

  • "password required to open this archive" — the archive is encrypted but no password was provided.
  • "wrong password or corrupted archive" — the password is incorrect or the archive is corrupt.

License

MIT