OpenUI
OpenUI is a full-stack Generative UI framework — a compact streaming-first language, a React runtime with built-in component libraries, and ready-to-use chat interfaces — that is up to 67% more token-efficient than JSON.
Most AI applications are limited to returning text (as markdown) or rendering pre-built UI responses. Markdown isn't interactive, and pre-built responses are rigid (they don't adapt to the context of the conversation).
Generative UI fundamentally changes this relationship. Instead of merely providing content, the AI composes the interface itself. It dynamically selects, configures, and composes components from a predefined library to create a purpose-built interface tailored to the user's immediate request, be it an interactive chart, a complex form, or a multi-tab dashboard.
OpenUI is the Generative UI framework powering Mitigate's chat interface. To enable it, select OpenUI as the Output Format in your workspace settings.
Examples
E-commerce
root = Stack([carousel])carousel = Carousel([slide1, slide2, slide3, slide4, slide5], "card")slide1 = [CardHeader("Wireless Headphones", "Premium sound quality"), Image("Wireless Headphones", "/docs/openui/wireless-headphones.png"), form1]form1 = Form("product1", btn1, [qty1])qty1 = FormControl("Quantity", Input("qty1", "Enter quantity", "number", { required: true, min: 0, max: 100 }))btn1 = Buttons([Button("Add to Cart", { type: "continue_conversation", context: "Add Wireless Headphones to cart" }, "primary")])slide2 = [CardHeader("Bluetooth Speaker", "Portable audio"), Image("Bluetooth Speaker", "/docs/openui/bluetooth-speaker.png"), form2]form2 = Form("product2", btn2, [qty2])qty2 = FormControl("Quantity", Input("qty2", "Enter quantity", "number", { required: true, min: 0, max: 100 }))btn2 = Buttons([Button("Add to Cart", { type: "continue_conversation", context: "Add Bluetooth Speaker to cart" }, "primary")])slide3 = [CardHeader("USB-C Hub", "Multi-port connectivity"), Image("USB-C Hub", "/docs/openui/usb-c-hub.png"), form3]form3 = Form("product3", btn3, [qty3])qty3 = FormControl("Quantity", Input("qty3", "Enter quantity", "number", { required: true, min: 0, max: 100 }))btn3 = Buttons([Button("Add to Cart", { type: "continue_conversation", context: "Add USB-C Hub to cart" }, "primary")])slide4 = [CardHeader("Mechanical Keyboard", "Tactile typing experience"), Image("Mechanical Keyboard", "/docs/openui/mechanical-keyboard.png"), form4]form4 = Form("product4", btn4, [qty4])qty4 = FormControl("Quantity", Input("qty4", "Enter quantity", "number", { required: true, min: 0, max: 100 }))btn4 = Buttons([Button("Add to Cart", { type: "continue_conversation", context: "Add Mechanical Keyboard to cart" }, "primary")])slide5 = [CardHeader("Laptop Stand", "Ergonomic design"), Image("Laptop Stand", "/docs/openui/laptop-stand.png"), form5]form5 = Form("product5", btn5, [qty5])qty5 = FormControl("Quantity", Input("qty5", "Enter quantity", "number", { required: true, min: 0, max: 100 }))btn5 = Buttons([Button("Add to Cart", { type: "continue_conversation", context: "Add Laptop Stand to cart" }, "primary")])Kanban Board
root = Stack([header, board])header = Card([headerButtons], "clear", "row", "none", "center", "between")headerButtons = Buttons([addBtn, filterBtn], "row")addBtn = Button("+ Add Task", { type: "continue_conversation", context: "Add a new task to the kanban board" }, "primary", "normal", "small")filterBtn = Button("Filter", { type: "continue_conversation", context: "Filter tasks on the kanban board" }, "secondary", "normal", "small")board = Stack([todoCol, inProgressCol, doneCol], "row", "m", "start")todoCol = Card([todoHeader, todoSep, todo1, todo2, todo3, todo4], "sunk", "column", "s")todoHeader = Stack([todoLabel, todoBadge], "row", "s", "center", "between")todoLabel = TextContent("📋 To Do", "small-heavy")todoBadge = Tag("4", "", "sm", "neutral")todoSep = Separator("horizontal")todo1 = Card([todo1Header, todo1Tags, todo1Footer], "card", "column", "xs")todo1Header = CardHeader("Redesign login page", "Update UI to match new brand guidelines")todo1Tags = TagBlock(["UI", "Design"])todo1Footer = Buttons([Button("Move →", { type: "continue_conversation", context: "Move 'Redesign login page' to In Progress" }, "tertiary", "normal", "extra-small")], "row")todo2 = Card([todo2Header, todo2Tags, todo2Footer], "card", "column", "xs")todo2Header = CardHeader("Set up CI/CD pipeline", "Automate build and deploy process")todo2Tags = TagBlock(["DevOps", "Backend"])todo2Footer = Buttons([Button("Move →", { type: "continue_conversation", context: "Move 'Set up CI/CD pipeline' to In Progress" }, "tertiary", "normal", "extra-small")], "row")todo3 = Card([todo3Header, todo3Tags, todo3Footer], "card", "column", "xs")todo3Header = CardHeader("Write API documentation", "Document all REST endpoints")todo3Tags = TagBlock(["Docs", "API"])todo3Footer = Buttons([Button("Move →", { type: "continue_conversation", context: "Move 'Write API documentation' to In Progress" }, "tertiary", "normal", "extra-small")], "row")todo4 = Card([todo4Header, todo4Tags, todo4Footer], "card", "column", "xs")todo4Header = CardHeader("Accessibility audit", "Ensure WCAG 2.1 compliance")todo4Tags = TagBlock(["QA", "Design"])todo4Footer = Buttons([Button("Move →", { type: "continue_conversation", context: "Move 'Accessibility audit' to In Progress" }, "tertiary", "normal", "extra-small")], "row")inProgressCol = Card([inProgressHeader, inProgressSep, inp1, inp2, inp3], "sunk", "column", "s")inProgressHeader = Stack([inProgressLabel, inProgressBadge], "row", "s", "center", "between")inProgressLabel = TextContent("🔄 In Progress", "small-heavy")inProgressBadge = Tag("3", "", "sm", "info")inProgressSep = Separator("horizontal")inp1 = Card([inp1Header, inp1Tags, inp1Footer], "card", "column", "xs")inp1Header = CardHeader("User authentication module", "JWT-based auth with refresh tokens")inp1Tags = TagBlock(["Backend", "Security"])inp1Footer = Buttons([Button("← Back", { type: "continue_conversation", context: "Move 'User authentication module' back to To Do" }, "tertiary", "normal", "extra-small"), Button("Move →", { type: "continue_conversation", context: "Move 'User authentication module' to Done" }, "tertiary", "normal", "extra-small")], "row")inp2 = Card([inp2Header, inp2Tags, inp2Footer], "card", "column", "xs")inp2Header = CardHeader("Dashboard analytics", "Build charts and KPI widgets")inp2Tags = TagBlock(["Frontend", "Data"])inp2Footer = Buttons([Button("← Back", { type: "continue_conversation", context: "Move 'Dashboard analytics' back to To Do" }, "tertiary", "normal", "extra-small"), Button("Move →", { type: "continue_conversation", context: "Move 'Dashboard analytics' to Done" }, "tertiary", "normal", "extra-small")], "row")inp3 = Card([inp3Header, inp3Tags, inp3Footer], "card", "column", "xs")inp3Header = CardHeader("Mobile responsive layout", "Ensure all pages work on small screens")inp3Tags = TagBlock(["Frontend", "UI"])inp3Footer = Buttons([Button("← Back", { type: "continue_conversation", context: "Move 'Mobile responsive layout' back to To Do" }, "tertiary", "normal", "extra-small"), Button("Move →", { type: "continue_conversation", context: "Move 'Mobile responsive layout' to Done" }, "tertiary", "normal", "extra-small")], "row")doneCol = Card([doneHeader, doneSep, done1, done2, done3], "sunk", "column", "s")doneHeader = Stack([doneLabel, doneBadge], "row", "s", "center", "between")doneLabel = TextContent("✅ Done", "small-heavy")doneBadge = Tag("3", "", "sm", "success")doneSep = Separator("horizontal")done1 = Card([done1Header, done1Tags], "card", "column", "xs")done1Header = CardHeader("Project setup & scaffolding", "Repo, folder structure, and tooling")done1Tags = TagBlock(["DevOps", "Setup"])done2 = Card([done2Header, done2Tags], "card", "column", "xs")done2Header = CardHeader("Database schema design", "ERD and migration scripts")done2Tags = TagBlock(["Backend", "Database"])done3 = Card([done3Header, done3Tags], "card", "column", "xs")done3Header = CardHeader("Wireframes approved", "All screens signed off by stakeholders")done3Tags = TagBlock(["Design", "Planning"])Layout
Stack
root = Stack([a, b, c], "row", "m")a = TextContent("Item 1")b = TextContent("Item 2")c = TextContent("Item 3")Tabs
root = Tabs([tabReact, tabVue])tabReact = TabItem("react", "React", reactContent)tabVue = TabItem("vue", "Vue", vueContent)reactContent = [TextContent("React is a library by Meta for building UIs."), Callout("info", "Note", "React uses JSX syntax.")]vueContent = [TextContent("Vue is a progressive framework by Evan You."), Callout("success", "Tip", "Vue has a gentle learning curve.")]Accordion
root = Accordion([acc1, acc2, acc3])acc1 = AccordionItem("getting-started", "Getting Started", [TextContent("Follow the installation guide to get started.")])acc2 = AccordionItem("configuration", "Configuration", [TextContent("Configure your project settings in the config file.")])acc3 = AccordionItem("deployment", "Deployment", [TextContent("Deploy your app to production with a single command.")])Steps
root = Steps([step1, step2, step3])step1 = StepsItem("Install", "Run npm install to add dependencies.")step2 = StepsItem("Configure", "Set up your configuration file.")step3 = StepsItem("Deploy", "Push to production.")Carousel
root = Carousel([[slide1], [slide2], [slide3]])slide1 = TextContent("Slide 1: Welcome to OpenUI")slide2 = TextContent("Slide 2: Build beautiful interfaces")slide3 = TextContent("Slide 3: Ship with confidence")Separator
root = Stack([above, sep, below])above = TextContent("Content above")sep = Separator()below = TextContent("Content below")Content
Card
root = Card([header, body])header = CardHeader("Example Card", "A subtitle for the card")body = TextContent("This is card content with a description.")TextContent
root = Stack([t1, t2, t3])t1 = TextContent("Large Heavy Text", "large-heavy")t2 = TextContent("Medium text with regular weight", "medium")t3 = TextContent("Default sized text content")MarkDownRenderer
root = MarkDownRenderer("# Heading\n\nA paragraph with **bold** and *italic* text.\n\n- Item one\n- Item two\n- Item three\n\n```js\nconsole.log(\"hello\")\n```")Callout
root = Stack([c1, c2, c3])c1 = Callout("info", "Information", "This is an informational callout.")c2 = Callout("success", "Success", "Operation completed successfully.")c3 = Callout("warning", "Warning", "Please review before proceeding.")TextCallout
root = Stack([c1, c2])c1 = TextCallout("info", "Info", "A short informational message.")c2 = TextCallout("warning", "Warning", "Be careful with this action!")Image
root = Image("Landscape image", "/docs/openui/landscape-imageblock.png")ImageBlock
root = ImageBlock("/docs/openui/landscape-imageblock.png", "A captioned image")ImageGallery
root = ImageGallery([{ src: "/docs/openui/gallery-photo-1.png", alt: "Photo 1" }, { src: "/docs/openui/gallery-photo-2.png", alt: "Photo 2" }, { src: "/docs/openui/gallery-photo-3.png", alt: "Photo 3" }])CodeBlock
root = CodeBlock("javascript", "const greeting = \"Hello, World!\";\nconsole.log(greeting);\n\nfunction add(a, b) {\n return a + b;\n}")Tables
Table
root = Table(cols, rows)cols = [Col("Language", "string"), Col("Users (M)", "number"), Col("Year", "number")]rows = [["Python", 15.7, 1991], ["JavaScript", 14.2, 1995], ["Java", 12.1, 1995], ["TypeScript", 8.5, 2012], ["Go", 5.2, 2009]]Charts
BarChart
Grouped
root = BarChart(labels, [s1, s2], "grouped")labels = ["Oct", "Nov", "Dec"]s1 = Series("Product A", [120, 150, 180])s2 = Series("Product B", [90, 110, 140])Stacked
root = BarChart(labels, [s1, s2], "stacked")labels = ["Oct", "Nov", "Dec"]s1 = Series("Product A", [120, 150, 180])s2 = Series("Product B", [90, 110, 140])LineChart
Linear
root = LineChart(labels, [s1, s2], "linear")labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]s1 = Series("Visitors", [1200, 1900, 3000, 5000, 4200, 5500])s2 = Series("Page Views", [3600, 5700, 9000, 15000, 12600, 16500])Natural
root = LineChart(labels, [s1, s2], "natural")labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]s1 = Series("Visitors", [1200, 1900, 3000, 5000, 4200, 5500])s2 = Series("Page Views", [3600, 5700, 9000, 15000, 12600, 16500])Step
root = LineChart(labels, [s1, s2], "step")labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]s1 = Series("Visitors", [1200, 1900, 3000, 5000, 4200, 5500])s2 = Series("Page Views", [3600, 5700, 9000, 15000, 12600, 16500])AreaChart
Linear
root = AreaChart(labels, [s1, s2], "linear")labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]s1 = Series("Visitors", [1200, 1900, 3000, 5000, 4200, 5500])s2 = Series("Page Views", [3600, 5700, 9000, 15000, 12600, 16500])Natural
root = AreaChart(labels, [s1, s2], "natural")labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]s1 = Series("Visitors", [1200, 1900, 3000, 5000, 4200, 5500])s2 = Series("Page Views", [3600, 5700, 9000, 15000, 12600, 16500])Step
root = AreaChart(labels, [s1, s2], "step")labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]s1 = Series("Visitors", [1200, 1900, 3000, 5000, 4200, 5500])s2 = Series("Page Views", [3600, 5700, 9000, 15000, 12600, 16500])RadarChart
root = RadarChart(labels, [s1, s2])labels = ["Frontend", "Backend", "DevOps", "Design", "Testing"]s1 = Series("Alice", [90, 70, 60, 80, 75])s2 = Series("Bob", [60, 90, 80, 50, 85])HorizontalBarChart
Grouped
root = HorizontalBarChart(labels, [s1, s2], "grouped")labels = ["Alice", "Bob", "Carol", "Dave"]s1 = Series("Tasks Completed", [42, 38, 55, 29])s2 = Series("Tasks Pending", [8, 12, 5, 21])Stacked
root = HorizontalBarChart(labels, [s1, s2], "stacked")labels = ["Alice", "Bob", "Carol", "Dave"]s1 = Series("Tasks Completed", [42, 38, 55, 29])s2 = Series("Tasks Pending", [8, 12, 5, 21])PieChart
Pie
root = PieChart([s1, s2, s3, s4], "pie")s1 = Slice("Chrome", 65)s2 = Slice("Safari", 18)s3 = Slice("Firefox", 10)s4 = Slice("Other", 7)Donut
root = PieChart([s1, s2, s3, s4], "donut")s1 = Slice("Chrome", 65)s2 = Slice("Safari", 18)s3 = Slice("Firefox", 10)s4 = Slice("Other", 7)RadialChart
root = RadialChart([s1, s2, s3])s1 = Slice("Tasks", 78)s2 = Slice("Bugs", 92)s3 = Slice("Reviews", 65)SingleStackedBarChart
root = SingleStackedBarChart([s1, s2, s3])s1 = Slice("Completed", 60)s2 = Slice("In Progress", 25)s3 = Slice("Pending", 15)ScatterChart
root = ScatterChart([series1], "Height (cm)", "Weight (kg)")series1 = ScatterSeries("Adults", [p1, p2, p3, p4, p5])p1 = Point(165, 60)p2 = Point(170, 65)p3 = Point(175, 72)p4 = Point(180, 80)p5 = Point(185, 85)Forms
Form
root = Form("contact", btns, [nameField, emailField, countryField, msgField])nameField = FormControl("Name", Input("name", "Your name", "text", { required: true, minLength: 2 }))emailField = FormControl("Email", Input("email", "you@example.com", "email", { required: true, email: true }))countryField = FormControl("Country", Select("country", countryOpts, "Select...", { required: true }))msgField = FormControl("Message", TextArea("message", "Tell us more...", 4, { required: true, minLength: 10 }))countryOpts = [SelectItem("us", "United States"), SelectItem("uk", "United Kingdom"), SelectItem("de", "Germany")]btns = Buttons([Button("Submit", { type: "continue_conversation" }, "primary"), Button("Cancel", { type: "continue_conversation" }, "secondary")])FormControl
root = FormControl("Username", Input("username", "Enter your username", "text", { required: true }))Label
root = Label("Email address")Input
root = Stack([i1, i2, i3])i1 = FormControl("Text", Input("text", "Enter text", "text"))i2 = FormControl("Email", Input("email", "you@example.com", "email"))i3 = FormControl("Password", Input("password", "Enter password", "password"))TextArea
root = FormControl("Description", TextArea("description", "Write a description...", 4))Select
root = FormControl("Country", Select("country", opts, "Choose a country..."))opts = [SelectItem("us", "United States"), SelectItem("uk", "United Kingdom"), SelectItem("de", "Germany"), SelectItem("fr", "France")]DatePicker
root = FormControl("Date", DatePicker("date", "single"))Slider
root = FormControl("Volume", Slider("volume", "continuous", 0, 100))CheckBoxGroup
root = FormControl("Interests", CheckBoxGroup("interests", [c1, c2, c3]))c1 = CheckBoxItem("Frontend", "Frontend development", "frontend")c2 = CheckBoxItem("Backend", "Backend development", "backend")c3 = CheckBoxItem("DevOps", "DevOps engineering", "devops")RadioGroup
root = FormControl("Plan", RadioGroup("plan", [r1, r2, r3]))r1 = RadioItem("Free", "Basic features", "free")r2 = RadioItem("Pro", "Advanced features", "pro")r3 = RadioItem("Enterprise", "Full access", "enterprise")SwitchGroup
root = FormControl("Settings", SwitchGroup("settings", [s1, s2]))s1 = SwitchItem("Enable notifications", "Receive alerts", "notifications")s2 = SwitchItem("Dark mode", "Use dark theme", "darkMode")Buttons
Button
Large
root = Buttons([b1, b2, b3, b4])b1 = Button("Primary", { type: "continue_conversation" }, "primary", "normal", "large")b2 = Button("Secondary", { type: "continue_conversation" }, "secondary", "normal", "large")b3 = Button("Tertiary", { type: "continue_conversation" }, "tertiary", "normal", "large")b4 = Button("Destructive", { type: "continue_conversation" }, "primary", "destructive", "large")Medium
root = Buttons([b1, b2, b3, b4])b1 = Button("Primary", { type: "continue_conversation" }, "primary", "normal", "medium")b2 = Button("Secondary", { type: "continue_conversation" }, "secondary", "normal", "medium")b3 = Button("Tertiary", { type: "continue_conversation" }, "tertiary", "normal", "medium")b4 = Button("Destructive", { type: "continue_conversation" }, "primary", "destructive", "medium")Small
root = Buttons([b1, b2, b3, b4])b1 = Button("Primary", { type: "continue_conversation" }, "primary", "normal", "small")b2 = Button("Secondary", { type: "continue_conversation" }, "secondary", "normal", "small")b3 = Button("Tertiary", { type: "continue_conversation" }, "tertiary", "normal", "small")b4 = Button("Destructive", { type: "continue_conversation" }, "primary", "destructive", "small")Extra Small
root = Buttons([b1, b2, b3, b4])b1 = Button("Primary", { type: "continue_conversation" }, "primary", "normal", "extra-small")b2 = Button("Secondary", { type: "continue_conversation" }, "secondary", "normal", "extra-small")b3 = Button("Tertiary", { type: "continue_conversation" }, "tertiary", "normal", "extra-small")b4 = Button("Destructive", { type: "continue_conversation" }, "primary", "destructive", "extra-small")Data Display
TagBlock
root = TagBlock(["React", "TypeScript", "Node.js", "Python"])Tag
Large
root = Stack([t1, t2, t3, t4, t5], "row", "s")t1 = Tag("Neutral", undefined, "lg", "neutral")t2 = Tag("Info", undefined, "lg", "info")t3 = Tag("Success", undefined, "lg", "success")t4 = Tag("Warning", undefined, "lg", "warning")t5 = Tag("Danger", undefined, "lg", "danger")Medium
root = Stack([t1, t2, t3, t4, t5], "row", "s")t1 = Tag("Neutral", undefined, "md", "neutral")t2 = Tag("Info", undefined, "md", "info")t3 = Tag("Success", undefined, "md", "success")t4 = Tag("Warning", undefined, "md", "warning")t5 = Tag("Danger", undefined, "md", "danger")Small
root = Stack([t1, t2, t3, t4, t5], "row", "s")t1 = Tag("Neutral", undefined, "sm", "neutral")t2 = Tag("Info", undefined, "sm", "info")t3 = Tag("Success", undefined, "sm", "success")t4 = Tag("Warning", undefined, "sm", "warning")t5 = Tag("Danger", undefined, "sm", "danger")