resolving profile — anon:7f3a…
composing from 9 registered components…
validated — 0 errors
Open source — Apache-2.0a vision of personalized product designself-hosted · zero runtime deps · v0.1-alpha(dynui.dev)

The same app.A differentscreen for theindividual user.

DynUI composes real, registered components into a screen per user driven by behavior, consent, and experiments. Your design system is the boundary. Dynamic, personalized UI.

scroll — the vocabulary is below ↓

Compose.Validate.Then render.

A deterministic engine — or an optional model provider — emits a server-driven UI tree from your component manifest. A strict validator is the render gate. Consent and experiments are enforced in code, not prompts.

$ npm run demo — 22 rules, 0 errors, fails closed
( the idea )

A design tool defines the vocabulary. A model composes a screen per user. A validator refuses anything off-contract — so the model never free-draws.

( the proof )

One activity.Three screens.

The same morning run, rendered for three different people — composed from the same nine components, never the same way.

validateRenderableTree — 22 rules, 0 errors, every screen

activity-header
Morning Run · 10.2 km
recovery-ring
72
Recovery — ready to push
strain-bar
14.2 / 21
hrv-trend
58ms ↑
splits-table
1 km4:32
2 km4:28
3 km4:25 · PB
greeting-card
Good morning, Alex
A gentle day works in your favor.
sleep-card
7h 42m
Sleep — quality 86%
readiness-message
Fully recovered. Yesterday's walk lowered your stress baseline.
steps-ring
6,412 / 8,000
feed-card
SM
Sam — Hill Repeats
12 kudos · 3 comments
leaderboard
1 · Priya48.2 km
2 · You46.9 km
3 · Sam44.1 km
challenge-card
82%
June Distance Challenge
feed-card
PR
Priya — Track Intervals
9 kudos · you gave kudos

The tree isthe contract.

Providers emit JSON, never markup. Unknown types, oversized trees, consent violations, and ungated experiments are rejected before render — then the fallback composes deterministically.

$ PROVIDER=anthropic npm run demo — first try valid, fallback unused

{
"type": "screen", "surface": "activity-detail",
"generatedFor": { "anonId": "7f3a…", "segment": "performance" },
"children": [
{ "type": "recovery-ring", "data": { "score": 72 } },
{ "type": "hrv-trend", "variant": "7-day" },
{ "type": "splits-table", "variant": "dense" }
]
}
 
validateRenderableTree — 22 rules, 0 errors
rendered in 4ms — cacheKey m1.2:activity:performance
( how it works — 01→06 )
01ContractDesigners annotate components in Figma with a behavioral contract — surfaces, data, audience, accessibility.@dynui/figma
02ManifestThe registered vocabulary. Variants, slots, required data, experiment gates. Linted and versioned.@dynui/contracts
03ProfileBehavior resolves to a segment. PII stays on your side of the adapter — the engine sees signals, not people.@dynui/profile
04ComposeA model — backed by a deterministic engine — assembles a UI tree from eligible components only.@dynui/generate
05ValidateThe render gate. Twenty-two rules. Off-contract trees never reach a user, from any provider.@dynui/validate
06RenderYour renderer maps the tree to real components — measured per component, canaried per experiment.@dynui/experiments
( the numbers )
1
deterministic fallback behind model calls — failures close safely
22
validation rules between generation and render
10
packages, zero runtime dependencies
3
screens from one activity — performance, recovery, social
( the toolkit — 10 packages )