The .kimo model
A document is one JSON object. Its nodes member is a flat table: id → node. Each node
names its parent (an id, or null at the top level). There is no nested children array.
Siblings are ordered by an internal key, and you only ever deal with an index.
On this page6 sections
{ "type": "frame", "name": "Card", "w": 320, "h": {"mode": "fit"},"fill": "#FFFFFF", "radius": 12,"layout": {"dir": "column", "gap": 8, "pad": 16} }
Ids
- Ids are 6–24 letters/digits (
Hq3Lm9aZ1x). Kimo mints them. You name new nodes withkeyand refer to them as@keywithin the same call.created[]in the result maps keys to ids. - Names (
name) are labels only. Never use them to reference anything. - Inside an instance, descendants are addressed by IdPath:
instanceIdplus the path inside its component, for exampleInst000001/Label00001(seecomponents).
Node types
| type | Key fields |
|---|---|
frame | container. w,h (Size), fill, stroke, radius, clip, layout, effects |
group | container with no box of its own; bounds = children |
rect, ellipse, polygon | w,h required; fill, stroke, radius / sides / innerRadius |
path | d (SVG path data), viewBox, w,h, fillRule |
text | content (string), grow, style (see text) |
icon | set (lucide, feather, phosphor, material-*), icon (glyph name), w,h, color |
instance | of (component id), props, args, overrides (see components) |
note, prompt | canvas annotations: content |
framew,h (Size), fill, stroke, radius, clip, layout, effectsgrouprect, ellipse, polygonw,h required; fill, stroke, radius / sides / innerRadiuspathd (SVG path data), viewBox, w,h, fillRuletextcontent (string), grow, style (see text)iconset (lucide, feather, phosphor, material-*), icon (glyph name), w,h, colorinstanceof (component id), props, args, overrides (see components)note, promptcontentOnly frame and group hold children. Images are fill: {kind:"image", src:"./assets/…"} on a
rect or frame, imported with kimo_import / kimo_assets. There is no image node.
Common fields
- Placement:
x,y(relative to the parent; ignored inside a layout frame unlessposition: "absolute"),name,locked,theme(pins, seetokens). - Look:
opacity0–1,visible,rotation(degrees CCW),blend,flipX/flipY. - Paint: a color string
#RRGGBB/#RRGGBBAA,{space:"oklch", l, c, h}, a binding{"$ref":"name"}, or{kind:"linear"|"radial"|"angular", stops:[{color, at}]}. A list paints bottom to top.fill: []means "no paint". - Stroke:
{paint, width, align:"inside"|"center"|"outside", dash?};widthcan be per side{t, r, b, l}. - Effects:
[{kind:"shadow", x, y, blur, color, spread?, inner?}, {kind:"blur", radius}, {kind:"backdrop-blur", radius}].
Pages
A document can have several pages (kimo_get_state → pages[]). A page is not a node: a
top-level node's page field names its page, and a top-level node without page is on the first
page. Children are on their top-level ancestor's page; never set page below the top level.
Read one page with kimo_query {select: {topLevel: true, page: "<id>"}}; create, rename, move
and delete pages with the page op (see ops). Polygons take star: {ratio} (inner / outer
radius, default 0.38) to draw stars; an image fill with fit: "crop" shows its crop region.
Defaults and nulls
A field equal to its default is the same as the field being absent, and Kimo omits it when it
saves. The format never stores null. To clear a field, use update {unset:["field"]} (a null
in update.set is read the same way; a null field in a new node body is dropped).
Features
Some constructs need a feature listed in the document's features: layout/wrap,
layout/stretch-baseline, size/min-max, text/runs, tokens/composite. kimo_apply_ops
declares them for you in the same edit that writes the gated value (for example
layout.align: "stretch"), so you never set features yourself.
The normative JSON Schema is the resource kimo://schema/1.0.