---
title: "Welcome to Prefab"
sidebarTitle: "Welcome"
description: The agentic frontend framework that even humans can use.
icon: hand-wave
mode: center
---
import _C_showcase from '/snippets/gen/welcome/code_showcase.mdx'

import { ComponentPreview } from '/snippets/component-preview.mdx'

<Warning>
*Don't panic. Prefab is under **extremely** active development. You probably shouldn't use it yet.*
</Warning>

**Prefab is a frontend framework with a Python DSL that compiles to JSON.** Describe a UI — layouts, forms, charts, data tables, full interactivity — and a bundled React renderer turns that JSON into a self-contained application.

Composing frontends in Python is ~~blasphemous~~ surprisingly natural. And because it's a JSON protocol, any source can produce a Prefab UI. Write one in Python, serve one as an [MCP App](/running/fastmcp), or let an agent generate one dynamically — no templates or predefined views required.

<div style={{
  margin: '0 clamp(-180px, calc(-12vw + 80px), 0px) 2rem',
  maxHeight: '800px',
  overflow: 'hidden',
  position: 'relative',
  maskImage: 'linear-gradient(to bottom, black 70%, transparent)',
  WebkitMaskImage: 'linear-gradient(to bottom, black 70%, transparent)',
}}>
<ComponentPreview bare id="showcase" json={{"view":{"cssClass":"gap-4","type":"Grid","minColumnWidth":"240px","children":[{"cssClass":"gap-4","type":"Column","children":[{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Register Towel"},{"type":"CardDescription","content":"The most important item in the galaxy"}]},{"type":"CardContent","children":[{"cssClass":"gap-3","type":"Column","children":[{"name":"input_22","type":"Input","inputType":"text","placeholder":"Towel name...","disabled":false,"readOnly":false,"required":false},{"name":"input_23","type":"Input","inputType":"text","placeholder":"Owner name...","disabled":false,"readOnly":false,"required":false},{"name":"select_9","type":"Select","placeholder":"Type...","size":"default","disabled":false,"required":false,"children":[{"type":"SelectOption","value":"bath","label":"Bath","selected":false,"disabled":false},{"type":"SelectOption","value":"beach","label":"Beach","selected":false,"disabled":false},{"type":"SelectOption","value":"interstellar","label":"Interstellar","selected":false,"disabled":false},{"type":"SelectOption","value":"micro","label":"Microfiber","selected":false,"disabled":false}]},{"name":"checkbox_12","type":"Checkbox","label":"Panic-proof certified","checked":true,"disabled":false,"required":false}]}]},{"type":"CardFooter","children":[{"cssClass":"gap-2","type":"Row","children":[{"type":"Dialog","title":"Towel Registered!","description":"Your towel has been added to the galactic registry.","children":[{"type":"Button","label":"Register","variant":"default","size":"default","disabled":false},{"type":"Condition","cases":[{"when":"{{ owner }}","children":[{"content":"Thanks, {{ input_23 }}. Don't forget to bring it.","type":"Text"}]}],"else":[{"content":"Anonymous, I see? Don't forget to bring it.","type":"Text"}]}]},{"type":"Button","label":"Cancel","variant":"outline","size":"default","disabled":false}]}]}]},{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Ship Status"}]},{"type":"CardContent","children":[{"cssClass":"gap-3","type":"Column","children":[{"cssClass":"items-center justify-between","type":"Row","children":[{"content":"heart-of-gold","type":"Text"},{"type":"HoverCard","openDelay":0,"closeDelay":200,"children":[{"type":"Badge","label":"In Orbit","variant":"default"},{"cssClass":"gap-2","type":"Column","children":[{"content":"heart-of-gold","type":"Text"},{"content":"Deployed 2h ago","type":"Muted"},{"type":"Progress","value":100.0,"min":0,"max":100.0,"variant":"default","indicatorClass":"bg-green-500"}]}]}]},{"type":"Progress","value":100.0,"min":0,"max":100.0,"variant":"default","indicatorClass":"bg-green-500"},{"cssClass":"items-center justify-between","type":"Row","children":[{"content":"vogon-poetry","type":"Text"},{"type":"Tooltip","content":"64% \u2014 ETA 12 min","delay":0,"children":[{"type":"Badge","variant":"secondary","children":[{"type":"Loader","variant":"spin","size":"sm"},{"content":"Deploying","type":"Text"}]}]}]},{"type":"Progress","value":64.0,"min":0,"max":100.0,"variant":"default"},{"cssClass":"items-center justify-between","type":"Row","children":[{"content":"bistromath","type":"Text"},{"type":"Tooltip","content":"Position 3 of 8","delay":0,"children":[{"type":"Badge","label":"Queued","variant":"outline"}]}]},{"type":"Progress","value":12.0,"min":0,"max":100.0,"variant":"default"},{"cssClass":"items-center justify-between","type":"Row","children":[{"content":"deep-thought","type":"Text"},{"type":"Tooltip","content":"Computing... 7.5 million years remaining","delay":0,"children":[{"type":"Loader","variant":"ios","size":"sm"}]}]}]}]}]},{"type":"Alert","variant":"info","icon":"book-open","children":[{"type":"AlertTitle","content":"The Guide Says"},{"type":"AlertDescription","content":"Prefab: Mostly Harmless."}]},{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Questions Answered"},{"type":"CardDescription","content":"Horizon agents this quarter"}]},{"type":"CardContent","children":[{"cssClass":"gap-2","type":"Column","children":[{"content":"1,842","type":"Large"},{"content":"+23% from last quarter","type":"Muted"},{"type":"Tooltip","content":"84% of quarterly goal","delay":0,"children":[{"type":"Progress","value":84.0,"min":0,"max":100.0,"variant":"default","indicatorClass":"bg-green-500"}]}]}]}]}]},{"cssClass":"gap-4","type":"Column","children":[{"type":"Card","children":[{"type":"CardHeader","children":[{"cssClass":"items-center justify-between","type":"Row","children":[{"type":"CardTitle","content":"Agent Queries"},{"name":"period","type":"Select","placeholder":"6 months","size":"default","disabled":false,"required":false,"children":[{"type":"SelectOption","value":"3m","label":"3 months","selected":false,"disabled":false},{"type":"SelectOption","value":"6m","label":"6 months","selected":false,"disabled":false},{"type":"SelectOption","value":"1y","label":"1 year","selected":false,"disabled":false}]}]}]},{"type":"CardContent","children":[{"type":"BarChart","data":[{"month":"Jan","queries":820,"tool_calls":2400},{"month":"Feb","queries":1100,"tool_calls":3200},{"month":"Mar","queries":950,"tool_calls":2800},{"month":"Apr","queries":1400,"tool_calls":4100},{"month":"May","queries":1300,"tool_calls":3900},{"month":"Jun","queries":1842,"tool_calls":5200}],"series":[{"dataKey":"queries","label":"Queries"},{"dataKey":"tool_calls","label":"Tool Calls"}],"xAxis":"month","height":200,"stacked":false,"horizontal":false,"barRadius":4,"showLegend":true,"showTooltip":true,"showGrid":true,"showYAxis":true,"yAxisFormat":"auto"}]}]},{"type":"Card","children":[{"type":"CardHeader","children":[{"cssClass":"gap-2 items-center","type":"Row","children":[{"type":"CardTitle","content":"Context Window"},{"type":"Loader","variant":"bars","size":"sm"}]}]},{"type":"CardContent","children":[{"cssClass":"gap-2","type":"Column","children":[{"cssClass":"items-center justify-between","type":"Row","children":[{"content":"45% used","type":"Text"},{"content":"90k / 200k tokens","type":"Muted"}]},{"type":"Tooltip","content":"Auto-compact buffer: 12%","delay":0,"children":[{"type":"Progress","value":45.0,"min":0,"max":100.0,"variant":"default"}]}]}]}]},{"type":"Card","children":[{"type":"CardContent","children":[{"type":"DataTable","columns":[{"key":"crew","header":"Crew","sortable":true},{"key":"species","header":"Species","sortable":true},{"key":"towel","header":"Towel?","sortable":true},{"key":"status","header":"Status","sortable":true}],"rows":[{"crew":"Arthur Dent","species":"Human","towel":"Yes","status":"Confused"},{"crew":"Ford Prefect","species":"Betelgeusian","towel":"Always","status":"Drinking"},{"crew":"Zaphod","species":"Betelgeusian","towel":"Lost it","status":"Presidential"},{"crew":"Trillian","species":"Human","towel":"Yes","status":"Navigating"},{"crew":"Marvin","species":"Android","towel":"No point","status":"Depressed"},{"crew":"Slartibartfast","species":"Magrathean","towel":"Somewhere","status":"Designing"}],"searchable":true,"paginated":false,"pageSize":10}]}]}]},{"cssClass":"gap-4","type":"Column","children":[{"type":"Card","children":[{"type":"CardHeader","children":[{"cssClass":"gap-2 items-center","type":"Row","children":[{"type":"CardTitle","content":"Improbability Drive"},{"cssClass":"text-blue-500","type":"Loader","variant":"pulse","size":"sm"}]}]},{"type":"CardContent","children":[{"cssClass":"gap-2","type":"Column","children":[{"name":"improbability","type":"Slider","min":0.0,"max":100.0,"value":42.0,"disabled":false},{"cssClass":"items-center justify-between","type":"Row","children":[{"content":"Probable","type":"Muted"},{"content":"Infinite","type":"Muted"}]}]}]}]},{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Horizon Agent Config"}]},{"type":"CardContent","children":[{"cssClass":"gap-3","type":"Column","children":[{"name":"autoscale","type":"Switch","label":"Auto-scale agents","checked":true,"size":"default","disabled":false,"required":false},{"type":"Separator","orientation":"horizontal"},{"name":"cache","type":"Switch","label":"Tool call caching","checked":false,"size":"default","disabled":false,"required":false},{"type":"Separator","orientation":"horizontal"},{"name":"fail_notifs","type":"Switch","label":"Failure notifications","checked":true,"size":"default","disabled":false,"required":false}]}]},{"type":"CardFooter","children":[{"type":"Button","label":"Save Preferences","variant":"default","size":"default","disabled":false,"onClick":{"action":"showToast","message":"Preferences saved!"}}]}]},{"type":"Alert","variant":"success","icon":"check-circle","children":[{"type":"AlertTitle","content":"Don't Panic"},{"type":"AlertDescription","content":"All 42 deployments are running normally."}]},{"type":"Alert","variant":"warning","icon":"alert-triangle","children":[{"type":"AlertTitle","content":"Babel Fish Advisory"},{"type":"AlertDescription","content":"Insert in ear before approaching Vogons."}]},{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Towel Inventory"},{"type":"CardDescription","content":"The most massively useful thing an interstellar hitchhiker can have"}]},{"type":"CardContent","children":[{"cssClass":"gap-2","type":"Column","children":[{"cssClass":"items-center justify-between","type":"Row","children":[{"content":"Bath","type":"Text"},{"content":"17","type":"Muted"}]},{"type":"Progress","value":68.0,"min":0,"max":100.0,"variant":"default","indicatorClass":"bg-blue-500"},{"cssClass":"items-center justify-between","type":"Row","children":[{"content":"Beach","type":"Text"},{"content":"8","type":"Muted"}]},{"type":"Progress","value":32.0,"min":0,"max":100.0,"variant":"default","indicatorClass":"bg-yellow-500"},{"cssClass":"items-center justify-between","type":"Row","children":[{"content":"Interstellar","type":"Text"},{"content":"1","type":"Muted"}]},{"type":"Progress","value":4.0,"min":0,"max":100.0,"variant":"default","indicatorClass":"bg-purple-500"}]}]}]}]},{"cssClass":"gap-4","type":"Column","children":[{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Marvin's Mood"}]},{"type":"CardContent","children":[{"cssClass":"gap-3","type":"Column","children":[{"content":"How is your experience with the Infinite Improbability Drive?","type":"P"},{"cssClass":"gap-2 flex-wrap","type":"Row","children":[{"type":"Button","label":"Improbable","variant":"default","size":"default","disabled":false,"onClick":{"action":"showToast","message":"Improbability factor: 2\u00b2\u2077\u2079 to 1 against"}},{"type":"Button","label":"Meh","variant":"secondary","size":"default","disabled":false,"onClick":{"action":"showToast","message":"Noted. Enthusiasm levels nominal."}},{"type":"Button","label":"Depressed","variant":"outline","size":"default","disabled":false,"onClick":{"action":"showToast","message":"I think you ought to know I'm feeling very depressed."}}]},{"name":"feedback","type":"Textarea","placeholder":"Brain the size of a planet...","disabled":false,"required":false},{"cssClass":"gap-2 items-center","type":"Row","children":[{"type":"Loader","variant":"dots","size":"sm"},{"content":"Marvin is thinking...","type":"Muted"}]}]}]}]},{"cssClass":"gap-3","type":"Column","children":[{"type":"Condition","cases":[{"when":"{{ !pressed }}","children":[{"type":"Button","label":"This is probably the best button to press.","variant":"info","size":"default","disabled":false,"onClick":{"action":"setState","key":"pressed","value":true}}]}],"else":[{"type":"Button","label":"Please do not press this button again.","variant":"secondary","size":"default","disabled":false,"onClick":{"action":"setState","key":"pressed","value":false}}]}]},{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Travel Class"}]},{"type":"CardContent","children":[{"name":"travel_class","type":"RadioGroup","children":[{"name":"radio_16","type":"Radio","value":"economy","label":"Economy","checked":false,"disabled":false,"required":false},{"name":"radio_17","type":"Radio","value":"business","label":"Business Class","checked":false,"disabled":false,"required":false},{"name":"radio_18","type":"Radio","value":"improbability","label":"Infinite Improbability","checked":true,"disabled":false,"required":false}]}]}]},{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"MCP Servers"},{"type":"CardDescription","content":"Deployed on Horizon"}]},{"type":"CardContent","children":[{"cssClass":"gap-2","type":"Column","children":[{"cssClass":"items-center justify-between","type":"Row","children":[{"content":"weather-api","type":"Text"},{"type":"Tooltip","content":"Uptime: 99.97%","delay":0,"children":[{"type":"Badge","label":"Healthy","variant":"default"}]}]},{"type":"Separator","orientation":"horizontal"},{"cssClass":"items-center justify-between","type":"Row","children":[{"content":"doc-search","type":"Text"},{"type":"Tooltip","content":"Uptime: 99.94%","delay":0,"children":[{"type":"Badge","label":"Healthy","variant":"default"}]}]},{"type":"Separator","orientation":"horizontal"},{"cssClass":"items-center justify-between","type":"Row","children":[{"content":"marvin-brain","type":"Text"},{"type":"HoverCard","openDelay":0,"closeDelay":200,"children":[{"type":"Badge","label":"Depressed","variant":"secondary"},{"cssClass":"gap-2","type":"Column","children":[{"content":"marvin-brain","type":"Text"},{"content":"Uptime: 100% \u2014 not that it matters","type":"Muted"},{"type":"Progress","value":100.0,"min":0,"max":100.0,"variant":"default"}]}]}]}]}]}]}]}]},"state":{"checkbox_12":true,"improbability":42.0,"autoscale":true,"cache":false,"fail_notifs":true}}}>
<CodeGroup>
```python Python expandable icon="python"
from prefab_ui.components import *
from prefab_ui.components.charts import *
from prefab_ui.components.control_flow import Else, If
from prefab_ui.actions import *

with Grid(min_column_width="240px", gap=4):

    with Column(gap=4):
        with Card():
            with CardHeader():
                CardTitle("Register Towel")
                CardDescription("The most important item in the galaxy")
            with CardContent():
                with Column(gap=3):
                    Input(placeholder="Towel name...")
                    owner_input = Input(placeholder="Owner name...")
                    with Select(placeholder="Type..."):
                        SelectOption(value="bath", label="Bath")
                        SelectOption(value="beach", label="Beach")
                        SelectOption(value="interstellar", label="Interstellar")
                        SelectOption(value="micro", label="Microfiber")
                    Checkbox(label="Panic-proof certified", checked=True)
            with CardFooter():
                with Row(gap=2):
                    with Dialog(
                        title="Towel Registered!",
                        description="Your towel has been added to the galactic registry.",
                    ):
                        Button("Register")
                        with If("{{ owner }}"):
                            Text(f"Thanks, {owner_input.rx}. Don't forget to bring it.")
                        with Else():
                            Text("Anonymous, I see? Don't forget to bring it.")
                    Button("Cancel", variant="outline")
        with Card():
            with CardHeader():
                CardTitle("Ship Status")
            with CardContent():
                with Column(gap=3):
                    with Row(align="center", css_class="justify-between"):
                        Text("heart-of-gold")
                        with HoverCard(open_delay=0, close_delay=200):
                            Badge("In Orbit", variant="default")
                            with Column(gap=2):
                                Text("heart-of-gold")
                                Muted("Deployed 2h ago")
                                Progress(value=100, max=100, indicator_class="bg-green-500")
                    Progress(value=100, max=100, indicator_class="bg-green-500")
                    with Row(align="center", css_class="justify-between"):
                        Text("vogon-poetry")
                        with Tooltip("64% — ETA 12 min", delay=0):
                            with Badge(variant="secondary"):
                                Loader(size="sm")
                                Text("Deploying")
                    Progress(value=64, max=100)
                    with Row(align="center", css_class="justify-between"):
                        Text("bistromath")
                        with Tooltip("Position 3 of 8", delay=0):
                            Badge("Queued", variant="outline")
                    Progress(value=12, max=100)
                    with Row(align="center", css_class="justify-between"):
                        Text("deep-thought")
                        with Tooltip("Computing... 7.5 million years remaining", delay=0):
                            Loader(variant="ios", size="sm")
        with Alert(variant="info", icon="book-open"):
            AlertTitle("The Guide Says")
            AlertDescription("Prefab: Mostly Harmless.")
        with Card():
            with CardHeader():
                CardTitle("Questions Answered")
                CardDescription("Horizon agents this quarter")
            with CardContent():
                with Column(gap=2):
                    Large("1,842")
                    Muted("+23% from last quarter")
                    with Tooltip("84% of quarterly goal", delay=0):
                        Progress(value=84, max=100, indicator_class="bg-green-500")
    with Column(gap=4):
        with Card():
            with CardHeader():
                with Row(align="center", css_class="justify-between"):
                    CardTitle("Agent Queries")
                    with Select(placeholder="6 months", name="period"):
                        SelectOption(value="3m", label="3 months")
                        SelectOption(value="6m", label="6 months")
                        SelectOption(value="1y", label="1 year")
            with CardContent():
                BarChart(
                    data=[
                        {"month": "Jan", "queries": 820, "tool_calls": 2400},
                        {"month": "Feb", "queries": 1100, "tool_calls": 3200},
                        {"month": "Mar", "queries": 950, "tool_calls": 2800},
                        {"month": "Apr", "queries": 1400, "tool_calls": 4100},
                        {"month": "May", "queries": 1300, "tool_calls": 3900},
                        {"month": "Jun", "queries": 1842, "tool_calls": 5200},
                    ],
                    series=[
                        ChartSeries(dataKey="queries", label="Queries"),
                        ChartSeries(dataKey="tool_calls", label="Tool Calls"),
                    ],
                    x_axis="month", height=200, bar_radius=4,
                    show_legend=True, show_tooltip=True, show_grid=True,
                )
        with Card():
            with CardHeader():
                with Row(gap=2, align="center"):
                    CardTitle("Context Window")
                    Loader(variant="bars", size="sm")
            with CardContent():
                with Column(gap=2):
                    with Row(align="center", css_class="justify-between"):
                        Text("45% used")
                        Muted("90k / 200k tokens")
                    with Tooltip("Auto-compact buffer: 12%", delay=0):
                        Progress(value=45, max=100)
        with Card():
            with CardContent():
                DataTable(
                    columns=[
                        DataTableColumn(key="crew", header="Crew", sortable=True),
                        DataTableColumn(key="species", header="Species", sortable=True),
                        DataTableColumn(key="towel", header="Towel?", sortable=True),
                        DataTableColumn(key="status", header="Status", sortable=True),
                    ],
                    rows=[
                        {"crew": "Arthur Dent", "species": "Human",
                        "towel": "Yes", "status": "Confused"},
                        {"crew": "Ford Prefect", "species": "Betelgeusian",
                        "towel": "Always", "status": "Drinking"},
                        {"crew": "Zaphod", "species": "Betelgeusian",
                        "towel": "Lost it", "status": "Presidential"},
                        {"crew": "Trillian", "species": "Human",
                        "towel": "Yes", "status": "Navigating"},
                        {"crew": "Marvin", "species": "Android",
                        "towel": "No point", "status": "Depressed"},
                        {"crew": "Slartibartfast", "species": "Magrathean",
                        "towel": "Somewhere", "status": "Designing"},
                    ],
                    searchable=True, paginated=False,
                )

    with Column(gap=4):
        with Card():
            with CardHeader():
                with Row(gap=2, align="center"):
                    CardTitle("Improbability Drive")
                    Loader(variant="pulse", size="sm", css_class="text-blue-500")
            with CardContent():
                with Column(gap=2):
                    Slider(min=0, max=100, value=42, name="improbability")
                    with Row(align="center", css_class="justify-between"):
                        Muted("Probable")
                        Muted("Infinite")
        with Card():
            with CardHeader():
                CardTitle("Horizon Agent Config")
            with CardContent():
                with Column(gap=3):
                    Switch(label="Auto-scale agents", checked=True, name="autoscale")
                    Separator()
                    Switch(label="Tool call caching", checked=False, name="cache")
                    Separator()
                    Switch(label="Failure notifications", checked=True, name="fail_notifs")
            with CardFooter():
                Button("Save Preferences", on_click=ShowToast("Preferences saved!"))
        with Alert(variant="success", icon="check-circle"):
            AlertTitle("Don't Panic")
            AlertDescription("All 42 deployments are running normally.")
        with Alert(variant="warning", icon="alert-triangle"):
            AlertTitle("Babel Fish Advisory")
            AlertDescription("Insert in ear before approaching Vogons.")
        with Card():
            with CardHeader():
                CardTitle("Towel Inventory")
                CardDescription(
                    "The most massively useful thing an interstellar hitchhiker can have"
                )
            with CardContent():
                with Column(gap=2):
                    with Row(align="center", css_class="justify-between"):
                        Text("Bath")
                        Muted("17")
                    Progress(value=68, max=100, indicator_class="bg-blue-500")
                    with Row(align="center", css_class="justify-between"):
                        Text("Beach")
                        Muted("8")
                    Progress(value=32, max=100, indicator_class="bg-yellow-500")
                    with Row(align="center", css_class="justify-between"):
                        Text("Interstellar")
                        Muted("1")
                    Progress(value=4, max=100, indicator_class="bg-purple-500")

    with Column(gap=4):
        with Card():
            with CardHeader():
                CardTitle("Marvin's Mood")
            with CardContent():
                with Column(gap=3):
                    P("How is your experience with the Infinite Improbability Drive?")
                    with Row(gap=2, css_class="flex-wrap"):
                        Button(
                            "Improbable",
                            on_click=ShowToast("Improbability factor: 2²⁷⁹ to 1 against"),
                        )
                        Button(
                            "Meh", variant="secondary",
                            on_click=ShowToast("Noted. Enthusiasm levels nominal."),
                        )
                        Button(
                            "Depressed", variant="outline",
                            on_click=ShowToast(
                                "I think you ought to know I'm feeling very depressed."
                            ),
                        )
                    Textarea(placeholder="Brain the size of a planet...", name="feedback")
                    with Row(gap=2, align="center"):
                        Loader(variant="dots", size="sm")
                        Muted("Marvin is thinking...")
        with Column(gap=3):
            with If("!pressed"):
                Button(
                    "This is probably the best button to press.",
                    variant="info",
                    on_click=SetState("pressed", True),
                )
            with Else():
                Button(
                    "Please do not press this button again.",
                    variant="secondary",
                    on_click=SetState("pressed", False),
                )
        with Card():
            with CardHeader():
                CardTitle("Travel Class")
            with CardContent():
                with RadioGroup(name="travel_class"):
                    Radio(value="economy", label="Economy")
                    Radio(value="business", label="Business Class")
                    Radio(value="improbability", label="Infinite Improbability", checked=True)
        with Card():
            with CardHeader():
                CardTitle("MCP Servers")
                CardDescription("Deployed on Horizon")
            with CardContent():
                with Column(gap=2):
                    with Row(align="center", css_class="justify-between"):
                        Text("weather-api")
                        with Tooltip("Uptime: 99.97%", delay=0):
                            Badge("Healthy", variant="default")
                    Separator()
                    with Row(align="center", css_class="justify-between"):
                        Text("doc-search")
                        with Tooltip("Uptime: 99.94%", delay=0):
                            Badge("Healthy", variant="default")
                    Separator()
                    with Row(align="center", css_class="justify-between"):
                        Text("marvin-brain")
                        with HoverCard(open_delay=0, close_delay=200):
                            Badge("Depressed", variant="secondary")
                            with Column(gap=2):
                                Text("marvin-brain")
                                Muted("Uptime: 100% — not that it matters")
                                Progress(value=100, max=100)

```
```json Protocol icon="brackets-curly"
{
  "view": {
    "cssClass": "gap-4",
    "type": "Grid",
    "minColumnWidth": "240px",
    "children": [
      {
        "cssClass": "gap-4",
        "type": "Column",
        "children": [
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [
                  {"type": "CardTitle", "content": "Register Towel"},
                  {"type": "CardDescription", "content": "The most important item in the galaxy"}
                ]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "cssClass": "gap-3",
                    "type": "Column",
                    "children": [
                      {
                        "name": "input_22",
                        "type": "Input",
                        "inputType": "text",
                        "placeholder": "Towel name...",
                        "disabled": false,
                        "readOnly": false,
                        "required": false
                      },
                      {
                        "name": "input_23",
                        "type": "Input",
                        "inputType": "text",
                        "placeholder": "Owner name...",
                        "disabled": false,
                        "readOnly": false,
                        "required": false
                      },
                      {
                        "name": "select_9",
                        "type": "Select",
                        "placeholder": "Type...",
                        "size": "default",
                        "disabled": false,
                        "required": false,
                        "children": [
                          {
                            "type": "SelectOption",
                            "value": "bath",
                            "label": "Bath",
                            "selected": false,
                            "disabled": false
                          },
                          {
                            "type": "SelectOption",
                            "value": "beach",
                            "label": "Beach",
                            "selected": false,
                            "disabled": false
                          },
                          {
                            "type": "SelectOption",
                            "value": "interstellar",
                            "label": "Interstellar",
                            "selected": false,
                            "disabled": false
                          },
                          {
                            "type": "SelectOption",
                            "value": "micro",
                            "label": "Microfiber",
                            "selected": false,
                            "disabled": false
                          }
                        ]
                      },
                      {
                        "name": "checkbox_12",
                        "type": "Checkbox",
                        "label": "Panic-proof certified",
                        "checked": true,
                        "disabled": false,
                        "required": false
                      }
                    ]
                  }
                ]
              },
              {
                "type": "CardFooter",
                "children": [
                  {
                    "cssClass": "gap-2",
                    "type": "Row",
                    "children": [
                      {
                        "type": "Dialog",
                        "title": "Towel Registered!",
                        "description": "Your towel has been added to the galactic registry.",
                        "children": [
                          {
                            "type": "Button",
                            "label": "Register",
                            "variant": "default",
                            "size": "default",
                            "disabled": false
                          },
                          {
                            "type": "Condition",
                            "cases": [
                              {
                                "when": "{{ owner }}",
                                "children": [
                                  {"content": "Thanks, {{ input_23 }}. Don't forget to bring it.", "type": "Text"}
                                ]
                              }
                            ],
                            "else": [{"content": "Anonymous, I see? Don't forget to bring it.", "type": "Text"}]
                          }
                        ]
                      },
                      {
                        "type": "Button",
                        "label": "Cancel",
                        "variant": "outline",
                        "size": "default",
                        "disabled": false
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [{"type": "CardTitle", "content": "Ship Status"}]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "cssClass": "gap-3",
                    "type": "Column",
                    "children": [
                      {
                        "cssClass": "items-center justify-between",
                        "type": "Row",
                        "children": [
                          {"content": "heart-of-gold", "type": "Text"},
                          {
                            "type": "HoverCard",
                            "openDelay": 0,
                            "closeDelay": 200,
                            "children": [
                              {"type": "Badge", "label": "In Orbit", "variant": "default"},
                              {
                                "cssClass": "gap-2",
                                "type": "Column",
                                "children": [
                                  {"content": "heart-of-gold", "type": "Text"},
                                  {"content": "Deployed 2h ago", "type": "Muted"},
                                  {
                                    "type": "Progress",
                                    "value": 100.0,
                                    "min": 0,
                                    "max": 100.0,
                                    "variant": "default",
                                    "indicatorClass": "bg-green-500"
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "type": "Progress",
                        "value": 100.0,
                        "min": 0,
                        "max": 100.0,
                        "variant": "default",
                        "indicatorClass": "bg-green-500"
                      },
                      {
                        "cssClass": "items-center justify-between",
                        "type": "Row",
                        "children": [
                          {"content": "vogon-poetry", "type": "Text"},
                          {
                            "type": "Tooltip",
                            "content": "64% \u2014 ETA 12 min",
                            "delay": 0,
                            "children": [
                              {
                                "type": "Badge",
                                "variant": "secondary",
                                "children": [
                                  {"type": "Loader", "variant": "spin", "size": "sm"},
                                  {"content": "Deploying", "type": "Text"}
                                ]
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "type": "Progress",
                        "value": 64.0,
                        "min": 0,
                        "max": 100.0,
                        "variant": "default"
                      },
                      {
                        "cssClass": "items-center justify-between",
                        "type": "Row",
                        "children": [
                          {"content": "bistromath", "type": "Text"},
                          {
                            "type": "Tooltip",
                            "content": "Position 3 of 8",
                            "delay": 0,
                            "children": [{"type": "Badge", "label": "Queued", "variant": "outline"}]
                          }
                        ]
                      },
                      {
                        "type": "Progress",
                        "value": 12.0,
                        "min": 0,
                        "max": 100.0,
                        "variant": "default"
                      },
                      {
                        "cssClass": "items-center justify-between",
                        "type": "Row",
                        "children": [
                          {"content": "deep-thought", "type": "Text"},
                          {
                            "type": "Tooltip",
                            "content": "Computing... 7.5 million years remaining",
                            "delay": 0,
                            "children": [{"type": "Loader", "variant": "ios", "size": "sm"}]
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "Alert",
            "variant": "info",
            "icon": "book-open",
            "children": [
              {"type": "AlertTitle", "content": "The Guide Says"},
              {"type": "AlertDescription", "content": "Prefab: Mostly Harmless."}
            ]
          },
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [
                  {"type": "CardTitle", "content": "Questions Answered"},
                  {"type": "CardDescription", "content": "Horizon agents this quarter"}
                ]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "cssClass": "gap-2",
                    "type": "Column",
                    "children": [
                      {"content": "1,842", "type": "Large"},
                      {"content": "+23% from last quarter", "type": "Muted"},
                      {
                        "type": "Tooltip",
                        "content": "84% of quarterly goal",
                        "delay": 0,
                        "children": [
                          {
                            "type": "Progress",
                            "value": 84.0,
                            "min": 0,
                            "max": 100.0,
                            "variant": "default",
                            "indicatorClass": "bg-green-500"
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "cssClass": "gap-4",
        "type": "Column",
        "children": [
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [
                  {
                    "cssClass": "items-center justify-between",
                    "type": "Row",
                    "children": [
                      {"type": "CardTitle", "content": "Agent Queries"},
                      {
                        "name": "period",
                        "type": "Select",
                        "placeholder": "6 months",
                        "size": "default",
                        "disabled": false,
                        "required": false,
                        "children": [
                          {
                            "type": "SelectOption",
                            "value": "3m",
                            "label": "3 months",
                            "selected": false,
                            "disabled": false
                          },
                          {
                            "type": "SelectOption",
                            "value": "6m",
                            "label": "6 months",
                            "selected": false,
                            "disabled": false
                          },
                          {
                            "type": "SelectOption",
                            "value": "1y",
                            "label": "1 year",
                            "selected": false,
                            "disabled": false
                          }
                        ]
                      }
                    ]
                  }
                ]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "type": "BarChart",
                    "data": [
                      {"month": "Jan", "queries": 820, "tool_calls": 2400},
                      {"month": "Feb", "queries": 1100, "tool_calls": 3200},
                      {"month": "Mar", "queries": 950, "tool_calls": 2800},
                      {"month": "Apr", "queries": 1400, "tool_calls": 4100},
                      {"month": "May", "queries": 1300, "tool_calls": 3900},
                      {"month": "Jun", "queries": 1842, "tool_calls": 5200}
                    ],
                    "series": [
                      {"dataKey": "queries", "label": "Queries"},
                      {"dataKey": "tool_calls", "label": "Tool Calls"}
                    ],
                    "xAxis": "month",
                    "height": 200,
                    "stacked": false,
                    "horizontal": false,
                    "barRadius": 4,
                    "showLegend": true,
                    "showTooltip": true,
                    "showGrid": true,
                    "showYAxis": true,
                    "yAxisFormat": "auto"
                  }
                ]
              }
            ]
          },
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [
                  {
                    "cssClass": "gap-2 items-center",
                    "type": "Row",
                    "children": [
                      {"type": "CardTitle", "content": "Context Window"},
                      {"type": "Loader", "variant": "bars", "size": "sm"}
                    ]
                  }
                ]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "cssClass": "gap-2",
                    "type": "Column",
                    "children": [
                      {
                        "cssClass": "items-center justify-between",
                        "type": "Row",
                        "children": [
                          {"content": "45% used", "type": "Text"},
                          {"content": "90k / 200k tokens", "type": "Muted"}
                        ]
                      },
                      {
                        "type": "Tooltip",
                        "content": "Auto-compact buffer: 12%",
                        "delay": 0,
                        "children": [
                          {
                            "type": "Progress",
                            "value": 45.0,
                            "min": 0,
                            "max": 100.0,
                            "variant": "default"
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "Card",
            "children": [
              {
                "type": "CardContent",
                "children": [
                  {
                    "type": "DataTable",
                    "columns": [
                      {"key": "crew", "header": "Crew", "sortable": true},
                      {"key": "species", "header": "Species", "sortable": true},
                      {"key": "towel", "header": "Towel?", "sortable": true},
                      {"key": "status", "header": "Status", "sortable": true}
                    ],
                    "rows": [
                      {
                        "crew": "Arthur Dent",
                        "species": "Human",
                        "towel": "Yes",
                        "status": "Confused"
                      },
                      {
                        "crew": "Ford Prefect",
                        "species": "Betelgeusian",
                        "towel": "Always",
                        "status": "Drinking"
                      },
                      {
                        "crew": "Zaphod",
                        "species": "Betelgeusian",
                        "towel": "Lost it",
                        "status": "Presidential"
                      },
                      {"crew": "Trillian", "species": "Human", "towel": "Yes", "status": "Navigating"},
                      {
                        "crew": "Marvin",
                        "species": "Android",
                        "towel": "No point",
                        "status": "Depressed"
                      },
                      {
                        "crew": "Slartibartfast",
                        "species": "Magrathean",
                        "towel": "Somewhere",
                        "status": "Designing"
                      }
                    ],
                    "searchable": true,
                    "paginated": false,
                    "pageSize": 10
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "cssClass": "gap-4",
        "type": "Column",
        "children": [
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [
                  {
                    "cssClass": "gap-2 items-center",
                    "type": "Row",
                    "children": [
                      {"type": "CardTitle", "content": "Improbability Drive"},
                      {
                        "cssClass": "text-blue-500",
                        "type": "Loader",
                        "variant": "pulse",
                        "size": "sm"
                      }
                    ]
                  }
                ]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "cssClass": "gap-2",
                    "type": "Column",
                    "children": [
                      {
                        "name": "improbability",
                        "type": "Slider",
                        "min": 0.0,
                        "max": 100.0,
                        "value": 42.0,
                        "disabled": false
                      },
                      {
                        "cssClass": "items-center justify-between",
                        "type": "Row",
                        "children": [
                          {"content": "Probable", "type": "Muted"},
                          {"content": "Infinite", "type": "Muted"}
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [{"type": "CardTitle", "content": "Horizon Agent Config"}]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "cssClass": "gap-3",
                    "type": "Column",
                    "children": [
                      {
                        "name": "autoscale",
                        "type": "Switch",
                        "label": "Auto-scale agents",
                        "checked": true,
                        "size": "default",
                        "disabled": false,
                        "required": false
                      },
                      {"type": "Separator", "orientation": "horizontal"},
                      {
                        "name": "cache",
                        "type": "Switch",
                        "label": "Tool call caching",
                        "checked": false,
                        "size": "default",
                        "disabled": false,
                        "required": false
                      },
                      {"type": "Separator", "orientation": "horizontal"},
                      {
                        "name": "fail_notifs",
                        "type": "Switch",
                        "label": "Failure notifications",
                        "checked": true,
                        "size": "default",
                        "disabled": false,
                        "required": false
                      }
                    ]
                  }
                ]
              },
              {
                "type": "CardFooter",
                "children": [
                  {
                    "type": "Button",
                    "label": "Save Preferences",
                    "variant": "default",
                    "size": "default",
                    "disabled": false,
                    "onClick": {"action": "showToast", "message": "Preferences saved!"}
                  }
                ]
              }
            ]
          },
          {
            "type": "Alert",
            "variant": "success",
            "icon": "check-circle",
            "children": [
              {"type": "AlertTitle", "content": "Don't Panic"},
              {
                "type": "AlertDescription",
                "content": "All 42 deployments are running normally."
              }
            ]
          },
          {
            "type": "Alert",
            "variant": "warning",
            "icon": "alert-triangle",
            "children": [
              {"type": "AlertTitle", "content": "Babel Fish Advisory"},
              {
                "type": "AlertDescription",
                "content": "Insert in ear before approaching Vogons."
              }
            ]
          },
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [
                  {"type": "CardTitle", "content": "Towel Inventory"},
                  {
                    "type": "CardDescription",
                    "content": "The most massively useful thing an interstellar hitchhiker can have"
                  }
                ]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "cssClass": "gap-2",
                    "type": "Column",
                    "children": [
                      {
                        "cssClass": "items-center justify-between",
                        "type": "Row",
                        "children": [{"content": "Bath", "type": "Text"}, {"content": "17", "type": "Muted"}]
                      },
                      {
                        "type": "Progress",
                        "value": 68.0,
                        "min": 0,
                        "max": 100.0,
                        "variant": "default",
                        "indicatorClass": "bg-blue-500"
                      },
                      {
                        "cssClass": "items-center justify-between",
                        "type": "Row",
                        "children": [{"content": "Beach", "type": "Text"}, {"content": "8", "type": "Muted"}]
                      },
                      {
                        "type": "Progress",
                        "value": 32.0,
                        "min": 0,
                        "max": 100.0,
                        "variant": "default",
                        "indicatorClass": "bg-yellow-500"
                      },
                      {
                        "cssClass": "items-center justify-between",
                        "type": "Row",
                        "children": [{"content": "Interstellar", "type": "Text"}, {"content": "1", "type": "Muted"}]
                      },
                      {
                        "type": "Progress",
                        "value": 4.0,
                        "min": 0,
                        "max": 100.0,
                        "variant": "default",
                        "indicatorClass": "bg-purple-500"
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "cssClass": "gap-4",
        "type": "Column",
        "children": [
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [{"type": "CardTitle", "content": "Marvin's Mood"}]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "cssClass": "gap-3",
                    "type": "Column",
                    "children": [
                      {
                        "content": "How is your experience with the Infinite Improbability Drive?",
                        "type": "P"
                      },
                      {
                        "cssClass": "gap-2 flex-wrap",
                        "type": "Row",
                        "children": [
                          {
                            "type": "Button",
                            "label": "Improbable",
                            "variant": "default",
                            "size": "default",
                            "disabled": false,
                            "onClick": {
                              "action": "showToast",
                              "message": "Improbability factor: 2\u00b2\u2077\u2079 to 1 against"
                            }
                          },
                          {
                            "type": "Button",
                            "label": "Meh",
                            "variant": "secondary",
                            "size": "default",
                            "disabled": false,
                            "onClick": {"action": "showToast", "message": "Noted. Enthusiasm levels nominal."}
                          },
                          {
                            "type": "Button",
                            "label": "Depressed",
                            "variant": "outline",
                            "size": "default",
                            "disabled": false,
                            "onClick": {
                              "action": "showToast",
                              "message": "I think you ought to know I'm feeling very depressed."
                            }
                          }
                        ]
                      },
                      {
                        "name": "feedback",
                        "type": "Textarea",
                        "placeholder": "Brain the size of a planet...",
                        "disabled": false,
                        "required": false
                      },
                      {
                        "cssClass": "gap-2 items-center",
                        "type": "Row",
                        "children": [
                          {"type": "Loader", "variant": "dots", "size": "sm"},
                          {"content": "Marvin is thinking...", "type": "Muted"}
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "cssClass": "gap-3",
            "type": "Column",
            "children": [
              {
                "type": "Condition",
                "cases": [
                  {
                    "when": "{{ !pressed }}",
                    "children": [
                      {
                        "type": "Button",
                        "label": "This is probably the best button to press.",
                        "variant": "info",
                        "size": "default",
                        "disabled": false,
                        "onClick": {"action": "setState", "key": "pressed", "value": true}
                      }
                    ]
                  }
                ],
                "else": [
                  {
                    "type": "Button",
                    "label": "Please do not press this button again.",
                    "variant": "secondary",
                    "size": "default",
                    "disabled": false,
                    "onClick": {"action": "setState", "key": "pressed", "value": false}
                  }
                ]
              }
            ]
          },
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [{"type": "CardTitle", "content": "Travel Class"}]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "name": "travel_class",
                    "type": "RadioGroup",
                    "children": [
                      {
                        "name": "radio_16",
                        "type": "Radio",
                        "value": "economy",
                        "label": "Economy",
                        "checked": false,
                        "disabled": false,
                        "required": false
                      },
                      {
                        "name": "radio_17",
                        "type": "Radio",
                        "value": "business",
                        "label": "Business Class",
                        "checked": false,
                        "disabled": false,
                        "required": false
                      },
                      {
                        "name": "radio_18",
                        "type": "Radio",
                        "value": "improbability",
                        "label": "Infinite Improbability",
                        "checked": true,
                        "disabled": false,
                        "required": false
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [
                  {"type": "CardTitle", "content": "MCP Servers"},
                  {"type": "CardDescription", "content": "Deployed on Horizon"}
                ]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "cssClass": "gap-2",
                    "type": "Column",
                    "children": [
                      {
                        "cssClass": "items-center justify-between",
                        "type": "Row",
                        "children": [
                          {"content": "weather-api", "type": "Text"},
                          {
                            "type": "Tooltip",
                            "content": "Uptime: 99.97%",
                            "delay": 0,
                            "children": [{"type": "Badge", "label": "Healthy", "variant": "default"}]
                          }
                        ]
                      },
                      {"type": "Separator", "orientation": "horizontal"},
                      {
                        "cssClass": "items-center justify-between",
                        "type": "Row",
                        "children": [
                          {"content": "doc-search", "type": "Text"},
                          {
                            "type": "Tooltip",
                            "content": "Uptime: 99.94%",
                            "delay": 0,
                            "children": [{"type": "Badge", "label": "Healthy", "variant": "default"}]
                          }
                        ]
                      },
                      {"type": "Separator", "orientation": "horizontal"},
                      {
                        "cssClass": "items-center justify-between",
                        "type": "Row",
                        "children": [
                          {"content": "marvin-brain", "type": "Text"},
                          {
                            "type": "HoverCard",
                            "openDelay": 0,
                            "closeDelay": 200,
                            "children": [
                              {"type": "Badge", "label": "Depressed", "variant": "secondary"},
                              {
                                "cssClass": "gap-2",
                                "type": "Column",
                                "children": [
                                  {"content": "marvin-brain", "type": "Text"},
                                  {"content": "Uptime: 100% \u2014 not that it matters", "type": "Muted"},
                                  {
                                    "type": "Progress",
                                    "value": 100.0,
                                    "min": 0,
                                    "max": 100.0,
                                    "variant": "default"
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  "state": {
    "checkbox_12": true,
    "improbability": 42.0,
    "autoscale": true,
    "cache": false,
    "fail_notifs": true
  }
}
```
</CodeGroup>
</ComponentPreview>
</div>

Every component above was generated from the following Python code.

<Tip>
In fact, **every example in the Prefab docs is rendered by Prefab itself.** The Python code and corresponding Prefab protocol JSON are always shown below the example for reference.
</Tip>


{/* @code:showcase */}
<_C_showcase />




## Why Prefab

Prefab began as a DSL for building [MCP Apps](/running/fastmcp) as part of [FastMCP](https://github.com/PrefectHQ/fastmcp). MCP Apps are an extension of the Model Context Protocol that lets MCP servers render fully interactive UIs directly inside the chat — dashboards, forms, data tables, visualizations — not as static text, but as live interfaces the user can interact with while talking to an agent.

Building an MCP App means shipping a self-contained UI bundle. For TypeScript SDK users, that's natural — they're already in the JavaScript ecosystem. But the vast majority of MCP servers are written in Python, and for those developers, building an MCP App means spinning up an entirely new project in an entirely new language, tightly coupled to their server with no shared types or enforcement. Prefab eliminates that gap entirely: describe your UI in Python, right next to your server logic, and Prefab compiles it to a production React bundle.

### The design philosophy

The goal isn't to port React to Python. Developers who want to build rich, bespoke frontends will — and should — reach for the best tools in the JavaScript ecosystem. Prefab is built on a different insight: the vast majority of interactive experiences appropriate for MCP are not full-fledged web applications. They are forms of **information delivery, visualization, and collection**.

When an agent pulls a large dataset from a database, the user today must choose between asking the agent to summarize it (losing detail) or dumping it into the chat (losing structure). An interactive data table with sorting and filtering is a better answer. When an agent needs structured input, a form beats a multi-turn conversation. When results need context, summary cards and charts communicate more than paragraphs of text.

These use cases don't need the infinite complexity of a full frontend stack. They need a relatively small number of composable components — layout, typography, forms, data display, charts — with enough interactivity for data delivery and collection to cover the vast majority of scenarios.

Prefab is a JSON protocol by design, not just a Python library. This means agents can dynamically construct new UIs on the fly — rendering interfaces that no developer predefined. An agent can decide, mid-conversation, to show a chart, build a form, or compose a dashboard from components, all by producing JSON that the renderer already knows how to paint.

### The landscape

There is a rich ecosystem of projects bringing frontend development to Python — Streamlit, Gradio, NiceGUI, Reflex, and many others. Most assume a running Python server that manages state and serves the UI. [FastUI](https://github.com/pydantic/FastUI) pioneered a different approach: a declarative component protocol rendered by a separate frontend. Prefab builds directly on that insight, from a different starting point — MCP and agent-native use cases where the UI may not have a server at all.

The renderer compiles JSON to real React — production components with state management, forms, and declarative interactivity — and ships as a self-contained static bundle. The Python side has no transport dependencies: it works with MCP servers via FastMCP, with REST APIs via FastAPI, or with anything else that can produce JSON.

Prefab is made with 💙 by [Prefect](https://www.prefect.io/).

## How It Works

The core idea is a pipeline: **JSON → React**. For Python authors, it's **Python → JSON → React**.

1. A component tree is described — in Python via the DSL, or as raw JSON from any source
2. The tree serializes to Prefab's JSON wire format
3. A React renderer (shipped as `@prefecthq/prefab-ui` on npm) compiles the JSON into a live interface

State flows through templates. When you write `{{ query }}`, the renderer interpolates the current value of `query` from client-side state. Actions like `CallTool` and `SetState` update that state, keeping the UI reactive.

Here's a simpler example — type in the input and watch the heading update in real time:

<ComponentPreview json={{"view":{"type":"Card","children":[{"type":"CardContent","children":[{"cssClass":"gap-3","type":"Column","children":[{"content":"Hello, {{ name }}!","type":"H3"},{"content":"Type below and watch this update in real time.","type":"Muted"},{"name":"name","type":"Input","inputType":"text","placeholder":"Your name...","disabled":false,"readOnly":false,"required":false}]}]},{"type":"CardFooter","children":[{"cssClass":"gap-2","type":"Row","children":[{"type":"Badge","label":"Name: {{ name }}","variant":"default"},{"type":"Badge","label":"Prefab","variant":"success"}]}]}]},"state":{"name":"world"}}} playground=" ">
<CodeGroup>
```python Python icon="python"
from prefab_ui.app import set_initial_state
from prefab_ui.components import Card, CardContent, CardFooter, Column, H3, Muted, Input, Badge, Row

set_initial_state(name="world")

with Card():
    with CardContent():
        with Column(gap=3):
            H3("Hello, {{ name }}!")
            Muted("Type below and watch this update in real time.")
            Input(name="name", placeholder="Your name...")
    with CardFooter():
        with Row(gap=2):
            Badge("Name: {{ name }}", variant="default")
            Badge("Prefab", variant="success")
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "type": "Card",
    "children": [
      {
        "type": "CardContent",
        "children": [
          {
            "cssClass": "gap-3",
            "type": "Column",
            "children": [
              {"content": "Hello, {{ name }}!", "type": "H3"},
              {"content": "Type below and watch this update in real time.", "type": "Muted"},
              {
                "name": "name",
                "type": "Input",
                "inputType": "text",
                "placeholder": "Your name...",
                "disabled": false,
                "readOnly": false,
                "required": false
              }
            ]
          }
        ]
      },
      {
        "type": "CardFooter",
        "children": [
          {
            "cssClass": "gap-2",
            "type": "Row",
            "children": [
              {"type": "Badge", "label": "Name: {{ name }}", "variant": "default"},
              {"type": "Badge", "label": "Prefab", "variant": "success"}
            ]
          }
        ]
      }
    ]
  },
  "state": {"name": "world"}
}
```
</CodeGroup>
</ComponentPreview>

## Installation

```bash
pip install prefab-ui
```

Prefab requires Python 3.10+. See [Installation](/installation) for version pinning guidance.

## What's in the Box

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Install, create an app, see it render. Two minutes, no prerequisites.
  </Card>
  <Card title="Components" icon="cube" href="/components/button">
    35+ components: layout, typography, forms, data display, and interactive elements. Nest them with Python context managers.
  </Card>
  <Card title="Actions" icon="bolt" href="/actions/overview">
    Declarative interactivity — state updates, server calls, navigation, and toast notifications. Chain them with lifecycle callbacks.
  </Card>
  <Card title="Expressions" icon="lightbulb" href="/expressions/overview">
    Templates, operators, and pipes — build reactive UIs with `{{ }}` syntax, no server required.
  </Card>
</CardGroup>

