---
title: "Templates and styles"
description: "Make an animation from repository data, then change its words, format, theme or film style."
canonical: "https://terminal.lottiefiles.com/docs/templates-and-styles/"
last_updated: 2026-10-28
---

# Templates and styles

Make an animation from repository data, then change its words, format, theme or film style.

Use [Make a repository animation](https://terminal.lottiefiles.com/docs/how-to/make-a-repository-animation.md) for a first run.

## Templates

Animations made from a repo's data, for the people who make software to post: a star
milestone, packages racing on their downloads, a package's growth, a release's news, a
thank-you for each contributor, a repo's promo and a banner for its README. **Templates**
(`⌥G`, or File › Templates) opens the gallery: every template, then a changelog and a teaser film (see
[Styles](https://terminal.lottiefiles.com/docs/templates-and-styles/#styles)), playing side by side, full screen. Paste a repo's link in the field along the top (`github.com/owner/repo`,
`owner/repo`, or packages: `npm:react,vue` · `pypi:requests,httpx` · `crates:serde,tokio`),
press enter, and every tile is made again from what GitHub and the registry say. Until then
they show made-up data (a repo called nova/orbit). The chips at the top make every template 9:16,
1:1, 4:5 or 16:9, set its theme, and pick the films' style (on a narrow screen the sizes come
first, then the styles and themes as there's room); a click on a tile (or ← → and enter, `⌃N` `⌃P` too, with
nothing typed) opens that template or film as a document of your own, in ~/Documents, named for the
repo and the template or film (`vhs-milestone.json`; `w` saves it). Esc (or `⌥G` again) goes back to the document that was
open, as it was (with something typed: the first esc leaves the field). `⌃O`, `⌃L` and `⌘P` go
on from it to the agents, LottieFiles and the palette.

![The gallery made from axios/axios and npm:axios,got,ky,node-fetch on Midnight, every template wearing materials: the star milestone at 100,000 under a chrome gold star and soft beams, the download race in September with node-fetch's bar ringed in light, axios's growth chart filled with flowing colour under its line, v0.34.0's news with its version in flowing colour over glass cards, its top contributor's picture ringed in light, the spotlight with its install typed in a terminal ringed in light, and the README banner, side by side; the packages in the field at the top, what they're made from under it, the sizes and themes at the right](https://terminal.lottiefiles.com/docs/assets/templates.png)

| Template | What it says | From |
| --- | --- | --- |
| Star milestone | the milestone the stars passed, rolling up as an odometer does, a star landing with a burst, the repo on a chip, a thank-you | a repo |
| Download race | packages' downloads month by month (crates.io's week by week), the bars re-ranking as they pass, the leader crowned, the fastest grower's growth | packages |
| Growth chart | a package's downloads drawn on as a line, the number counting with its head, its growth since the first month | packages (a repo's own, when it's installed from npm, PyPI or crates.io) |
| Release | the latest release's version, its news card by card (its notes' bullets, cleaned), how to install it typed on | a repo |
| Contributor thanks | a contributor's picture in a ring drawing on, their commits counted, their rank; once per contributor | a repo |
| Repo spotlight | the repo's name, what it does, its stars, forks, language and licence, its install typed in a terminal | a repo |
| README banner | the repo's name and what it does, a seamless loop, for a README as an animated SVG | a repo |

A template is code that writes a Lottie: it lays itself out for the size it's made at (a
story's buttons kept clear), says what the data says, and its words fit. What it writes is an
ordinary document: every layer edits, keys and eases as any other, its colours are the file's
tokens (`bg`, `surface`, `ink`, `sub`, `faint`, `accent`, `accent2`) and its five themes
(Midnight, Paper, Neon, Terminal, Sunset) are dotLottie themes, so an app can switch them as it
plays. Its type is Inter Display and JetBrains Mono, built in, so it draws the same on any
computer.

Each is lit with [materials](https://terminal.lottiefiles.com/docs/layers.md#materials): a moving backdrop under it, chrome on the
milestone's number and the race's bars, light along the growth chart, light on the release's
cards and the spotlight's terminal. The looks belong to the shapes and text they light.
Video draws them; players draw the content in its own colours.

**The rail's TEMPLATE section** shows while a template's document is open and nothing is
selected: what it's made from, in a field (type another link, enter: made again from that
repo; `↻` asks again for today's numbers), its words (each field what the data says until you
type your own; `↺` puts the data's back), its theme, its accent (its own, the repo's language's
colour, a few more, or typed), its size and its length. Each change makes the whole document
again as one undo step. Made again after edits of your own by hand, the first click says
they'd go and a second does it (`u` brings them back). For the contributor thanks, ◂ ▸ steps
through the contributors and **⇣ all** exports one file for each, into a folder beside the
document, as the export panel's last format. For the banner, **⇣ SVG + its line** writes the
animated SVG beside the document and puts the README's line for it on the clipboard, linking
to the repo (`[![vhs](vhs-banner.svg)](https://github.com/charmbracelet/vhs)`).

| TEMPLATE row | Control |
|---|---|
| **From** | Type a repository or package source; `enter` remakes it, **↻** fetches again |
| Words | Click and type, `enter` keeps, **↺** restores the data’s wording |
| **Theme** | **Midnight**, **Paper**, **Neon**, **Terminal**, **Sunset** |
| **Accent** | Sample colours, the repository language’s colour, or a typed hex colour |
| **Size** | **9:16**, **1:1**, **4:5**, **16:9** |
| **Length** | **−** and **+** shorten or lengthen the animation |
| **For** | Contributor arrows and **⇣ all**, on **Contributor thanks** |
| **README** | **⇣ SVG + its line**, on **README banner** |

| Template | Editable words |
|---|---|
| **Star milestone** | **Number**, **Label**, **Message** |
| **Download race** | **Title**, **Subtitle** |
| **Growth chart** | **Package**, **Headline**, **Badge** |
| **Release** | **Version**, **Label**, **Title**, **Note 1**, **Note 2**, **Note 3**, **Install** |
| **Contributor thanks** | **Headline**, **Message** |
| **Repo spotlight** | **Title**, **Tagline**, **Install** |
| **README banner** | **Title**, **Tagline** |

![The sample Star milestone's TEMPLATE rail shows From, words, Theme, Accent, Size and Length.](https://terminal.lottiefiles.com/docs/assets/shots/start-template.png)

![The download race open as a document, 16:9, at its end: node-fetch crowned with its growth (+163%) over axios, got and ky; the rail's TEMPLATE section with the packages it's made from, its title and subtitle, its theme, accent (JavaScript's yellow, axios's language), size and length; its tokens and themes under it; its layers on the score](https://terminal.lottiefiles.com/docs/assets/template-rail.png)

Where the data comes from: GitHub's API (the repo, its top 30 contributors without bots, its
latest release, the pictures), npm's (downloads a day, a year of them), pypistats' (six months)
and crates.io's (twelve weeks). Days a registry has no count for are left out and their month
counted from the days it has, so a gap doesn't read as a drop. GitHub answers a computer that
isn't signed in 60 times an hour, and a repo takes about four; signed in (`gh auth login`, or a
`GITHUB_TOKEN`), 5,000. How a repo is installed comes from its files: a JavaScript repo's
package.json (`npm i …`), a Python one's pyproject (`pip install …`), else a Homebrew formula made
from it (`brew install …`), else its Cargo.toml or Go module, else a clone. Pictures are kept in
`~/.config/motion/templates/pictures`; a document keeps where its facts came from
(`motion:template`, left out of exports), so it can be made again.

## Styles

Films in a style: a look and a way of moving measured from real films, made again with your
words and different on every take. Not templates: a style says how things look and move and
which parts a film is built of (a tile growing from a corner and handing off to the next, a
caption masking in, a stack of cards spreading into a row, hairline polygons drawing on, an
iris…), and a film puts those parts in an order with its own words and times. The gallery has two films after its templates, made from
the same repo: a changelog of its releases (in a repo of several packages, the package released
last) and a teaser of its latest version. The **films** chips along its top pick the style
they're made in: Paper, Line art or one of your own. A film is made in that style where the
style makes it, else in the first style that does, and its name under it says which (Teaser ·
Line art). A click opens one as a document of your own, in ~/Documents (`w` saves it). The
star milestone is the template's; the copilot's `film` tool still makes Paper's.


| Style | How it looks and moves | Its films |
| --- | --- | --- |
| Paper | black hairlines on near-white paper; tiles grow out of a corner and land with a hard snap while the last shrinks away, captions mask in, cards fan out and line up; living line icons in the tiles keep moving | Changelog, Milestone (the copilot's) |
| Line art | a soft grey vignette; a few small words at a time while hairline polygons draw themselves around them, dots drift, lines burst from a point, an iris turns the film dark; the camera drifts | Teaser, Changelog |

| Film | What it tells |
| --- | --- |
| Changelog | two to five releases, a tile each handing off to the next, its version, name and a line or two in the column beside it, then every release's card stacked, spread and lined up under the end title |
| Milestone | a number's story: an opening line, the number, a second number, each beside a tile or a stack of cards, then its title |
| Teaser | a title a word at a time inside a polygon drawing on, a line under it, an iris, then what comes and when, over a burst of lines |

**The rail's STYLE section** shows while a film is open and nothing is selected: its style (the
same film in another), another take (◂ ▸, where a seed lays out its dots and lines), its words
(each one typed over; too long for its place and it's set smaller, the words in red) and its
icons (◂ ▸), and what its checks found. Each change makes the film again as one undo step, as
templates do. **✦ write its words** opens the copilot with the ask in its composer, not yet sent:
add what your product is, who it's for and what's new, and send it. The copilot asks what else
it needs (it doesn't make facts up), then writes the words and makes the film again (a
changelog: from what you said and its repo's releases, in their own terms).

![A changelog open as a document: the tile handing off as v0.41 names dotLottie audio; the rail's STYLE section with its style, product, package, month, summary, each release's name, lines and icon, its checks, and its MOTION.md](https://terminal.lottiefiles.com/docs/assets/style-rail.png)

A film's checks hold it to its style, measured on its own keys: the median move's length, how
many things move at once, how many of its eased moves use the style's eases, and how much of
what sits in its tiles and cards keeps moving after it arrives. A film keeps what it was made
from (`motion:style`, left out of exports), so it can be made again.

### A style of your own: MOTION.md

A style is a MOTION.md file: YAML front matter
that is the motion system (durations, easings, the roles motion plays: `enter`, `exit`, `move`,
`grow`, `draw`), a `film` block for what a film looks like (its palette, type, the parts it may
use and their limits, its checks, its films), then its rules in sections an agent reads.


**make it yours** in the
STYLE section copies the film's style to `~/.config/motion/styles/<name>-mine/MOTION.md`, makes
the film in it, and watches the file: change an easing or a colour, save, and the film is made
again as you look. A style of your own can also start with `extends: paper` (or `lineart`, the
folder name of another of yours, or a path to a MOTION.md inside your styles folder, such as
`../base/MOTION.md`) and say only what's different:

```yaml
---
version: "1.0"
name: Night
extends: lineart
easings:
  quick: cubic-bezier(0.2, 0, 0, 1)
roles:
  enter: { use: "words arriving", duration: 300ms, easing: "{easings.quick}" }
film:
  palette: { paper: "#101418", ink: "#e8eef2" }
---

## Overview
The same quiet lines, at night.
```

The eases a film's parts use are its roles' easings (`enter` for arrivals, `exit`, `move` between
rests, `grow` for tiles and stacks, `draw` for lines), else the easings motion.md names
(`decelerate`, `standard`, `accelerate`…), else measured ones. As motion.md has it, opacity
never overshoots: where a role's easing does, a fade takes its `effects-easing`. A style that
can't be read says why in the gallery and the rail, and a film made in it stays as it was.

The copilot's `film` tool makes a film on the open document: a format with your words, or parts
as JSON (`{"style": "paper", "seed": 1, "parts": [{"part": "caption", "id": "c", "lines":
["Hello"], "at": [170, 520], "t": 0}, {"exit": "c", "t": 2}]}`), in drawing order. Each part's
parameters are checked against it and the style's limits, and an exit makes a part leave the
style's way.
