File format spec
§15
Canonical serialization
On this page3 sections
Status
Stable (format version
1.0.0, frozen 2026-10). Backward compatible within 1.x (§16.4). Supersedes the draft v0.1, kept as a historical record; 0.1 files open through the 0.1 → 1.0 migration (§16.2).Schema
https://getkimo.design/schema/kimo-1.0.json (JSON Schema draft 2020-12), generated into packages/core-schema/schema/kimo-1.0.schema.json . The 0.1 schema stays published at …/kimo-0.1.json (schema/kimo-0.1.schema.json, frozen).Reference
@kimo/core-schema (packages/core-schema). Where this document and the implementation disagree, that is a bug in one of them; file an issue.Plan of record
docs/teardown.md §10. Every place where this spec resolves an ambiguity in, or deviates from, that section is listed in §20.License
MIT
The canonical serialization is a pure function of the document's data. Writers MUST produce it; for every canonical text s, serialize(parse(s)) === s.
15.1 Layout
Text
{"$schema": "https://getkimo.design/schema/kimo-1.0.json","format": "1.0.0","features": ["layout/wrap"],"meta": {"name":"Kimo landing"},"variables": {"ink": {"type":"color","value":"#111111"}, "space-m": {"type":"number","value":16}},"nodes": {"A1hero0001": {"type":"frame","parent":null,"order":"a0","name":"Hero"}, "B2title001": {"type":"text","parent":"A1hero0001","order":"a0","content":"Hi"}}}
- The first line is
{; the file ends with}and one LF. - Each root member is written on its own line as
"key": <value>— one space after the colon — followed by,except for the last member. Members appear in canonical order (§15.2);nodesis always last; unknown root members follow the known ones (sorted by code unit) and precedenodes. Only the members defined in §4 are ranked at the root; an unknown root member is not ranked even when its name appears in Appendix A, and its value is opaque (§15.2). - Tables —
nodes,variables,assetsandconflicts(§21) — are written as"key": {, then one line per entry, then}. Entries are sorted by key (code unit). Each entry is"<key>": <value>on a single line; the separating comma is written at the start of every entry line after the first (, "<key>": …), and one blank line separates consecutive entries. An empty table is written{}on the member's line. (Appending or removing the last entry never edits a neighbouring line; the blank line keeps unrelated neighbours out of one conflict hunk in a line-based merge.) - Every other value (root members, table entries) is written as compact JSON: no insignificant whitespace.
- Strings are written as by ECMAScript
JSON.stringify(minimal escaping; non-ASCII as UTF-8; U+2028/U+2029 unescaped). A value never spans lines. - Numbers are written in the shortest form that round-trips (ECMAScript
Number.prototype.toString), e.g.0.30000000000000004,1e+21. Negative zero is written0. NaN and infinities cannot be written. - Properties equal to their default are omitted (§14). Top-level
featuresis sorted by code unit. Arrays otherwise keep their order. Properties whose value is undefined do not exist.
Keywords:
MUST
MUST NOT
SHOULD
MAY
set in small mono caps wherever they are normative
15.2 Key order
- Structs (schema-defined objects: the root, nodes, paints, layout, …): keys listed in Appendix A come first, in that order; all other keys follow, sorted by code unit. The order is a single global ranking that does not depend on the object's kind.
- Records (keys are data): keys sorted by code unit. Record-valued properties are listed in Appendix B. Their values are structs, except where Appendix B says opaque.
- Opaque values — anything below an unknown key, and the values of the opaque records — are ordered purely by code unit at every depth.
This rule is part of the versioning contract (§16.4): because keys introduced by later versions sort after all 1.0 keys and their subtrees are ordered purely by code unit, a 1.0 reader re-serializes a newer document byte-identically.
15.3 Parsing
Readers MUST reject: malformed JSON; duplicate keys in any object (a duplicated node id would otherwise be silently dropped); a root that is not an object. A __proto__ key is ordinary data. Parsing does not validate (§17).