Prototype strategy: core, controller, renderers

Use this template when a prototype is interaction-heavy, domain-typed, and likely to ship in more than one UI host.

Claim

Do not aim to auto-convert full UI across ecosystems. Share meaning and behavior — domain IR plus a headless controller — and hand-write thin views per host.

Layers

Layer Owns

Core

Domain IR: types, validation, evaluation/replay, serialize/deserialize

Controller

Headless interaction state machine (Zag.js / XState-shaped): selection, insert palettes, drag phases, keyboard paths, undo

Renderers

DOM first (a11y, clarity, theme); canvas/zoomable later for deep nesting

Thin wrappers

React / Solid / Vue / Web Components — bind host reactivity ↔ controller, pick renderer

Design rules

  1. Core has no DOM — legality and evaluation are framework-agnostic

  2. Controller mutates through core APIs — no shadow IR in a wrapper

  3. One IR, many renderers — same map semantics in a list or on a zoom plane

  4. Wrappers stay thin — logic that grows belongs in core or controller

  5. Export meaning — serialized IR + evaluation story, not pixel-perfect chrome

What not to promise

  • Universal UI export — historical UI languages (UIML, XUL, QML) won as runtimes, not exporters

  • Prior art covers parts: Zag/Ark (behavior), Mitosis/Stencil (structure), Web Components (encapsulation), XState (machines), node editors (canvas), Power Automate (product proof for visual pipelines — closed runtime)

Compose those parts on purpose. See Fundamental contexts for the broader map.

Proving ground