Your users just describe the page they want, and AI builds it for them on the spot. You stay in control: it can only use the data and actions you allow.
Declare the data and actions your app allows in plain natural language. Pass the real implementations; they remain completely private to your server.
Your users just say how they want the page to look. No settings to dig through, no templates to memorize—Veneer invents the layout on the fly.
“Show me a board of my tasks grouped by due date, with high priority tasks at the top”
Every generated element is loaded inside a read-only iframe sandbox. The model can style anything, but can only invoke the native functions you exposed.
Below is an ordinary task app built with the veneer-sdk. Click the button in the corner and tell the AI how you want it to look. Everything it invents runs inside the sandboxed canvas.
// 1) Declare what the AI may see and do. This registry is the contract. const registry = { dataSources: [ { id: 'tasks', description: "The user's tasks.", fields: [ { name: 'id', type: 'string' }, { name: 'title', type: 'string' }, { name: 'status', type: '"todo" | "doing" | "done"' }, ] }, ], actions: [ { id: 'createTask', description: 'Create a task.' }, { id: 'updateTask', description: "Update a task's fields." }, { id: 'archiveTask', description: 'Archive a task.' }, // no deleteTask → no generated UI can ever delete ], }; // 2) Pass the REAL implementations + live data. Veneer wires the rest. const actions = { createTask: ({ title }) => setTasks(...), updateTask: ({ id, ...changes }) => setTasks(...), archiveTask: ({ id }) => setTasks(...), }; // 3) Drop in three components. The frame is the sandbox; the chat redesigns it. <VeneerProvider registry={registry} actions={actions} data={{ tasks }}> <VeneerFrame style={{ height: 560 }} /> <VeneerChat /> </VeneerProvider>
A manager wants a dashboard; a teammate just wants today’s checklist. Instead of building both, you ship the pieces — and each person shapes the page to fit how they work, while you stay in control of what’s possible.
Change the UI to your liking with AI
Opaque origin, no network, validated bridge — three independent layers.
A typed, described capability surface the model composes against.
Each person's layout is saved to their own browser. Nobody else sees it.
A provider, a frame, a chat. Three components and you're live. (Note: Package naming is a placeholder subject to change on release.)
One endpoint returns { code, reply }. Use any LLM you like.
The model can write anything. It still can’t do anything you didn’t allow. Three independent layers each block the same impossible action — at once.
sandbox="allow-scripts"No allow-same-origin, so the frame runs at an opaque origin: zero access to the parent’s cookies, localStorage, or DOM.
connect-src 'none'A strict CSP means generated code cannot fetch, XHR, open a WebSocket, or send a beacon. There is no path off the page.
registry.actions[id]The parent validates every { action, args } message against the registry and runs the real implementation only if the id is registered.
deleteTask→impossible by constructionNo deleteTask is registered, so even if generated code tried to delete via the network, the opaque origin blocks it, the CSP blocks it, and the bridge rejects it. Deletion fails on every layer.
No new backend, no source-code delivery, no rebuild. Register what your app can do in plain natural language, hand over the functions, and drop in the open-source package.
// 1. Register the capabilities your app exposes const registry = { dataSources: [ { id: 'tasks', description: 'The user’s tasks.' } ], actions: [ { id: 'createTask', description: 'Create a task.' }, { id: 'updateTask', description: 'Update a task.' }, // no deleteTask → generated UIs can never delete ], }; // 2. Pass the REAL implementations + live data <VeneerProvider registry={registry} actions={actions} data={{ tasks }}> <VeneerFrame style={{ height: 620 }} /> <VeneerChat /> </VeneerProvider>
That’s the whole integration. The registry is the contract; the sandbox is the guarantee.
MCP gives an AI model a typed, described set of capabilities to work with. Veneer is the same idea — just pointed at your interface.
Lets a model use the tools and data your systems expose — through one typed, described surface. It can only ever call what’s on it.
The exact same shape — but the surface is your interface. The model composes a real UI against your registered data and actions, inside a sandbox.
Yes — that’s the core of the product. Generated UI runs in an opaque-origin iframe with no same-origin access, a CSP that blocks all network, and a bridge that only runs actions you registered. Three independent layers, each load-bearing.
No. You keep your code and pass the real action implementations into the provider. The model only ever sees the registry’s plain-English descriptions and ids — never your implementations.
Whichever you want. Your generator endpoint returns { code, reply }, so you can wire up Gemini, Claude, or any other model. The demo uses gemini-2.5-flash.
Only if you registered an action for it. If there is no deleteTask in the registry, no generated UI can delete — by construction. The bridge rejects any unregistered action id.
Veneer is in private beta. Join the waitlist and we’ll send an invite as access opens up in batches — no spam, just your invite.
Rethink the last mile of software delivery. Ship the primitives — let your users design the interface they actually want. Join the waitlist for early access.