3. The top-level object
A design file is one JSON object with five members, written in this order:
A design file is one JSON object with five members, written in this order:
{
"$schema": "https://raw.githubusercontent.com/arthurafarias/vscode-extension-ui-designer/master/schemas/design-1.0.schema.json",
"$comment": "SoftForge UI Designer design file (FMT-001). Do not edit `tree`. To change the design, append one event per line to `wal`, starting the line with a comma, or use the `ud` command.",
"designVersion": "1.0",
"tree": { },
"wal": [
{"seq":0,"op":"wal.base","epoch":"ep-0c2e4a6b8d1f","treeHash":"sha256:…"}
]
}| Member | Type | Meaning | When it is missing or wrong |
|---|---|---|---|
$schema |
string | URL of the JSON Schema of this format version (section 11). Editors use it for completion and validation. | Ignored; written again with the next change. |
$comment |
string | Instructions for agents and people who open the file as text. The text above, verbatim. | Ignored; written again with the next change. |
designVersion |
string | Format version, "<major>.<minor>". This document describes "1.0". Read before anything else (section 10). |
Read as the current version, with a warning. |
tree |
object | The consolidated document (section 4). | An empty document with one page (section 9.1). |
wal |
array | The wal.base marker followed by the events since the last consolidation (section 5). |
An empty list. |
Members a reader does not know are kept and written back unchanged.
3.1 Layout on disk#
Writers produce one fixed layout:
- the five members in the order shown, indented by two spaces;
- the tree pretty printed with two spaces per level;
- the WAL with one entry per line: first the
wal.basemarker, indented by four spaces, then every event as four spaces, a comma, and the event as compact JSON without any space or line break (line breaks inside texts are written as\nby JSON); - event members in the order
seq,at,by,op,group,note, then the payload; - a line break at the end of the file.
Saving a change therefore produces this diff, and nothing else:
--- a/login.design
+++ b/login.design
@@ -301,5 +301,6 @@
{"seq":12,"at":"2026-10-05T16:40:00.000Z","op":"wal.base","epoch":"ep-9b7d5f3a1c0e","treeHash":"sha256:6f1e2d3c4b5a69788796a5b4c3d2e1f00f1e2d3c4b5a69788796a5b4c3d2e1f0"}
,{"seq":13,"at":"2026-10-06T09:12:30.412Z","by":"Ada","op":"node.update","id":"nd-9f1b3d5c7e2a","set":{"characters":"Sign in to SoftForge"}}
+ ,{"seq":14,"at":"2026-10-06T09:20:04.118Z","by":"Ada","op":"node.update","id":"nd-4c6e8a0b2d1f","set":{"paddingTop":48}}
]
}
The layout is a convention for git, not a requirement for reading: a reader parses the file as ordinary JSON and accepts any spacing. A writer that changes a file whose layout differs (hand edited, or repaired, section 9) writes it in the canonical layout at that moment.
The tree is written in a stable order so that two consolidations of the same document give the same text:
pages by index; nodes depth-first, page by page, siblings by index; other maps by index where they have
one, else by id; members of an object in the order of the tables of section 4, unknown members last.
An empty file (zero bytes or only white space) is a document that has not been written yet: the editor opens it as a blank design with one page and writes the file with the first change.