Source is truth — how the editor writes your code back
Most editors keep their own document and ask you to accept it as the source of truth. vgai does the opposite: your project’s source is the truth, and the editor is a second way to edit it. There is no sidecar file, and there is nothing to keep in sync.
Every JSX element gets an identity
Section titled “Every JSX element gets an identity”At build and dev time, ui-source/ walks your TSX with the TypeScript compiler API (no Babel)
and stamps each JSX element with a data-oid attribute. Alongside that it builds an index
mapping every OID to { file, line, col, component, tag }.
That index is the whole trick. When you click a mesh in the viewport, the editor reads the OID off the live object and knows the exact source location that produced it — file, line and column.
An edit is surgical, not a re-serialize
Section titled “An edit is surgical, not a re-serialize”Because the editor knows where an element came from, a change rewrites only that element’s props. It does not regenerate your file.
Concretely: drag a crate in the viewport, and the position={[2, 0, 0]} literal on that one JSX
element updates. Your imports, comments, helper functions, formatting and every other element are
untouched — because nothing else was ever read or rewritten. Writes go through
SourceWriteBackend (readSource / applySource / prepare / runGesture), which is also the
seam that lets the same editor run against a dev server, the browser’s own storage, or a real
directory you picked.
Expression-bound props are read-only, on purpose
Section titled “Expression-bound props are read-only, on purpose”The editor only writes back literals. Given:
<mesh position={[2, 0, 0]} /> {/* editable — a literal tuple */}<mesh position={spawnPoint} /> {/* read-only — an expression */}…the first is draggable and the second is shown but not overwritten. The editor will not
resolve spawnPoint, guess its value, and replace your variable with a number — that would
silently destroy code you wrote deliberately. It reports the value it can see and leaves the
expression alone.
This is the same principle as the play-mode rule: once simulation runs, live state is gameplay’s output mixed with your intent, and attribution is undecidable — so play edits are ephemeral by architecture, not by omission. A JSX literal is an input to code, not a mirror of runtime state.
Autosave writes through the active adapter
Section titled “Autosave writes through the active adapter”There is no “editor format” to save into. Autosave asks whichever adapter is active to persist through its own truth: a three root writes TSX source, a canvas root writes its an ingested game never touches vendored source.
Browsers give no filesystem-change events, so the editor derives its watch signal from the storage backend’s own mutations. It can do that safely precisely because it is the sole writer.
The honest gap
Section titled “The honest gap”Structural JSX authoring — inserting an element at a chosen point in the tree, or extracting a subtree into a new component — does not exist yet. Prop-level editing is surgical and complete; “extract a component” has no editor path today and is done by hand in your file.
See also
Section titled “See also”- Worlds and roots — why a three root has no document format.
- Editor architecture · The starter world