Maelstrom orchestrates your UI.
An open-source library for AI-orchestrated UI. You author your components as vessels — their states, actions, and size hints — and a model arranges, resizes, and triggers them in real time, around the user's intent.
How It Works
Describe the pieces. Maelstrom handles the orchestration.
Describe Your Components
Each component gets a Vessel — a declaration that tells the AI everything it needs to know: available states, actions it can trigger, and minimum size requirements.
import { defineVessel } from "@maelstrom-co/protocol";
export const ordersVessel = defineVessel({
id: "orders",
name: "Orders Panel",
description: "Displays a list of orders",
defaultVariant: "list",
variants: {
list: {
props: {},
minSize: { width: 4, height: 3 },
actions: [
{ name: "selectOrder", transitionsTo: "details" },
],
},
details: {
props: {},
minSize: { width: 6, height: 5 },
},
},
}); Create Your Instance
Wire vessels to components and create a typed Maelstrom instance. One factory call gives you everything — Provider, Chart, and fully typed hooks.
import { createMaelstrom, vessel } from "@maelstrom-co/react";
import { ordersVessel } from "./orders.vessel";
import OrdersComponent from "./OrdersComponent";
const ordersEntry = vessel(ordersVessel, OrdersComponent);
export const m = createMaelstrom({
vessels: [ordersEntry],
}); User Intent
Voice or text — same API. The user says what they want, and the AI figures out the rest.
import { m } from "./maelstrom";
function Dashboard() {
const { processIntent } = m.useMaelstrom();
// "Show me pending orders"
// "Open order 1847"
await processIntent(userMessage);
} Engine Decides
The AI sees your entire UI — every vessel, every state, and all the space it has to work with. It returns a precise plan: which actions to fire and where to place each component.
// Engine returns actions + layout
{
userMessage: "Opening order #1847",
executionPlan: [
{ instanceId: "orders-1", action: "selectOrder" }
],
layout: {
type: "tiling",
tree: ["orders-1"],
instances: [{ variant: "details" }],
},
}; UI Responds
Components transition, the layout shifts, everything updates — instantly and type-safe. Your code stays predictable while the AI orchestrates the experience.
import { ok } from "@maelstrom-co/protocol";
import { m } from "./maelstrom";
function OrdersVessel({ instanceId }) {
m.useActions("orders", instanceId, {
selectOrder: async ({ orderId }) => {
loadOrder(orderId);
return ok(undefined);
},
});
return <OrdersPanel />;
} import { defineVessel } from "@maelstrom-co/protocol";
export const ordersVessel = defineVessel({
id: "orders",
name: "Orders Panel",
description: "Displays a list of orders",
defaultVariant: "list",
variants: {
list: {
props: {},
minSize: { width: 4, height: 3 },
actions: [
{ name: "selectOrder", transitionsTo: "details" },
],
},
details: {
props: {},
minSize: { width: 6, height: 5 },
},
},
}); import { createMaelstrom, vessel } from "@maelstrom-co/react";
import { ordersVessel } from "./orders.vessel";
import OrdersComponent from "./OrdersComponent";
const ordersEntry = vessel(ordersVessel, OrdersComponent);
export const m = createMaelstrom({
vessels: [ordersEntry],
}); import { m } from "./maelstrom";
function Dashboard() {
const { processIntent } = m.useMaelstrom();
// "Show me pending orders"
// "Open order 1847"
await processIntent(userMessage);
} // Engine returns actions + layout
{
userMessage: "Opening order #1847",
executionPlan: [
{ instanceId: "orders-1", action: "selectOrder" }
],
layout: {
type: "tiling",
tree: ["orders-1"],
instances: [{ variant: "details" }],
},
}; import { ok } from "@maelstrom-co/protocol";
import { m } from "./maelstrom";
function OrdersVessel({ instanceId }) {
m.useActions("orders", instanceId, {
selectOrder: async ({ orderId }) => {
loadOrder(orderId);
return ok(undefined);
},
});
return <OrdersPanel />;
} See It In Action
This is @maelstrom-co/react running live,
not a mockup. The AI responses are pre-recorded so you see a consistent demo.
Want to explore it yourself?
Try the PlaygroundHelp shape Maelstrom
We are inviting React engineers to test the Maelstrom library in real projects and help us prepare it for public release.
Build something real
Use Maelstrom in your own React project and test it against real product requirements.
Work with the maintainers
Share bugs, rough edges, and missing capabilities directly with the team building the library.
Shape the open source API
Help us make the developer experience solid before the first public release.
Become a beta tester
Join our Discord community for the beta role and instructions to request GitHub access.