2. Layers and source tree

The five layers above the line (core, text, layout, render, commands) are webview-safe: they are compiled a second time with tsconfig.webview.json (lib: ["ES2022", "DOM"], types: []), so an acciden…

Esta página está em inglês; a tradução está a caminho.

2.1 Folders#

Folder What it holds Runs in
src/core The document model: node, page, style, variable and comment types; ids; events and fold; indexes; drafts and commit groups; property resolution (instances, styles, variables, modes); undo inverses; the selector engine (CLI-001 §6); UDX parse and print (CLI-001 §7); SVG import sanitiser. host, script worker, CLI, webview, dev server
src/text The text engine: HarfBuzz binding, ICU4X segmenter binding, font index and loading interface, itemisation, bidi, line breaking, text layout, glyph path cache (§6). everywhere
src/layout The layout engine: constraints, auto layout (flex and grid), sizing, text auto-resize, incremental relayout, absolute transforms and bounds (§5). everywhere
src/render The display list builder, the Renderer interface, the Canvas2D renderer, the SVG writer, the PDF writer, the resvg adapter, tiling and LOD planning, the spatial index, hit testing (§7). everywhere (Canvas2D in the webview and dev page; resvg on host and CLI)
src/commands The command registry, every command definition by category (commands/node/, commands/text/, commands/layout/, …), the run pipeline, the JSON Schema subset validator, target resolution, transactions (§3). everywhere (the webview runs it only to predict, §11.4)
src/plugin-api The Figma Plugin API compatibility layer: the QuickJS loader, the prelude that defines the figma and ud globals inside the sandbox, the member map, value marshalling, ud-plugin-api.d.ts generation (§8). host (script worker), CLI
src/mcp The tool table (one row per Figma MCP tool and native ud_* tool), tool handlers, the MCP stdio server, resources and prompts, the Figma schema snapshot comparator, the loopback asset server (§9.6). host, CLI
src/cli The ud command: argument parsing generated from schemas, native verbs (tree, inspect, apply, render, …), file and actor resolution, output formatting, exit codes, the terminal shim (§9). CLI
src/headless A document opened straight from its file under a lock, with assets folder access, for the CLI when no editor has it open (§9.4). CLI
src/bridge The socket between ud and a running editor: registry folder, server, client, wire protocol (§9.4). host (server), CLI (client)
src/host/controller DesignController and everything an editor host needs that is not VS Code: the command queue, the undo stack, merging external changes, proposals, the script worker, the webview protocol, the Workbench interface (§10). host, dev server
src/host/vscode The VS Code host: CustomEditorProvider, document lifecycle, save and backup, file watching, Command Palette and keybinding contributions, settings, status bar, SecretStorage, licensing client, AI runner, LM tools, the terminal PATH (§10). host
src/third-party Vendored code that is not edited here: the Soft Forge Payments licensing client, generated Unicode tables (bidi classes and scripts, §6.1). host, CLI (licensing); everywhere (Unicode)
src/extension.ts activate(): wires src/host/vscode together. host
media/ The webview page: custom elements, the canvas, panels, the AppModel replica, the render worker (§11). media/lib/ is generated (§15.1), media/wasm/ and media/fonts/ are copied assets. webview, dev page
dev/ The development server (npm run dev): the same controller and webview in a browser, plus test endpoints (PLT-11). dev server (Node)
test/ Unit, conformance, golden image, Plugin API, CLI, bridge and integration tests, fixtures and their generators (§14). Node, VS Code test host, headless Chromium
scripts/ Build and maintenance scripts: copy WASM, generate contributions and typings, refresh the Figma tool snapshot, check the webview and the layer rules. Node (development only)

2.2 Which layer may import which#

text
                  ┌───────────┐
                  │ src/text  │  (nothing; WASM and font bytes are injected)
                  └─────▲─────┘
                        │
┌───────────┐     ┌─────┴─────┐     ┌────────────┐     ┌──────────────┐
│ src/core  │◄────┤ src/layout│◄────┤ src/render │◄────┤ src/commands │
└─────▲─────┘     └───────────┘     └────────────┘     └──────▲───────┘
      │  (core is imported by every box below)                │
      │                                       ┌───────────────┴──┐
      │                                       │ src/plugin-api   │
      │                                       └───────▲──────────┘
      │                                       ┌───────┴──────────┐
      │                                       │ src/mcp          │
      │                                       └───▲─────────▲────┘
      │                ┌───────────────┐          │         │
      │                │ src/bridge    │◄─────────┼─────┐   │
      │                └───────▲───────┘          │     │   │
      │       ┌────────────────┴──┐       ┌───────┴─────┴┐  │
      │       │ src/host/controller│◄─────┤ src/cli      │  │
      │       └──────▲──────▲─────┘       │ src/headless │──┘
      │              │      │             └──────────────┘
      │   ┌──────────┴───┐  │ ┌──────┐
      │   │src/host/vscode│ └─┤ dev/ │
      │   └──────────────┘    └──────┘
      │
   media/ ──► media/lib/{core,text,layout,render,commands}  (compiled copies, never src/ directly)
Layer May import Must not import
src/text nothing in the repository Node built-ins, DOM globals other than WebAssembly, TextDecoder
src/core src/third-party/unicode Node built-ins, DOM, vscode. Randomness only through globalThis.crypto.getRandomValues.
src/layout core, text as core
src/render core, text, layout as core. The Canvas2D renderer is written against a local Canvas2DLike interface, so it compiles under the Node configuration.
src/commands core, text, layout, render as core. Host-only services (raster, file reads, clipboard) come through ctx.services.
src/plugin-api the five above, the QuickJS package vscode, DOM
src/mcp the above, plugin-api vscode
src/bridge core (types), Node net, fs, os vscode, host
src/headless core, commands, layout, text, Node fs vscode, host
src/cli everything but src/host vscode
src/host/controller everything but cli and host/vscode; Node worker_threads vscode
src/host/vscode everything but cli —
dev/ src/host/controller and below, Node http vscode
media/ media/lib/**, its own modules anything outside media/

The five layers above the line (core, text, layout, render, commands) are webview-safe: they are compiled a second time with tsconfig.webview.json (lib: ["ES2022", "DOM"], types: []), so an accidental Node import fails the build. scripts/check-layers.mjs (run by npm run lint) enforces the rest of the table by parsing import specifiers.

2.3 Where each part runs#

Process Runs Holds a document?
Extension host (VS Code) src/host/vscode, DesignController, registry, bridge server, MCP tool handlers for bridged calls, LM tools, licensing, AI runner Yes: the authoritative copy of each open document.
Script worker (a worker_threads worker of the extension host, one per open document, started on first use) QuickJS, src/plugin-api, a replica of the document A replica that folds every committed event; scripts run on a draft of it (§8.2).
Webview (one per editor tab; a split view gets a second one) media/, media/lib/*; its render worker (a Worker with an OffscreenCanvas, ADR-10) runs shaping, layout and tile rasterisation A replica built from the snapshot and the event deltas the host sends (§11.4); the worker holds a second copy fed by the same deltas.
ud process (terminal, Claude Code, ud mcp) src/cli, src/mcp, and either the bridge client or src/headless Only headless: the file, under a lock. Through the bridge it holds nothing.
Dev server (npm run dev) dev/, DesignController, the webview page in a real browser The authoritative copy, in memory, backed by a file on save.