Reference
Status: Draft · Version:
motion/0.3· what each version added: §10
What a motion is on disk: the files, their fields and the rules any tool can rely on. This document only grows: a later version adds to it and never changes the meaning of what is here.
1. What a motion is
A motion is a reusable look for narrated and explanatory video: how a film looks (ground, colour, type) and how it moves (how things arrive, change and leave). It is written so that a person or an agent can make a new film in it with any engine.
A motion holds no film. It has no story, script, scene list, timings or end card. A sample made in it is one example among many.
2. Files
A motion is a directory named after its slug. A copy taken into a project may sit in a directory of another name (motion/); its slug still names it:
<slug>/
motion.json identity, authorship and licence required
MOTION.md how it looks and moves, for agents required
tokens.json colours and faces, in the DTCG format required
poster.jpg one representative frame required
CREDITS.md fonts, assets and sources required
MOTION.<lang>.md a translation of MOTION.md optional
<tool>/ files one tool needs (§7) optional
No other file may sit at the top of a motion. Names are exact and case-sensitive.
Where many motions are kept together, a scoped motion's directory sits in a directory named after its scope with an @ before it: @ana/ledger-pencil/ (§3, Identity).
3. motion.json
A JSON object with these members and no others, except extension members (§7).
| Member | Required | Value |
|---|---|---|
spec |
yes | "motion/0.3"; or "motion/0.2" for a motion without basedOn, or "motion/0.1" for one without scope and basedOn |
scope |
no | The GitHub username, in lowercase, of the person or organization that publishes the motion (since 0.2) |
slug |
yes | 3 to 40 characters of a-z, 0-9 and single hyphens, starting and ending with a letter or digit; the name of the directory it is published in (§2) |
version |
yes | A Semantic Versioning 2.0 version of this motion, for example "1.0.0" |
name |
yes | A localized string (§8) of at most 60 characters per language |
line |
yes | A localized string (§8) of at most 160 characters per language: one sentence saying what it looks like and what it is for |
authors |
yes | A non-empty array of { "name": string, "github": string }; github is a GitHub username |
license |
yes | { "text": SPDX, "code": SPDX }: text covers the documents, tokens and pictures; code covers any code under a tool directory and is required when there is any |
lang |
no | The BCP 47 tag of the language MOTION.md is written in; "en" when absent |
tags |
no | Up to 10 keywords, each of a-z, 0-9 and single hyphens, in English |
basedOn |
no | The motions this one builds on: an array of 1 to 10 { "id": string, "version": string }, each a motion's id (Identity) and, optionally, the version built on; no id twice, and never the motion's own (since 0.3) |
Identity
A motion's id is @<scope>/<slug> when it has a scope, and <slug> when it does not: @ana/ledger-pencil, red-pencil. Two motions under different scopes may have the same slug. Only the owner of a GitHub account publishes under its scope; what an unscoped id means is for the collection that holds it to say (motionhub accepts none: every motion there has a scope). Tools name, fetch and credit a motion by its id.
Building on another motion
A motion made from another names it in basedOn, by its id and the version it started from: "basedOn": [{ "id": "red-pencil", "version": "1.0.2" }]. This is the credit tools show and follow; CREDITS.md still says what was taken and what changed, as its licence asks. A tool does not require a motion named in basedOn to be at hand.
An SPDX value is an SPDX license expression, for example "CC-BY-4.0" or "MIT".
{
"spec": "motion/0.3",
"scope": "ana",
"slug": "lab-notebook",
"version": "1.0.0",
"name": { "en": "Lab Notebook", "zh-CN": "实验手记" },
"line": { "en": "A squared notebook page where the diagram is drawn stroke by stroke as it is explained." },
"authors": [{ "name": "Ana", "github": "ana" }],
"license": { "text": "CC-BY-4.0", "code": "MIT" },
"tags": ["hand-drawn", "line-art", "light"]
}
4. tokens.json
The motion's values in the Design Tokens Format Module of the W3C Design Tokens Community Group (DTCG), version 2025.10. Any tool that reads DTCG reads it.
- It has a
colorgroup and afontgroup, each with at least one token. colortokens are of typecolor;fonttokens are of typefontFamily. A group may set$typeonce for its members.- A token name contains no
$,{,}or., and is written in English (it is an identifier). - Every colour and face the motion relies on is a token. A token's
$descriptionsays what it is for, in any language. - Other groups are allowed and are read as plain DTCG. For timing, use
durationtokens andcubicBeziertokens; seconds, not frames. - Values are literal or DTCG aliases (
"{color.ink}"). No value refers to a file or a URL.
{
"color": {
"$type": "color",
"ground": { "$value": { "colorSpace": "srgb", "components": [0.98, 0.98, 0.96], "hex": "#FBFAF5" }, "$description": "the page" },
"ink": { "$value": { "colorSpace": "srgb", "components": [0.11, 0.16, 0.28], "hex": "#1B2A47" }, "$description": "every line and word" },
"accent": { "$value": { "colorSpace": "srgb", "components": [0.81, 0.31, 0.2], "hex": "#CF4F33" }, "$description": "the one result, never decoration" }
},
"font": {
"$type": "fontFamily",
"display": { "$value": ["Shantell Sans", "LXGW WenKai", "cursive"] },
"sans": { "$value": ["Atkinson Hyperlegible Next", "Noto Sans SC", "sans-serif"] }
},
"duration": { "$type": "duration", "enter": { "$value": { "value": 0.6, "unit": "s" } } },
"easing": { "$type": "cubicBezier", "arrive": { "$value": [0.22, 1, 0.36, 1] } }
}
5. MOTION.md
Markdown, at most 16 KB, in the language lang names. It is what an agent follows to make a film in this motion, so it describes the look and the motion, never a particular film.
It has a level-two heading for each of these five topics. The heading starts with the English word, which tools match without regard to case; any words may follow it (## Motion 动法).
| Heading | Says |
|---|---|
Essence |
The few traits that make a frame read as this motion at a glance, and what it is easily confused with |
Colour (or Color) |
What each colour token is for, and what is never coloured |
Type |
The faces and their roles, sizes, and how words sit in the frame |
Motion |
How things arrive, change and leave; the easing; how motion relates to narration or music; what never moves |
Avoid |
The mistakes this look invites, and what to do instead |
Any other sections may follow, in any order. A number in the text says where it comes from when that matters: measured, from a source, or chosen.
MOTION.<lang>.md is a translation of MOTION.md into the language <lang> (a BCP 47 tag). It follows the same rules and says nothing MOTION.md does not.
6. poster.jpg and CREDITS.md
poster.jpgis a JPEG frame of a film made in the motion: between 960 and 3840 pixels wide, at most 500 KB. It shows the look, not a title card.CREDITS.mdnames every font, image, sound, model or other asset the motion's files use or require, with its licence and where it comes from, and any work the motion learned from. A motion that uses none says so.
7. Extensions
Everything that belongs to one tool lives in that tool's space, and every other tool ignores it.
- Directories. A tool keeps its files in a directory named after it (
react/,remotion/): 2 to 40 characters ofa-z,0-9and single hyphens. - Members. A tool keeps its own
motion.jsonmembers under one member namedx-<tool>, for example"x-remotion": { "fps": 30 }. - Rule. A tool reading a motion ignores directories and
x-members it does not know, and does not report them. It never writes into another tool's space.
What several tools come to share moves into a later version of this format.
8. Languages
| Part | Language |
|---|---|
File and directory names, member names, scope, slug, spec, version, license, tags, token names, the start of the five MOTION.md headings |
English (identifiers) |
name, line |
A localized string: an object whose keys are BCP 47 tags and whose values are text in that language. en is required; other languages are optional |
The body of MOTION.md, translations, $description, authors[].name, CREDITS.md, words drawn in a film |
Any language |
9. Versions
A motion's version changes whenever any of its files change. A published version is never changed: a fix is a new version. A film that uses a motion keeps the copy it took.
spec names the version of this format. A tool that meets a spec it does not know does not guess its meaning. A tool that reads a version reads every version before it: a motion/0.1 motion is a motion/0.2 motion without a scope, and a motion/0.2 motion is a motion/0.3 motion without basedOn.
10. Versions of this format
| Version | Adds |
|---|---|
motion/0.1 |
The format: five files, motion.json, tokens.json, MOTION.md, extensions, languages |
motion/0.2 |
scope, and a motion's id @<scope>/<slug> (§3, Identity) |
motion/0.3 |
basedOn: the motions a motion builds on (§3, Building on another motion) |
This page is SPEC.md in the repository, rendered. Suggest a change