@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-ioThe 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-ioTwo 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 — provideswasm-opt)
git clone https://github.com/lottiefiles/dotlottie-io.git
cd dotlottie-io
yarn installBuild 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:wasmyarn build:wasm runs three steps internally:
- Compiles the Rust crate to
wasm32-unknown-unknownviawasm-pack(requireswasm-pack— install withcargo install wasm-pack) - 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) - 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 oxlintReleasing
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 summaryThis 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=main2. 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:
- Builds every target — the
buildmatrix cross-compiles all 9 native.nodebinaries (macOS, Linux glibc + musl, Windows), andbuild-wasmbuilds the browser/WASM bundle. - Assembles the packages —
napi create-npm-dirsscaffolds the per-platform packages,yarn artifactsdrops each.nodeinto its package, and the WASM bundle is restored intorelease/browser/. - Publishes —
changeset publishpublishes 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): DotLottieLoad a .lottie file directly from a filesystem path. Pass password to open a password-protected archive.
DotLottie.fromBytes(data: Buffer, password?: string): DotLottieLoad 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): BufferSerialize 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(): stringReturns the full manifest as a JSON string.
dotlottie.setInitial(animationId?: string | null, stateMachineId?: string | null): voidSet which animation or state machine the player loads first. Pass null to clear.
dotlottie.getInitialAnimationId(): string | nullReturns the ID of the initial animation declared in the manifest, or null if unset.
dotlottie.getInitialAnimation(): string | nullReturns 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') // BufferDotLottieReader
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): DotLottieReaderOpen 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): DotLottieReaderLoad 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 | nullBoth 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 | nullDotLottieBuilder
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): voidSet the manifest version string.
builder.generator(g: string): voidSet the generator field in the manifest (e.g. your tool name and version).
builder.mergeStrategy(strategy: MergeStrategy): voidCollision strategy when source animations share IDs. Defaults to MergeStrategy.Rename. See MergeStrategy for values.
builder.initialAnimation(id: string): void
builder.initialStateMachine(id: string): voidSet 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): voidThe 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(): DotLottieConsumes 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 collisionDotLottieMerger
Merges one or more .lottie packages into a base package, with configurable collision handling.
Constructor
new DotLottieMerger(strategy?: MergeStrategy) // defaults to MergeStrategy.RenameCollision 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[]): DotLottieMerges 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 readsPromotion
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() -> SelfConfiguration
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) -> SelfAdding 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) -> SelfAnimationSource 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 collisionAPI 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
.lottiepackages - 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
