# motionhub docs > Every page of https://motionhub.dev/docs, in order. ## Overview > https://motionhub.dev/docs/ · from https://github.com/motionhub-dev/motions/blob/main/docs/index.md 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), written down so that a person or an agent can make a new film in it with any engine. It holds no film: no story, script, scenes or timings. You bring the story; the motion keeps the look. [motionhub.dev](https://motionhub.dev) is the open catalogue of motions, and the format they are written in is open too. A motion works in any engine: its components run in Remotion and HyperFrames, and its words and tokens in anything else. ### Start in a minute Pick a motion, then paste this into any agent that can open a URL, with your topic and the motion's id: ```text Read https://motionhub.dev/llms.txt, then make a film about "" in the motion https://motionhub.dev/m/@iamsuosi/clay-world/ ``` That is all. To make it shorter, install the skill once, for every agent on your computer: ```sh npx skills add motionhub-dev/motions -g ``` then ask: ```text /motionhub make a film about in @iamsuosi/clay-world ``` and, to publish a look of your own: ```text /motionhub share this project's look as a motion ``` [Use a motion](https://motionhub.dev/docs/use.md) has every way: the skill, the command line, [Remotion](https://motionhub.dev/docs/remotion.md), [HyperFrames](https://motionhub.dev/docs/hyperframes.md) and any other engine. ### What a motion is made of A motion is a directory of five files, and a directory for each tool that wants ready-made pieces: | File | What it holds | | --- | --- | | `motion.json` | Its id, version, name, one line, authors and licence | | `MOTION.md` | The look in words, for people and agents: essence, colour, type, motion, what to avoid | | `tokens.json` | The exact values, as W3C design tokens: colours, faces, durations, easings | | `poster.jpg` | One frame of a film made in it | | `CREDITS.md` | Every font and asset it needs, with its licence and source | | `react/` | Optional: components that run unchanged in any React engine | The [specification](https://motionhub.dev/docs/spec.md) says exactly what each file holds and what any tool can rely on. ### Where to go next - **Make a film in a motion**: [Use a motion](https://motionhub.dev/docs/use.md), with any agent, from the command line, or in Remotion or HyperFrames. - **Share a look of your own**: [Share a motion](https://motionhub.dev/docs/contribute.md) explains the pull request, what is accepted and how it is reviewed. - **Build a tool that reads motions**: the [specification](https://motionhub.dev/docs/spec.md), and [the hub](https://motionhub.dev/docs/hub.md) for the index and the packages motionhub.dev serves. ### For agents Every page here has a Markdown twin at the same address with `.md` at the end: this one is [/docs/index.md](https://motionhub.dev/docs/index.md). [/llms.txt](https://motionhub.dev/llms.txt) tells an agent how to choose a motion and make a film in it, and lists every page; [/llms-full.txt](https://motionhub.dev/llms-full.txt) is all of them in one file. ## Use a motion > https://motionhub.dev/docs/use/ · from https://github.com/motionhub-dev/motions/blob/main/docs/use.md Pick a motion on [motionhub.dev](https://motionhub.dev), then make your film in it whichever way you work. The format is open, so the same motion gives the same look in every engine. Every motion's page has these steps with its own id filled in. ### With any agent Nothing to install. Paste this into any agent that can open a URL, with your topic and the motion you picked: ```text Read https://motionhub.dev/llms.txt, then make a film about "" in the motion https://motionhub.dev/m/@iamsuosi/red-pencil/ ``` [/llms.txt](https://motionhub.dev/llms.txt) tells the agent how: it fetches the motion, checks it against its SHA-256, reads `MOTION.md` and `tokens.json` whole, and makes your film in its look with whatever engine it uses. #### Install the skill The [agent skill](https://motionhub.dev/docs/skill.md) is the same instructions, kept by your agent so it needs no first line. Install it once, for every project and every agent on your computer (Claude Code, Codex and the others [skills](https://github.com/vercel-labs/skills) knows): ```sh npx skills add motionhub-dev/motions -g ``` Leave out `-g` to install it in the current project only. Then call it by name: ```text /motionhub make a film about in @iamsuosi/red-pencil ``` An agent without slash commands takes the same request in words: "Make a film about … in the motion @iamsuosi/red-pencil". ### Share a look of your own Made a film whose look others should have? With the skill installed, ask your agent from that project: ```text /motionhub share this project's look as a motion ``` It writes the motion as `@/`, takes the look from the project and never the film's story, runs the checks the pull request will run, shows you the result and opens the pull request only when you say yes. [Share a motion](https://motionhub.dev/docs/contribute.md) has the rules it follows and the commands it runs. ### From the command line ```sh npx @motionhub/cli search hand-drawn # motions with every word npx @motionhub/cli get @iamsuosi/red-pencil # into ./motion, checked against its SHA-256 ``` `get` takes a motion's id: its creator's GitHub name and its slug, `@iamsuosi/red-pencil`. The [command line](https://motionhub.dev/docs/cli.md) page has every command. ### In Remotion or HyperFrames A motion's tokens become values in either engine, and a motion with `react/` brings components that run in both unchanged. Each engine's guide starts from its own agent skills beside motionhub's: - **[Remotion](https://motionhub.dev/docs/remotion.md)**: with Remotion's skills, or by hand with [`@motionhub/remotion`](https://motionhub.dev/docs/remotion-binding.md) - **[HyperFrames](https://motionhub.dev/docs/hyperframes.md)**: with HyperFrames' skills, or by hand with [`@motionhub/hyperframes`](https://motionhub.dev/docs/hyperframes-binding.md) Both provide [`@motionhub/runtime`](https://motionhub.dev/docs/runtime.md), which is all a motion's components import besides React. ### In anything else A motion needs no tool, and no particular engine: HTML and CSS, GSAP, Motion Canvas or a renderer of your own. `MOTION.md` says in words how it looks and moves, and `tokens.json` gives the exact colours, faces and timings, the way a design system would. Follow them in your own engine, and credit the motion and its fonts as its `CREDITS.md` asks. ## Command line > https://motionhub.dev/docs/cli/ · from https://github.com/motionhub-dev/motions/blob/main/docs/cli.md `@motionhub/cli` finds, fetches and checks motions. It needs Node.js 20 or later and has no dependencies; run it with `npx` or install it with `npm i -g @motionhub/cli` for the `motionhub` command. ```sh npx @motionhub/cli [options] ``` ### search ```sh npx @motionhub/cli search [words ...] ``` The motions on motionhub.dev that have every word, in their id, names, line or tags. ### get ```sh npx @motionhub/cli get [--out ] ``` The newest version of a motion, by its id (`@iamsuosi/red-pencil`), into `./motion` (or `--out`), checked against the SHA-256 in the index. ### init ```sh npx @motionhub/cli init [--github ] ``` A new motion `@/` in `.//`, with every required file but the poster, to fill in. Your GitHub login comes from `gh`, or `--github`. ### check ```sh npx @motionhub/cli check [dir ...] [--format-only] [--author ] [--was ] ``` A motion against the [specification](https://motionhub.dev/docs/spec.md) and motionhub's rules. With no directory it checks the current directory when it is a motion, and otherwise every motion under `./motions/`. `--format-only` leaves out the hub's rules, for a motion that is not headed for motionhub; `--author` and `--was` check it as a pull request by that account, changing that published `motion.json`. ### share ```sh npx @motionhub/cli share [--github ] [--pr] ``` A motion through the checks its pull request will run, as you and against what is published. With `--pr` it opens that pull request from your fork of the repository, signed off, as the account `gh` is signed in as. [Share a motion](https://motionhub.dev/docs/contribute.md) explains what happens next. ## Contributing a motion > https://motionhub.dev/docs/contribute/ · from https://github.com/motionhub-dev/motions/blob/main/CONTRIBUTING.md A motion arrives as a pull request that adds `motions/@//` in the [format](https://motionhub.dev/docs/spec.md). Your GitHub account is your identity here: the motion's `scope` is your GitHub username in lowercase, its id is `@/`, and the `github` of at least one author in `motion.json` must be the account that opens the pull request. Every motion here has a scope, the maintainers' own included: there are no unscoped, official ids. ### The quick way With the [motionhub skill](https://motionhub.dev/docs/skill.md) installed: ```sh npx skills add motionhub-dev/motions -g ``` ask your agent from the project whose look you want to share: ```text /motionhub share this project's look as a motion ``` It runs the steps below for you and asks before it opens the pull request. By hand: ```sh npx @motionhub/cli init # .// with every required file to fill in, scoped to you npx @motionhub/cli share # the checks below, as your GitHub account (gh) npx @motionhub/cli share --pr # the pull request, from your fork, signed off ``` ### Before you open it ```sh npx @motionhub/cli check --author # or, in a clone of this repository: node tools/check.mjs motions/@/ --author ``` The checker has no dependencies (Node 20 or later). It runs the same rules as the pull request's checks: the format, then the rules below. Write `MOTION.md` in English if you can, or add an English translation next to it (`MOTION.en.md` when `MOTION.md` is in another language): more people and agents can use it. Neither is required. ### What is accepted - **Licences.** `license.text`: `CC-BY-4.0` (the default), `CC-BY-SA-4.0` or `CC0-1.0`. `license.code`: `MIT` (the default), `Apache-2.0`, `BSD-2-Clause`, `BSD-3-Clause`, `ISC` or `0BSD`. - **Fonts.** Open licences only (SIL Open Font License, Apache 2.0, Ubuntu Font Licence), each named in `CREDITS.md`. - **Assets.** Your own, or CC0, CC BY or OFL, each named in `CREDITS.md` with its source. Public-domain artworks are welcome when `CREDITS.md` says where they come from. - **Size.** At most 1 MB for the whole motion, the poster included. No video, audio over 500 KB, or build output in the repository. - **Scope and directory.** A motion has a `scope` (`hub.scope`) and sits in `motions/@//`, named by its id (`hub.slug`). - **Built on.** Every motion named in `basedOn` is one in this catalogue (`hub.basedOn`). - **Signed commits.** Every commit carries a `Signed-off-by:` line (`git commit -s`), certifying the [Developer Certificate of Origin](https://developercertificate.org): you have the right to contribute what it contains under its licence. ### Original work A motion is a look of your own. You may learn from any film or project, and say so in `CREDITS.md`, but you build it anew: - No brand, logo, trademark, product interface or character of someone else, and no look that would be mistaken for one. - No copy of another project's code, artwork, fonts or text, whatever its licence, unless that licence allows it and `CREDITS.md` names it. - An art movement or a painter's manner is fine. A copy of a particular protected artwork is not. Building on another motion is welcome when its licence allows it (every licence accepted here does): publish yours under your own scope, name it in `basedOn` in `motion.json` ([SPEC.md](https://motionhub.dev/docs/spec.md) §3, a motion in this catalogue), say in `CREDITS.md` what you took and what you changed, and keep its notices for any code you copied. The motion you built on shows yours, and its creator's page counts it. A pull request that breaks these is closed. If you hold rights in something here, open an issue and it will be looked at quickly. ### Tool directories A tool keeps its own files in a directory named after it (SPEC.md §7). Where several people write for one tool, the directory follows that tool's convention here: - **`react/`**: the motion's components, for any React engine. `react/parts/*.tsx` are React components that import only `react`, `@motionhub/runtime`, `three` and each other, colour with `var(--color-)`, set type with `var(--font-)`, and take their words, data, progress and video `src` as props, so they run unchanged in Remotion through [`@motionhub/remotion`](https://motionhub.dev/docs/remotion-binding.md) and in HyperFrames through [`@motionhub/hyperframes`](https://motionhub.dev/docs/hyperframes-binding.md). Each exports a literal `meta` beside it: `name`, `purpose`, `line`, `fits`, `params` (each with `type` and `doc`) and `preview`. Files they import sit in `react/assets/`, and `react/previews/.jpg` shows each one. A face Google Fonts does not serve goes in `react/fonts/` as WOFF2, cut to the characters the components draw (at most 300 KB each), with `react/fonts/fonts.json` naming each (`[{family, file, weight, style}]`) and `CREDITS.md` its licence (`hub.font`); players and bindings use it before Google Fonts. `react/sound.json` is how its world sounds: `{bpm, root, kit, roles: {land, move, draw, count, cut, out}}`, each role a voice of `@motionhub/runtime/sound` (`hub.sound`), and the reel says when with `export const cues = [{at, role, dur}]`. `react/reel.tsx` is the reel the motion's page plays live (HUB.md, "Reels"): a default export that composes the components by `useTime()`, with `Sequence`, `interpolate` and `Easing` from the runtime, and `export const reel = {seconds}`, at most 30. - **`remotion/`**: only what `react/` and `@motionhub/remotion` do not already give a Remotion project (a component that needs `@remotion/*`, say), imported from `../motion/remotion`, with a `README.md` saying what each piece is for and its props. Components there follow the same rules, and faces may be bundled under `remotion/fonts/` with their licence text. A convention for another tool is added here when its first motion arrives. ### Code in a tool directory Code under a tool directory runs in other people's browsers and render machines, so the checks refuse code that: - reaches the network (`fetch`, `XMLHttpRequest`, `WebSocket`, `EventSource`, `navigator.sendBeacon`); - evaluates text as code (`eval`, `new Function`, a string passed to `setTimeout` or `setInterval`) or imports at run time (`import(…)`); - reads or writes cookies or storage (`document.cookie`, `localStorage`, `sessionStorage`, `indexedDB`). A tool may add rules of its own for its directory. ### Review 1. The checks run on every pull request and post the result. 2. A reviewer agent reads the motion for originality, safety and whether `MOTION.md` lets someone make a film in it, and leaves its notes as comments ([REVIEW.md](https://github.com/motionhub-dev/motions/blob/main/REVIEW.md) is what it looks for). It advises; it does not merge. A pull request from a fork is reviewed when a maintainer asks for it. 3. A maintainer merges. A first-time contributor's pull request always waits for a person. ### Changing a published motion Only one of a motion's published authors may change it: the checks compare the pull request's author with the authors of the version on the main branch, so adding yourself to `authors` does not make a motion yours. To build on someone else's motion, publish your own under your scope and credit theirs, by its id, in `CREDITS.md`. A change carries a higher `version` than the published one, since a published version never changes ([SPEC.md](https://motionhub.dev/docs/spec.md) §9). The newest version replaces the previous one in its directory; published packages of earlier versions stay where they are ([HUB.md](https://motionhub.dev/docs/hub.md)). ## Motion format 0.3 > https://motionhub.dev/docs/spec/ · from https://github.com/motionhub-dev/motions/blob/main/SPEC.md > **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: ``` / 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..md a translation of MOTION.md optional / 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](https://semver.org) 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](https://www.rfc-editor.org/info/bcp47) 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 `@/` when it has a scope, and `` 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](https://spdx.github.io/spdx-spec/v2.3/SPDX-license-expressions/), for example `"CC-BY-4.0"` or `"MIT"`. ```json { "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](https://www.designtokens.org/) of the W3C Design Tokens Community Group (DTCG), version 2025.10. Any tool that reads DTCG reads it. - It has a `color` group and a `font` group, each with at least one token. - `color` tokens are of type `color`; `font` tokens are of type `fontFamily`. A group may set `$type` once 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 `$description` says what it is for, in any language. - Other groups are allowed and are read as plain DTCG. For timing, use `duration` tokens and `cubicBezier` tokens; seconds, not frames. - Values are literal or DTCG aliases (`"{color.ink}"`). No value refers to a file or a URL. ```json { "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..md` is a translation of `MOTION.md` into the language `` (a BCP 47 tag). It follows the same rules and says nothing `MOTION.md` does not. ### 6. `poster.jpg` and `CREDITS.md` - `poster.jpg` is 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.md` names 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 of `a-z`, `0-9` and single hyphens. - **Members.** A tool keeps its own `motion.json` members under one member named `x-`, 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 `@/` (§3, Identity) | | `motion/0.3` | `basedOn`: the motions a motion builds on (§3, Building on another motion) | ## The hub > https://motionhub.dev/docs/hub/ · from https://github.com/motionhub-dev/motions/blob/main/HUB.md > **Status:** Plan — the build, the site, the generic skill, the deploy and reels are written; listing levels and votes are not How this repository is published at [motionhub.dev](https://motionhub.dev): the catalogue, the files a tool or an agent fetches, reels and the levels a motion is listed at. This is the hub's policy and distribution, not the motion format: the format is [SPEC.md](https://motionhub.dev/docs/spec.md), and nothing here changes it. ### Where things are | Path | What it is | | --- | --- | | `motions/@//` | One motion in the [format](https://motionhub.dev/docs/spec.md), published by the GitHub account ``, id `@/`. Every motion on the hub has a scope; there are no unscoped, official ones. The newest version of each is the one in the main branch | | `tools/check.mjs` | The checker every pull request runs, with no dependencies: the one place the rules are written as code | | `bin/motionhub.mjs`, `tools/hub.mjs`, `package.json` | The npm package `@motionhub/cli` (command `motionhub`): `check` (the checker, for tools and people outside this repository), `search` and `get` (the index, and a package checked against its SHA-256 and unpacked into `./motion`). A tag `v` stages it on npm (`.github/workflows/publish.yaml`, trusted publishing, no token) and a maintainer approves it with `npm stage approve` | | `packages/runtime/`, `packages/remotion/`, `packages/hyperframes/` | The npm packages `@motionhub/runtime` (what a motion's components draw with, in any engine) and its bindings for Remotion and HyperFrames. A tag `-v` stages one the same way | | `tools/build.mjs` | Builds the files below into `dist/` from `motions/` and the skill, refusing while any motion has an issue | | `brand/`, `tools/brand.mjs` | The brand: tokens (colours for both themes, type, sizes), the logo, icons, favicons and default share card, and the rules for using them ([brand/BRAND.md](https://motionhub.dev/docs/brand.md)). `node tools/brand.mjs` writes `brand/tokens.css` from the tokens | | `site/` | The site's pages, an [Astro](https://astro.build) project with its own `package.json`: the gallery, a page per motion and the 404 page, in the brand's tokens and self-hosted fonts. `npm run build` there runs `tools/build.mjs` into `dist/`, builds the pages over it and adds them, never replacing a served file | | `docs/`, `tools/docs.mjs` | The guides only the docs have (overview, using a motion, the command line), and the list of every docs page with the document it is. A docs page is a document where it already lives in the repository, never a copy | | `tools/site.mjs` | What the pages share with the build, with no dependencies: the Markdown a motion's documents use, its colours and faces, and `_headers`, `robots.txt` and `sitemap.xml` | | `site/player/` | The reel player and its build: one page and one script per motion with a reel, under `/play//` | | `site/worker.mjs`, `wrangler.jsonc` | The Cloudflare Worker: it serves the build as static assets and the packages from the R2 bucket `motionhub` | | `.github/workflows/deploy.yml` | Builds, publishes each new package to R2 and deploys, on every push to the main branch and every six hours. It refuses to replace a published package | | `skills/motionhub/SKILL.md` | The generic skill: how any agent chooses a motion, fetches it and makes a film in it. `/llms.txt` is the same text, followed by the index of the docs | The repository keeps text, code and posters only: no video. ### What motionhub.dev serves A static site, rebuilt from the main branch whenever it changes and every six hours. | Path | What it is | | --- | --- | | `/` and `/m/` | The gallery and a page per motion: poster, reel, colours, faces, `MOTION.md` | | `/creators/` and `/creators//` | Everyone who is an author of a motion, by GitHub login in lowercase: their motions, the motions of others built on them (`basedOn`), and their downloads and likes | | `/api/motions.json` | The index: `spec`, and `motions`, one row per motion ordered by id, with `slug` (the motion's id, `` or `@/`, so a client that only knows `motion/0.1` never takes one motion for another), `scope` (when it has one), `spec` (its motion's), `version`, `name`, `line`, `lang`, `tags`, `authors`, `basedOn` (when it has one), `license`, `poster`, `tools` (the directories it has for tools), `package` (`url`, `sha256`, `bytes`) and, when it has a reel, `reel` (the path of its player). Paths are relative to the site | | `/api/stats.json` | Each motion's downloads and likes: `motions`, by id, with `downloads.total`, `downloads.last30` and `likes`, and `generated`. Kept for five minutes; see Counts below | | `/auth/login`, `/auth/callback`, `/auth/logout`, `/api/me`, `/api/likes/` | Signing in with GitHub, who is signed in and what they like, and giving (`POST`) or taking back (`DELETE`) a like. `DELETE /api/me` forgets the person. See Likes below | | `/m//MOTION.md`, `/m//tokens.json`, `/m//motion.json` | The newest version's files, to read directly | | `/m//.tgz` | The whole motion at that version, its paths under `/`, with its SHA-256 in the index. The same files always give the same bytes | | `/play//` | The motion's reel, playing live: its `react/reel.tsx`, its components, React and `@motionhub/runtime` in one script, with its faces. Served under a policy that lets it load nothing from anywhere else | | `/llms.txt` | For agents: what a motion is, how to choose one from the index and how to use it, then every docs page's Markdown twin | | `/docs//`, `/docs/.md`, `/llms-full.txt` | The docs: the repository's own documents (`SPEC.md`, `CONTRIBUTING.md`, this file, the skill, the packages' READMEs, `brand/BRAND.md`) and the guides in `docs/`, each as a page and as Markdown, and all of them in one file. The list is `tools/docs.mjs` | A tool needs the index to search and one package to use a motion; it never downloads the repository. Every published package stays at its URL: the build knows only the newest versions, so the deploy adds packages and never replaces or removes one. ### Reels A motion's page plays the motion live, from its reel: `react/reel.tsx`, a React component that composes the motion's components and animates them by `useTime()` for at most 30 seconds (`export const reel = {seconds}` and a default export; `hub.reel`). It shows how the motion moves, at a brisk pace, with no narration and no story of a film. The site's build bundles each reel with its components, React and `@motionhub/runtime` into `/play//` (`site/player/build.mjs`), and the page shows it in a frame sandboxed to scripts alone, with no origin of its own; `/play/*` is served under a content security policy that loads nothing from anywhere else and connects nowhere. A component's `