Structured design documents
A structured document holds every property as a typed value in a normalized tree, not as markup or a class string. That is what makes a design queryable, diffable, mergeable, and safe for two parties to edit at once.
Normalized, by ID
The document is a flat map from node ID to node, with parents naming their children in order — not a deeply nested object. Nesting reads nicely and is miserable to work with: every lookup is a traversal, every move is a splice at two depths, and every subscription redraws a subtree.
Flat and normalized, a node is found in one step, moved by editing two child lists, and rendered by a component subscribed to that node’s own revision. A thousand-node page updates one node when one node changes.
Values, not strings
The load-bearing rule is that properties are structured. Layout is a value with a direction, a gap, and alignment — not flex items-center gap-4. Colour is a value or a token reference, not #3b5bdb typed into a box.
Everything follows from that. A query for "every node using the accent token" is possible. Renaming a token updates every consumer. A breakpoint override is a patch on specific fields rather than a competing class list. And a value that makes no sense is rejected at the model boundary instead of being stored and rendered as nothing.
What you can do once it holds
The properties compound, and most of the tool’s features are consequences rather than separate work:
- Diff two versions field by field, instead of comparing screenshots.
- Merge two branches semantically — different fields on the same node combine cleanly, and only a real same-field collision needs a human.
- Rebase an in-flight edit against a change that arrived while you were dragging.
- Compile to HTML, React, or Tailwind deterministically, because there is nothing ambiguous left to interpret.
- Let an agent search the document rather than read all of it, which is the difference between a query and a context window.
The cost
You give up the escape hatch. There is no arbitrary code node, no freeform CSS string, no place to paste something the model does not support. When the document cannot express something, the answer is to extend the model, not to smuggle it in as text.
That is frustrating on the day you need one unsupported property, and it is the entire reason the rest works. One escape hatch and every guarantee above becomes conditional: the diff cannot compare it, the merge cannot reconcile it, the export has to pass it through blindly, and the agent cannot reason about it.
Rendering it
A structured document does not imply a proprietary renderer. Loora renders to real DOM and SVG under one camera transform, with a viewport-space overlay for selection and handles — so what you arrange is the same thing the export produces, and the browser does the layout work it is already good at.
Questions
What is a structured design document?
A design file where every property is a typed value in a normalized tree of nodes, rather than markup or CSS strings. Layout, colour, typography, tokens, breakpoints, and motion are all data the tool can validate, query, diff, and merge.
Why not store designs as HTML and CSS?
Because CSS is not diffable in a meaningful way, class strings cannot be validated, and there is no stable identity for an element. You lose semantic merge, targeted patching, token-wide renames, and any confidence that a value is coherent.
Does a structured document limit what I can design?
Yes, deliberately — anything the model cannot express has to be added to the model rather than pasted in as raw code. That constraint is what makes the diff, merge, export, and agent-editing guarantees hold at all.
Published 2026-08-02.