relottie is a tool that transforms Lotties with plugins. These plugins can inspect and change.
relottie is a ecosystem of plugins that work with the Lottie file format as structured data, specifically ASTs (abstract syntax trees). ASTs make it easy for programs to deal with Lottie files. We call those programs plugins. Plugins inspect and change trees. You can use the existing plugins or you can make your own.
- to learn Lottie, see this lottie-docs and what-is-lottie
- for more about us, see lottiefiles
- for help, see contribute
- for more about unified, see unifiedjs.com
- What is this?
- When should I use this?
- Plugins
- Examples
- Syntax
- Syntax tree
- Types
- Compatibility
- Security
- Setting up monorepo
- Contribute
- Community & Support
- Acknowledgments
- License
You can use plugins to change Lottie.
In:
{ "v": "5.5.2" }Plugin:
import {visit} from 'unist-util-visit'
import type { Plugin, Node } from 'unified'
import type { Root } from '@lottiefiles/last'
const myRelottiePlugin: Plugin<[]> () {
function transform (tree: Root, _file: VFile): void {
visit(tree, (node) => {
if (node.title === 'version') {
node.title = "6.0.0"
}
})
}
return transform
}Out:
{ "v": "6.0.0" }You can use relottie for many different things. unified is the core project that transforms content with ASTs. relottie adds support for Lottie to unified. last is the Lottie AST that relottie uses.
This GitHub repository is a monorepo that contains the following packages:
last— Type definitions for Lottie Abstract Syntax Tree (last)last-builder— Composable functions to easily build syntax tree (last) structuresrelottie— a unified processor with support for parsing Lottie input and serializing Lottie as outputrelottie-parse— plugin to take Lottie as input and turn it into a syntax tree (NodeValue) with support for fragment parsing viaphantomRootrelottie-stringify— plugin to take a syntax tree (last) and turn it into Lottie as outputrelottie-cli— Command line interface to inspect and change Lottie files with relottierelottie-extract-features— plugin to extract Lottie features from the document and store them in vfilerelottie-metadata— plugin to extract Lottie metadata from the document and store them invfile.data
relottie focusses on ASTs and providing an interface for plugins to transform them.
Depending on the input you have and output you want, you can use different parts
of relottie.
If the input is Lottie JSON file, you can use relottie-parse with unified.
If the output is Lottie JSON file, you can use relottie-stringify with unified. If you need to transform LottieJSON to .lottie, you can dotlottie.js
relottie plugins deal with Lottie. Some popular examples are:
These plugins are exemplary because what they do and how they do it is quite different, respectively to extend Lottie syntax, inspect trees, change trees, and define other output formats.
You can choose from the plugins that already exist. Here are three good ways to find plugins:
- List of LF plugins — list of all plugins
relottie-plugintopic — any tagged repo on GitHub
Some plugins are maintained by us here in the @lottiefiles organization while
others are maintained by folks elsewhere.
Anyone can make relottie plugins, so as always when choosing whether to include
dependencies in your project, make sure to carefully assess the quality of
relottie plugins too.
- be the first one ;)
relottie follows last definitions, lottie-types and lottie-docs title names (with a few changes) Some syntax extensions are supported through plugins.
We use momoa JSON parser for our parsing. See its documentation for more information.
The syntax tree format used in relottie is last. It represents Lottie constructs as JSON objects.
In:
{ "v": "6.0.0" }Out:
{
"type": "root",
"title": "animation",
"hasExpressions": false,
"position": {
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 17,
"offset": 16
}
},
"children": [
{
"type": "attribute",
"key": {
"type": "key",
"position": {
"start": {
"line": 1,
"column": 3,
"offset": 2
},
"end": {
"line": 1,
"column": 6,
"offset": 5
}
},
"value": "v"
},
"title": "version",
"position": {
"start": {
"line": 1,
"column": 3,
"offset": 2
},
"end": {
"line": 1,
"column": 15,
"offset": 14
}
},
"children": [
{
"type": "primitive",
"value": "6.0.0",
"position": {
"start": {
"line": 1,
"column": 8,
"offset": 7
},
"end": {
"line": 1,
"column": 15,
"offset": 14
}
},
"valueType": "string"
}
]
}
]
}The relottie organization and the unified as a whole is fully typed with TypeScript. Types for last are available in last. Also have a look at lottie-types.
For TypeScript to work, it is particularly important to type your plugins
correctly.
We strongly recommend using the Plugin type from unified with its generics
and to use the node types for the syntax trees provided by last.
import type { Root } from '@lottiefiles/last';
import type { Plugin } from 'unified';
export function myRelottiePluginAcceptingOptions(options): Plugin<[Options?], Root> {
// `options` is `Options?`.
return function (tree, file) {
// `tree` is `Root`.
}
}As of now, that is Node.js 16.0+, and 18.0+ (other versions have not been tested yet) Our projects sometimes work with older versions, but this is not guaranteed.
As last properties can have expressions, and improper use of last can open you up to cross-site scripting cross-site scripting (XSS). Carefully assess each plugin and the risks involved in using them.
This repository runs a layered set of automated security checks on every push, PR, and a weekly schedule. The full disclosure policy and a self-detection runbook live in SECURITY.md.
CI workflows:
| Workflow file | What it does |
|---|---|
.github/workflows/release.yml |
Validate job runs pnpm audit --prod --audit-level=high, generates a CycloneDX SBOM artifact, and verifies sigstore provenance attestations on every published package after release |
.github/workflows/security.yml |
Three jobs run independently: gitleaks scans the full git history for committed secrets, OSV-Scanner cross-references pnpm-lock.yaml against the OSV vulnerability database, and ioc-scan searches the installed tree for the specific indicators of compromise published for the mini Shai-Hulud npm worm family |
.github/workflows/codeql.yml |
Runs GitHub's security-and-quality query pack against JavaScript/TypeScript |
Every CI job is wrapped by StepSecurity Harden-Runner in audit mode so any unexpected outbound network call from the runner is surfaced. Every actions/checkout sets persist-credentials: false so GITHUB_TOKEN never lands in .git/config. All GitHub Action references are pinned to 40-character commit SHAs.
Repo-side policies live alongside the workflows:
.npmrc—ignore-scripts=trueblocks dependency lifecycle scripts duringpnpm install. This is whypnpm preparehas to be run manually after the first install (the side note below in Setting up Monorepo).pnpm.onlyBuiltDependencies: [](in rootpackage.json) — explicit empty allowlist for packages permitted to run install scripts.socket.yml— declares which Socket.dev alert classes block a PR (error) vs warn vs are ignored. Takes effect once the Socket Security GitHub App is installed.osv-scanner.toml— documents the three advisories with no upstream fix yet, each with anignoreUntildate so the scanner re-flags them on a schedule..github/CODEOWNERS— supply-chain-sensitive paths (package.json, lockfile,.github/,.npmrc,.husky/) require review from the @LottieFiles/rnd team..github/dependabot.yml— weekly grouped updates for thenpmandgithub-actionsecosystems so the pinned action SHAs stay current.
git clone https://github.com/LottieFiles/relottie.git
cd relottie
pnpm install
Git hooks are not installed automatically (the repo sets ignore-scripts=true in
.npmrc as a supply-chain defense). After the initial install, run:
pnpm prepare
pnpm dev
pnpm test
We use changeset
pnpm changelog
pnpm build
pnpm lint
Any contributions are welcome.
- Github issues. For bugs and errors you encounter using this player.
- Discord. For hanging out with the community and sharing your awesome Lottie animations!
The initial release of this project was authored by @aidosmf