Files
figcraft/docs/architecture.md
BFlat 10a9b7b165 M8: Windows QA fixes (#131)
Found and fixed in a Windows pass of everyday workflows: unsaved documents are now copied in the background (at most every 10 s) and offered back after a crash or forced quit (file.recover); Ctrl+arrow / Ctrl+Backspace / Ctrl+Delete text motion follows Windows and Linux conventions (keymap::text_motion); number-field scrubbing keeps its value; typing in a Tab-focused field works; default linear gradients and their handles behave; Escape closes dialogs without deselecting; clipped panel hints wrap; the unsaved-changes dialog is translated.
2026-10-11 18:20:38 +07:00

7.3 KiB
Raw Permalink Blame History

FigCraft architecture

Last reviewed: 2026-10-10 · Last updated: 2026-10-11 · Change: minor (the shared hub in collab-net and the figcraft-server app) · Target: Figma Design

How FigCraft is built today. Engine first, a thin swappable UI, everything a command; a Figma-shaped data model (a scene graph of frames with auto layout, components and variables). ~108,800 lines of Rust (2026-10-10).

Crates and layers

cargo xtask layers enforces the layering (xtask/src/layers.rs): a crate may depend only on lower layers. Nothing below L6 depends on egui, eframe, rfd or winit, so the UI crate can be replaced.

Layer Crate Lines Role
L0 figcraft-geom ~0.5k Affine transforms, shape path builders (rounded and smoothed corners, polygons, stars, arcs) on kurbo
L0 figcraft-color ~1.3k Colours (HSB/HSL, hex/CSS, Display P3), paints (solid, gradients, image), blend modes
L1 figcraft-doc ~8.5k Document model: pages, node tree in a persistent map (imbl, stable ids), properties, components, styles, variables, prototype data, comments, versions. Serde everywhere
L2 figcraft-layout ~1.8k Auto layout (horizontal, vertical, wrap, grid; hug/fill/fixed; min/max), constraints, layout grid geometry
L2 figcraft-text ~3.1k Font database (optional embedded craft-fonts + system scan), shaping (harfrust), bidi, line layout, glyph outlines (skrifa), variable fonts
L2 figcraft-collab ~3.4k Real-time collaboration core (no networking): synced object/property model, change sets, fractional positions, server ordering and validation, client reconciliation, wire messages
L2 figcraft-plugin ~1.0k Plugin manifest and the WebAssembly sandbox (wasmi, metered, memory cap, no file system, network or clock)
L2 figcraft-pathops ~1.1k Booleans (linesweeper), outline stroke with alignment, arrowheads
L3 figcraft-render ~5.4k Scene → pixels on tiny-skia (CPU): isolated layers for opacity/blend/effects, clips, masks, shadows, blurs (uniform, progressive, background), noise, texture, glass, text; banded in parallel; retained rendering of only what changed; levels of detail when zoomed out
L3 figcraft-format ~5.2k Native .figcraft (zip of document.json + images; streamed JSON), local library files, versions, REST API file JSON import (rest/)
L4 figcraft-svg ~3.7k SVG export and import (usvg)
L4 figcraft-pdf ~2.3k PDF export (krilla) with print options
L5 figcraft-engine ~39.3k Sessions, undo history (Arc snapshots), the command registry (cmd/*, spec!), pointer tools and vector edit mode, snapping and measuring, components sync, libraries, prototype runtime, Dev Mode code generation, the menu catalog (catalog.rs) and the keymap (keymap.rs), a panic guard
L6 figcraft-ui-egui ~31.9k The UI3-style frontend: canvas (render worker), toolbar, layers, Design/Prototype/Inspect panels, colour picker, menus, dialogs, presenter, comments, accessibility (AccessKit), the control channel server
L6 figcraft-mcp ~2.4k MCP server (JSON-RPC over stdio), headless or bridged to a running app
L6 figcraft-collab-net ~3.0k Live sessions over the network: the WebSocket transport (tungstenite, a reader and a writer thread per connection), the hub that runs a collaboration core server per open file for the session host the app embeds and for figcraft-server (behind a Backend), the joining and managing clients (publishing), invite links, presence relay and limits; the browser client; the only crate allowed networking dependencies
apps figcraft, figcraft-cli, figcraft-web, figcraft-server ~3.2k Desktop app (eframe + wgpu), command line, browser build (WASM, WebGPU/WebGL2), collaboration server (files, share links, persistence; server.md)
plugins plugins/ (own workspace) Rust plugin SDK and two example plugins, built for wasm32 by cargo xtask plugins (plugins.md)
tools xtask ci, layers, assets, parity, version, icon, wasm, plugins, bench

Data model

A Document holds pages, a persistent map of nodes (frames, groups, sections, rectangles, ellipses, polygons, stars, lines, vector networks, text with styled runs, boolean groups, components, component sets, instances, slices), styles, variable collections, comments, versions and images by hash. Instances keep their main's id and per-layer overrides; the engine keeps their materialised children in sync when a main changes (directly for value, size and add/remove edits, by a rebuild otherwise). Snapshots are cheap (Arc and structural sharing), which gives unlimited undo with one step per gesture.

Commands: one path for every surface

Every user-visible behaviour is a command in crates/engine/src/cmd/* (455 ids after #101) with an id, label, parameter docs and undo flag. The menus (generated from the catalog), keyboard shortcuts, Actions palette, CLI (figcraft-cli run), JSON control channel (--control <port>) and MCP server all dispatch the same ids, so agents can do anything a person can; WebAssembly plugins call them too, within their manifest's permissions. Commands never open dialogs themselves; they request UI, and programmatic callers drop those requests. cargo xtask parity measures the catalog's coverage (parity-checklist.md).

Rendering

The CPU renderer is the single source of pixels for the canvas, exports and the browser. The desktop canvas renders on a worker thread at the device pixel ratio and keeps its last image, re-rendering only the region a pan uncovers or an edit touches; overlays (selection, handles, guides, labels) are drawn by egui on top. A seeded random walk checks the retained canvas against full renders. SVG and PDF export walk the same scene and embed rasters where those formats can't express an effect.

File I/O

.figcraft is the native format (atomic saves, autosave checkpoints; the desktop app keeps recovery copies of unsaved documents that reopen after a crash or a forced quit). Imports: REST API file JSON with variables and images, SVG, raster images, clipboard content. Exports: PNG, JPG, WebP, SVG, PDF, code. There is no .fig reader yet (file-format-parity.md).

Robustness

Workspace lints deny unwrap, expect, panic! and friends in shipped code; unsafe_code is forbidden. figcraft_engine::guard turns a panicking command into an error and rolls the document back; the desktop app also guards each UI frame. Junk-parameter sweeps run every command with bad input.

Revision history

Date Change Summary
2026-10-11 minor collab-net hosts through one hub for the app's sessions and the standalone server; added the figcraft-server app
2026-10-10 minor Merged main after #101–#103: WASM plugins (plugins area 0% → 35% breadth, 20% ready; ecosystem 5% → 20%) and the multiplayer core without networking (multiplayer 5% → 15% breadth, 5% ready; collaboration 8% → 12%); menu breadth 97.5% → 98.5% (200/203); ready for real work ~46% → ~47%; full parity 420–790 h → 390–745 h; beta 210–380 h → 200–365 h. Fixed the stated weight sums (areas 1–16 sum to 94, total 113; percentages were already computed with those)
2026-10-10 major Created from the code as of PR #99