# The document format

> Reference for the .envy.json game UI document - boards, nodes, layout, style, components, interaction, bindings, focus, lists, scenarios, localization and animation.

Source: https://envyui.com/docs/format

An Envy document is one JSON file (`*.envy.json`). Both runtimes read it as is. Missing fields are filled with defaults on load, so hand-written documents stay short. The JSON Schema is available from `envy schema`.

```json
{
  "format": "envy-ui", "version": 2, "id": "d_…", "name": "My game UI",
  "description": "What this UI is for, read by implementers and AI agents",
  "tokens": { "colors": { "accent": "#f2c14e" } },
  "textStyles": { "H1": { "font": "Rajdhani", "size": 56, "weight": 700, "lineHeight": 1.05, "letterSpacing": 6, "uppercase": true } },
  "assets": { "img_…": { "name": "…", "src": "data:image/png;base64,…", "width": 512, "height": 512 } },
  "screens": [ { "id": "…", "name": "Main Menu", "root": "<node id>", "width": 1920, "height": 1080 } ],
  "components": [ { "id": "…", "name": "Button / Primary", "root": "<node id>", "set": "…", "variant": { "Style": "Primary" } } ],
  "componentSets": [ { "id": "…", "name": "Button", "props": [ { "name": "Style", "values": ["Primary", "Danger"] } ] } ],
  "nodes": { "<id>": { } },
  "animations": [ ],
  "sampleData": { "player": { "hp": 72 } },
  "scenarios": [ { "id": "…", "name": "Low health", "data": { "player": { "hp": 5 } } } ],
  "i18n": { "base": "en", "tables": { "de": { "menu.play": "Spielen" } } }
}
```

## Boards and nodes

Screens and components are both **boards**: a root node with no parent. Nodes live in one flat map and form a tree through `parent` and `children`; children order is paint order.

Node types: `frame`, `button`, `text`, `image`, `progress`, `shape`, `instance`. Frames and buttons have children; instances get theirs from their component. Any node can carry `notes`.

| Field | See |
|---|---|
| `layout` (anchors, offsets, width, height, sizing, rotation) | [Layout](/docs/layout) |
| `container` (mode, gap, padding, align, justify, wrap) | [Layout](/docs/layout) |
| `style`, `text`, `image`, `progress`, `shape` | [Style](/docs/style) |
| `instance` (component, overrides, values) | [Components](/docs/components) |
| `states`, `events.click` | [Components](/docs/components), [Data and events](/docs/data) |
| `bindings`, `list` | [Data and events](/docs/data) |
| `focus` | [Focus](/docs/focus) |
| `text.key` | [Localization](/docs/localization) |

## Colors

A color is `#rrggbb`, `#rrggbbaa` or a token reference like `$accent`.

## Animations

```json
{ "id": "…", "name": "Intro", "screen": "<screen id>", "duration": 1.4, "loop": false, "autoplay": true,
  "tracks": [ { "id": "…", "node": "<node id>", "prop": "opacity", "keys": [ { "t": 0, "v": 0, "ease": "out" }, { "t": 0.5, "v": 1, "ease": "linear" } ] } ] }
```

See [Animation](/docs/animation).

## Versions

The format has a version number, and older documents load through a migration step (`normalizeDoc`). Documents from version 1 and the older `strata-ui` id load unchanged.
