Handbook
Architecture
Edges are pluggable. The core is platform-agnostic TypeScript.
React / Scene API
→
Node graph
→
dirty · layout · paint · hit
→
DrawOp[]
→
Canvas2D / …
Layers
Frontend
limn/react — custom reconciler; HTML tags + className + style objects/strings.
createScene — imperative create/add/setStyle without React.
- Host ops map DOM-ish events onto the scene (pointer, scroll, focus).
Core
Node scene graph with style, layout box, transform.
- Three dirty bits drive scheduler passes.
- Layout: flex, grid, table, inline/block, absolute/sticky, …
- Paint: backgrounds, borders, text, SVG, filters → abstract draw ops.
- Hit-test walks the same boxes/transforms used for paint.
Backend
createCanvas2DBackend — primary host today.
- Interface is consume-DrawOp, not embed-ctx in core.
Source map
| Path | Owns |
src/core/ | Node, dirty, style, scheduler, animation |
src/layout/ | flex, grid, table, text, transform |
src/paint/ | paint walk, gradient, dirty-rect |
src/event/ | dispatch, hit-test, text select |
src/frontend/ | React, Scene, stylesheet, host-ops |
src/backend/ | Canvas2D + host types |
src/svg/ | SVG elements, path, SMIL subset |
Mental model
Treat limn as a small browser kernel for canvas hosts: cascade → layout → paint → hit,
with explicit dirty invalidation instead of a full DOM implementation.