Server-driven UI

Your platform decides the screen. Blueprint is how it ships.

You already have a platform that decides which screen a user sees next. Blueprint turns that decision into a rendered screen — a portable JSON contract your Builder authors, your backend fills with data, and your frontend renders as real components. You keep the orchestration, the data, and the logic; you never write a UI interpreter or ship one to the browser.

no interpreter · no eval · your orchestration, untouched

The problem

You want screens from the server. You don’t want to build the interpreter.

Every usual way to render UI from your backend forces a trade a platform team can’t make.

Ship an interpreter

Server config that gets eval'd in the browser: a CSP hole, an audit you'll lose, a security review you won't pass.

Roll your own format

Invent a JSON-to-UI schema and a renderer — then maintain both forever. Months of undifferentiated work you now own.

Rent a hosted builder

A vendor owns your rendering, your data path, and your bill — and you can’t run it where your data lives.

Where it fits

You keep the orchestration. Blueprint is the contract, filled and rendered.

You don’t hand-write the UI contract — the Builder generates it. Your backend just reads it. Your frontend renders it. Your orchestration never changes.

Yours — the platform
  • Which screen, when, and for whom
  • Routing & business logic
  • Your data & auth
  • The response envelope you shape
Blueprint — three bounded pieces
  • The contract — a portable JSON screen, authored in the Builder (not by hand)
  • The SDK — fills the contract with your data, server-side, no eval
  • The runtime — renders it as real components, on your design system
Read it. Render it.

Your backend reads the contract. Your frontend renders it.

Two thin libraries you drop into the stack you already run. Everything between them is your envelope, your call.

server/onboarding.ts · your backend
// your platform already decided the screen
const file = await store.load(`${screen}.json`)
const ui = load(file)

// bind your data, server-side
await ui.resolveAll(yourResolver)

// return it in your own envelope
return res.json({ user, screen: ui.toContract() })
app/onboarding.tsx · your frontend
// your platform picked the onboarding step
// your app fetched the envelope from your API

const { screen } = await api.get(
  `/onboarding/${step}`,
)

// render it — no eval, your real components
return <DashBlueprint {...screen} lib="tw" />
In practice

A fintech onboarding, screen by screen.

1

Your platform decides: “this user is at the KYC step.” Routing and logic are yours — nothing about that moves.

2

Your backend loads kyc.contract.json (authored in the Builder), binds the country list from your DB, and returns it in your envelope.

3

Your frontend renders the KYC screen as real components, on your design system — no eval, nothing to interpret.

4

Need to change the screen? Edit the contract in the Builder — no frontend deploy. Your orchestration, routing and logic never moved.

The difference

A server-driven UI you drive, not a vendor.

The backend controls the screen, and you control the backend. No interpreter ships to the browser, no vendor sits in your render path, and the contract is a file you own — which is exactly why a fintech can put it on the critical path. See the regulated case

One core, more surfaces

The pieces that make it work.

The Builder

Author the contract visually and export portable JSON.

Learn more

The SDK

Your backend fills the contract with your data, in any language.

Learn more

The runtime

Renders the envelope as real components on your design system.

Learn more
Get started

Drive the flow. Own the render.