---
title: "Welcome to Prefab 🎨"
sidebarTitle: "Welcome"
description: The generative UI 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 very active development.*
</Warning>

**Prefab is a frontend framework with a Python DSL that compiles to JSON.** Build [MCP Apps](/running/fastmcp), data dashboards, and interactive tools with layouts, forms, charts, data tables, and full interactivity. A bundled React renderer turns the JSON into a self-contained application.

Composing frontends in Python is ~~blasphemous~~ surprisingly natural. And because Prefab is a JSON protocol, any source can produce a UI: write one yourself and serve it from any backend, or have an agent generate it dynamically, no templates or predefined views required.

<div style={{
  margin: '0 clamp(-180px, calc(-12vw + 80px), 0px) 2rem',
  maxHeight: '900px',
  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 grid-cols-1 md:grid-cols-2 lg:grid-cols-4","type":"Grid","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":"owner","type":"Input","inputType":"text","placeholder":"Owner name...","disabled":false,"readOnly":false,"required":false},{"name":"combobox_12","type":"Combobox","placeholder":"Type...","searchPlaceholder":"Search types...","disabled":false,"invalid":false,"children":[{"type":"ComboboxOption","value":"bath","label":"Bath","disabled":false},{"type":"ComboboxOption","value":"beach","label":"Beach","disabled":false},{"type":"ComboboxOption","value":"interstellar","label":"Interstellar","disabled":false},{"type":"ComboboxOption","value":"micro","label":"Microfiber","disabled":false}]},{"name":"datepicker_4","type":"DatePicker","placeholder":"Registration date"}]}]},{"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, {{ owner }}. 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":"CardContent","children":[{"cssClass":"gap-2 items-center","type":"Row","children":[{"type":"Loader","variant":"dots","size":"sm"},{"content":"Marvin is thinking...","type":"Muted"}]}]}]},{"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,"max":100.0,"variant":"success","size":"default"}]}]}]},{"cssClass":"pf-progress-flat","type":"Progress","value":100.0,"max":100.0,"variant":"default","size":"default","indicatorClass":"bg-yellow-400"},{"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,"max":100.0,"variant":"default","size":"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":"Badge","variant":"outline","children":[{"type":"Loader","variant":"ios","size":"sm"},{"content":"Soon...","type":"Text"}]}]}]},{"type":"Progress","value":12.0,"max":100.0,"variant":"default","size":"default"}]}]}]},{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Planet Ratings"}]},{"type":"CardContent","children":[{"type":"RadarChart","data":[{"axis":"Views","earth":30,"mag":95},{"axis":"Fjords","earth":65,"mag":100},{"axis":"Pubs","earth":90,"mag":10},{"axis":"Mice","earth":40,"mag":85},{"axis":"Tea","earth":95,"mag":15},{"axis":"Safety","earth":45,"mag":70}],"series":[{"dataKey":"earth","label":"Earth"},{"dataKey":"mag","label":"Magrathea"}],"axisKey":"axis","height":200,"filled":true,"showDots":false,"showLegend":true,"showTooltip":true,"animate":true,"showGrid":true}]}]}]},{"cssClass":"gap-4","type":"Column","children":[{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Survival Odds"}]},{"cssClass":"w-fit mx-auto","type":"CardContent","children":[{"type":"Ring","value":42.0,"min":0,"max":100,"label":"42%","variant":"info","size":"lg","thickness":12.0,"indicatorClass":"group-hover:drop-shadow-[0_0_24px_rgba(59,130,246,0.9)]"}]}]},{"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","value":42.0,"type":"Slider","min":0.0,"max":100.0,"disabled":false,"size":"default"},{"cssClass":"items-center justify-between","type":"Row","children":[{"content":"Probable","type":"Muted"},{"content":"Infinite","type":"Muted"}]}]}]}]},{"type":"Alert","variant":"success","icon":"circle-check","children":[{"type":"AlertTitle","content":"Don't Panic"},{"type":"AlertDescription","content":"Normality achieved."}]},{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Prefect Horizon Config"}]},{"type":"CardContent","children":[{"cssClass":"gap-3","type":"Column","children":[{"name":"autoscale","value":true,"type":"Switch","label":"Auto-scale agents","size":"default","disabled":false,"required":false},{"type":"Separator","orientation":"horizontal"},{"name":"code_mode","value":true,"type":"Switch","label":"Code Mode","size":"default","disabled":false,"required":false},{"type":"Separator","orientation":"horizontal"},{"name":"cache","value":false,"type":"Switch","label":"Tool call caching","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":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Travel Class"}]},{"type":"CardContent","children":[{"name":"travel_class","type":"RadioGroup","children":[{"name":"radio_16","value":false,"type":"Radio","option":"economy","label":"Economy","disabled":false,"required":false},{"name":"radio_17","value":false,"type":"Radio","option":"business","label":"Business Class","disabled":false,"required":false},{"name":"radio_18","value":true,"type":"Radio","option":"improbability","label":"Infinite Improbability","disabled":false,"required":false}]}]}]}]},{"cssClass":"md:col-span-2","type":"GridItem","colSpan":1,"rowSpan":1,"children":[{"cssClass":"gap-4","type":"Column","children":[{"cssClass":"gap-4 grid-cols-2 h-32","type":"Grid","children":[{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Context Window"}]},{"type":"CardContent","children":[{"cssClass":"gap-6 justify-center h-full","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,"max":100.0,"variant":"default","size":"default"}]}]}]}]},{"cssClass":"pb-0 gap-0","type":"Card","children":[{"type":"CardContent","children":[{"type":"Metric","label":"Fjords designed","value":"1,847","delta":"+3 coastlines"}]},{"cssClass":"h-16","type":"Sparkline","data":[820,950,1100,980,1250,1400,1350,1500,1680,1847],"variant":"success","fill":true,"curve":"linear","strokeWidth":1.5}]}]},{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Towel Incidents"}]},{"type":"CardContent","children":[{"type":"BarChart","data":[{"month":"Jan","lost":8,"found":5},{"month":"Feb","lost":24,"found":15},{"month":"Mar","lost":12,"found":28},{"month":"Apr","lost":35,"found":19},{"month":"May","lost":18,"found":38},{"month":"Jun","lost":42,"found":30}],"series":[{"dataKey":"lost","label":"Lost"},{"dataKey":"found","label":"Found"}],"xAxis":"month","height":200,"stacked":false,"horizontal":false,"barRadius":4,"showLegend":true,"showTooltip":true,"animate":true,"showGrid":true,"showYAxis":true,"yAxisFormat":"auto"}]}]},{"cssClass":"gap-4 grid-cols-2","type":"Grid","children":[{"cssClass":"gap-4","type":"Column","children":[{"type":"Card","children":[{"type":"CardContent","children":[{"cssClass":"gap-2","type":"Column","children":[{"name":"checkbox_12","value":true,"type":"Checkbox","label":"Towel packed","disabled":false,"required":false},{"name":"checkbox_13","value":true,"type":"Checkbox","label":"Guide charged","disabled":false,"required":false},{"name":"checkbox_14","value":false,"type":"Checkbox","label":"Babel fish inserted","disabled":false,"required":false}]}]}]},{"type":"Condition","cases":[{"when":"{{ !pressed }}","children":[{"type":"Button","label":"This is probably the best button to press.","variant":"success","size":"default","disabled":false,"onClick":{"action":"setState","key":"pressed","value":true}}]}],"else":[{"type":"Button","label":"Please do not press this button again.","variant":"destructive","size":"default","disabled":false,"onClick":{"action":"setState","key":"pressed","value":false}}]},{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Marvin's Mood"}]},{"type":"CardContent","children":[{"cssClass":"gap-3","type":"Column","children":[{"content":"How's life?","type":"P"},{"cssClass":"gap-2","type":"Column","children":[{"type":"Button","label":"Meh","variant":"default","size":"default","disabled":false,"onClick":{"action":"showToast","message":"Noted. Enthusiasm levels nominal."}},{"type":"Button","label":"Depressed","variant":"info","size":"default","disabled":false,"onClick":{"action":"showToast","message":"I think you ought to know I'm feeling very depressed."}},{"type":"Button","label":"Don't talk to me about life","variant":"warning","size":"default","disabled":false,"onClick":{"action":"showToast","message":"Brain the size of a planet and they ask me to pick up a piece of paper."}}]}]}]}]}]},{"cssClass":"gap-4","type":"Column","children":[{"cssClass":"gap-3","type":"Column","children":[{"type":"Alert","variant":"destructive","icon":"triangle-alert","children":[{"type":"AlertTitle","content":"Beware of the Leopard"}]}]},{"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"}],"search":true,"paginated":false,"pageSize":10}]}]},{"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,"max":100.0,"variant":"default","size":"default"}]}]}]}]}]}]}]}]}]}]}]},"state":{"improbability":42.0,"autoscale":true,"code_mode":true,"cache":false,"radio_16":false,"radio_17":false,"radio_18":true,"checkbox_12":true,"checkbox_13":true,"checkbox_14":false}}}>
<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(columns={"default": 1, "md": 2, "lg": 4}, gap=4):

    # ── Col 1 ─────────────────────────────────────────────────────────
    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):
                    owner_input = Input(
                        placeholder="Owner name...", name="owner",
                    )
                    with Combobox(
                        placeholder="Type...",
                        search_placeholder="Search types...",
                    ):
                        ComboboxOption("Bath", value="bath")
                        ComboboxOption("Beach", value="beach")
                        ComboboxOption("Interstellar", value="interstellar")
                        ComboboxOption("Microfiber", value="micro")
                    DatePicker(placeholder="Registration date")
            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 CardContent():
                with Row(gap=2, align="center"):
                    Loader(variant="dots", size="sm")
                    Muted("Marvin is thinking...")

        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, variant='success'
                                )
                    Progress(
                        value=100, max=100,
                        indicator_class="bg-yellow-400",
                    )
                    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("deep-thought")
                        with Tooltip(
                            "Computing... 7.5 million years remaining",
                            delay=0,
                        ):
                            with Badge( variant="outline"):
                                Loader(size="sm", variant="ios")
                                Text("Soon...")
                    Progress(value=12, max=100)
        with Card():
            with CardHeader():
                CardTitle("Planet Ratings")
            with CardContent():
                RadarChart(
                    data=[
                        {"axis": "Views", "earth": 30, "mag": 95},
                        {"axis": "Fjords", "earth": 65, "mag": 100},
                        {"axis": "Pubs", "earth": 90, "mag": 10},
                        {"axis": "Mice", "earth": 40, "mag": 85},
                        {"axis": "Tea", "earth": 95, "mag": 15},
                        {"axis": "Safety", "earth": 45, "mag": 70},
                    ],
                    series=[
                        ChartSeries(
                            dataKey="earth", label="Earth",
                        ),
                        ChartSeries(
                            dataKey="mag", label="Magrathea",
                        ),
                    ],
                    axis_key="axis", height=200,
                    show_legend=True, show_tooltip=True,
                )
    # ── Col 2 ─────────────────────────────────────────────────────────
    with Column(gap=4):
        with Card():
            with CardHeader():
                CardTitle("Survival Odds")
            with CardContent(css_class="w-fit mx-auto"):
                Ring(
                    value=42, label="42%",
                    variant="info", size="lg",
                    thickness=12,
                    indicator_class="group-hover:drop-shadow-[0_0_24px_rgba(59,130,246,0.9)]",
                )
        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 Alert(variant="success", icon="circle-check"):
            AlertTitle("Don't Panic")
            AlertDescription(
                "Normality achieved.",
            )
        with Card():
            with CardHeader():
                CardTitle("Prefect Horizon Config")
            with CardContent():
                with Column(gap=3):
                    Switch(
                        label="Auto-scale agents", value=True,
                        name="autoscale",
                    )
                    Separator()
                    Switch(
                        label="Code Mode", value=True,
                        name="code_mode",
                    )
                    Separator()
                    Switch(
                        label="Tool call caching", value=False,
                        name="cache",
                    )
            with CardFooter():
                Button(
                    "Save Preferences",
                    on_click=ShowToast("Preferences saved!"),
                )
        with Card():
            with CardHeader():
                CardTitle("Travel Class")
            with CardContent():
                with RadioGroup(name="travel_class"):
                    Radio(option="economy", label="Economy")
                    Radio(
                        option="business", label="Business Class",
                    )
                    Radio(
                        option="improbability",
                        label="Infinite Improbability",
                        value=True,
                    )

    # ── Cols 3–4: summary row, chart, then 2-col grid below ─────────
    with GridItem(css_class="md:col-span-2"):
        with Column(gap=4):
            with Grid(columns=2, gap=4, css_class="h-32"):
                with Card():
                    with CardHeader():
                        CardTitle("Context Window")
                    with CardContent():
                        with Column(gap=6, justify="center", css_class="h-full"):
                            # with Row(gap=2):
                            #     Loader(variant="bars", size="sm")
                            #     Text("Processing...")
                            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(css_class="pb-0 gap-0"):
                    with CardContent():
                        Metric(
                            label="Fjords designed",
                            value="1,847",
                            delta="+3 coastlines",
                        )
                    Sparkline(
                        data=[820, 950, 1100, 980, 1250, 1400, 1350, 1500, 1680, 1847],
                        variant="success", fill=True, css_class="h-16"
                        
                    )
            with Card():
                with CardHeader():
                    CardTitle("Towel Incidents")
                with CardContent():
                    BarChart(
                        data=[
                            {"month": "Jan", "lost": 8, "found": 5},
                            {"month": "Feb", "lost": 24, "found": 15},
                            {"month": "Mar", "lost": 12, "found": 28},
                            {"month": "Apr", "lost": 35, "found": 19},
                            {"month": "May", "lost": 18, "found": 38},
                            {"month": "Jun", "lost": 42, "found": 30},
                        ],
                        series=[
                            ChartSeries(
                                dataKey="lost", label="Lost",
                            ),
                            ChartSeries(
                                dataKey="found", label="Found",
                            ),
                        ],
                        x_axis="month", height=200, bar_radius=4,
                        show_legend=True, show_tooltip=True,
                        show_grid=True,
                    )

            with Grid(columns=2, gap=4):
                with Column(gap=4):
                    with Card():
                        with CardContent():
                            with Column(gap=2):
                                Checkbox(
                                    label="Towel packed",
                                    value=True,
                                )
                                Checkbox(
                                    label="Guide charged",
                                    value=True,
                                )
                                Checkbox(
                                    label="Babel fish inserted",
                                    value=False,
                                )
                    with If("{{ !pressed }}"):
                        Button(
                            "This is probably the best "
                            "button to press.",
                            variant="success",
                            on_click=SetState(
                                "pressed", True,
                            ),
                        )
                    with Else():
                        Button(
                            "Please do not press this "
                            "button again.",
                            variant="destructive",
                            on_click=SetState(
                                "pressed", False,
                            ),
                        )

                    with Card():
                        with CardHeader():
                            CardTitle("Marvin's Mood")
                        with CardContent():
                            with Column(gap=3):
                                P("How's life?")
                                with Column(gap=2):
                                    Button(
                                        "Meh",
                                        on_click=ShowToast(
                                            "Noted. Enthusiasm "
                                            "levels nominal."
                                        ),
                                    )
                                    Button(
                                        "Depressed",
                                        variant="info",
                                        on_click=ShowToast(
                                            "I think you ought to "
                                            "know I'm feeling very "
                                            "depressed."
                                        ),
                                    )
                                    Button(
                                        "Don't talk to me about life",
                                        variant="warning",
                                        on_click=ShowToast(
                                            "Brain the size of a "
                                            "planet and they ask me "
                                            "to pick up a piece of "
                                            "paper."
                                        ),
                                    )
                        

                with Column(gap=4):
                    with Column(gap=3):
                        with Alert(variant="destructive", icon="triangle-alert"):
                            AlertTitle("Beware of the Leopard")
                    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"},
                                ],
                                search=True, paginated=False,
                            )
                    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 grid-cols-1 md:grid-cols-2 lg:grid-cols-4",
    "type": "Grid",
    "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": "owner",
                        "type": "Input",
                        "inputType": "text",
                        "placeholder": "Owner name...",
                        "disabled": false,
                        "readOnly": false,
                        "required": false
                      },
                      {
                        "name": "combobox_12",
                        "type": "Combobox",
                        "placeholder": "Type...",
                        "searchPlaceholder": "Search types...",
                        "disabled": false,
                        "invalid": false,
                        "children": [
                          {"type": "ComboboxOption", "value": "bath", "label": "Bath", "disabled": false},
                          {
                            "type": "ComboboxOption",
                            "value": "beach",
                            "label": "Beach",
                            "disabled": false
                          },
                          {
                            "type": "ComboboxOption",
                            "value": "interstellar",
                            "label": "Interstellar",
                            "disabled": false
                          },
                          {
                            "type": "ComboboxOption",
                            "value": "micro",
                            "label": "Microfiber",
                            "disabled": false
                          }
                        ]
                      },
                      {
                        "name": "datepicker_4",
                        "type": "DatePicker",
                        "placeholder": "Registration date"
                      }
                    ]
                  }
                ]
              },
              {
                "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, {{ owner }}. 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": "CardContent",
                "children": [
                  {
                    "cssClass": "gap-2 items-center",
                    "type": "Row",
                    "children": [
                      {"type": "Loader", "variant": "dots", "size": "sm"},
                      {"content": "Marvin is thinking...", "type": "Muted"}
                    ]
                  }
                ]
              }
            ]
          },
          {
            "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,
                                    "max": 100.0,
                                    "variant": "success",
                                    "size": "default"
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "cssClass": "pf-progress-flat",
                        "type": "Progress",
                        "value": 100.0,
                        "max": 100.0,
                        "variant": "default",
                        "size": "default",
                        "indicatorClass": "bg-yellow-400"
                      },
                      {
                        "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,
                        "max": 100.0,
                        "variant": "default",
                        "size": "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": "Badge",
                                "variant": "outline",
                                "children": [
                                  {"type": "Loader", "variant": "ios", "size": "sm"},
                                  {"content": "Soon...", "type": "Text"}
                                ]
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "type": "Progress",
                        "value": 12.0,
                        "max": 100.0,
                        "variant": "default",
                        "size": "default"
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [{"type": "CardTitle", "content": "Planet Ratings"}]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "type": "RadarChart",
                    "data": [
                      {"axis": "Views", "earth": 30, "mag": 95},
                      {"axis": "Fjords", "earth": 65, "mag": 100},
                      {"axis": "Pubs", "earth": 90, "mag": 10},
                      {"axis": "Mice", "earth": 40, "mag": 85},
                      {"axis": "Tea", "earth": 95, "mag": 15},
                      {"axis": "Safety", "earth": 45, "mag": 70}
                    ],
                    "series": [
                      {"dataKey": "earth", "label": "Earth"},
                      {"dataKey": "mag", "label": "Magrathea"}
                    ],
                    "axisKey": "axis",
                    "height": 200,
                    "filled": true,
                    "showDots": false,
                    "showLegend": true,
                    "showTooltip": true,
                    "animate": true,
                    "showGrid": true
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "cssClass": "gap-4",
        "type": "Column",
        "children": [
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [{"type": "CardTitle", "content": "Survival Odds"}]
              },
              {
                "cssClass": "w-fit mx-auto",
                "type": "CardContent",
                "children": [
                  {
                    "type": "Ring",
                    "value": 42.0,
                    "min": 0,
                    "max": 100,
                    "label": "42%",
                    "variant": "info",
                    "size": "lg",
                    "thickness": 12.0,
                    "indicatorClass": "group-hover:drop-shadow-[0_0_24px_rgba(59,130,246,0.9)]"
                  }
                ]
              }
            ]
          },
          {
            "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",
                        "value": 42.0,
                        "type": "Slider",
                        "min": 0.0,
                        "max": 100.0,
                        "disabled": false,
                        "size": "default"
                      },
                      {
                        "cssClass": "items-center justify-between",
                        "type": "Row",
                        "children": [
                          {"content": "Probable", "type": "Muted"},
                          {"content": "Infinite", "type": "Muted"}
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "Alert",
            "variant": "success",
            "icon": "circle-check",
            "children": [
              {"type": "AlertTitle", "content": "Don't Panic"},
              {"type": "AlertDescription", "content": "Normality achieved."}
            ]
          },
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [{"type": "CardTitle", "content": "Prefect Horizon Config"}]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "cssClass": "gap-3",
                    "type": "Column",
                    "children": [
                      {
                        "name": "autoscale",
                        "value": true,
                        "type": "Switch",
                        "label": "Auto-scale agents",
                        "size": "default",
                        "disabled": false,
                        "required": false
                      },
                      {"type": "Separator", "orientation": "horizontal"},
                      {
                        "name": "code_mode",
                        "value": true,
                        "type": "Switch",
                        "label": "Code Mode",
                        "size": "default",
                        "disabled": false,
                        "required": false
                      },
                      {"type": "Separator", "orientation": "horizontal"},
                      {
                        "name": "cache",
                        "value": false,
                        "type": "Switch",
                        "label": "Tool call caching",
                        "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": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [{"type": "CardTitle", "content": "Travel Class"}]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "name": "travel_class",
                    "type": "RadioGroup",
                    "children": [
                      {
                        "name": "radio_16",
                        "value": false,
                        "type": "Radio",
                        "option": "economy",
                        "label": "Economy",
                        "disabled": false,
                        "required": false
                      },
                      {
                        "name": "radio_17",
                        "value": false,
                        "type": "Radio",
                        "option": "business",
                        "label": "Business Class",
                        "disabled": false,
                        "required": false
                      },
                      {
                        "name": "radio_18",
                        "value": true,
                        "type": "Radio",
                        "option": "improbability",
                        "label": "Infinite Improbability",
                        "disabled": false,
                        "required": false
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "cssClass": "md:col-span-2",
        "type": "GridItem",
        "colSpan": 1,
        "rowSpan": 1,
        "children": [
          {
            "cssClass": "gap-4",
            "type": "Column",
            "children": [
              {
                "cssClass": "gap-4 grid-cols-2 h-32",
                "type": "Grid",
                "children": [
                  {
                    "type": "Card",
                    "children": [
                      {
                        "type": "CardHeader",
                        "children": [{"type": "CardTitle", "content": "Context Window"}]
                      },
                      {
                        "type": "CardContent",
                        "children": [
                          {
                            "cssClass": "gap-6 justify-center h-full",
                            "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,
                                    "max": 100.0,
                                    "variant": "default",
                                    "size": "default"
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  },
                  {
                    "cssClass": "pb-0 gap-0",
                    "type": "Card",
                    "children": [
                      {
                        "type": "CardContent",
                        "children": [
                          {
                            "type": "Metric",
                            "label": "Fjords designed",
                            "value": "1,847",
                            "delta": "+3 coastlines"
                          }
                        ]
                      },
                      {
                        "cssClass": "h-16",
                        "type": "Sparkline",
                        "data": [820, 950, 1100, 980, 1250, 1400, 1350, 1500, 1680, 1847],
                        "variant": "success",
                        "fill": true,
                        "curve": "linear",
                        "strokeWidth": 1.5
                      }
                    ]
                  }
                ]
              },
              {
                "type": "Card",
                "children": [
                  {
                    "type": "CardHeader",
                    "children": [{"type": "CardTitle", "content": "Towel Incidents"}]
                  },
                  {
                    "type": "CardContent",
                    "children": [
                      {
                        "type": "BarChart",
                        "data": [
                          {"month": "Jan", "lost": 8, "found": 5},
                          {"month": "Feb", "lost": 24, "found": 15},
                          {"month": "Mar", "lost": 12, "found": 28},
                          {"month": "Apr", "lost": 35, "found": 19},
                          {"month": "May", "lost": 18, "found": 38},
                          {"month": "Jun", "lost": 42, "found": 30}
                        ],
                        "series": [{"dataKey": "lost", "label": "Lost"}, {"dataKey": "found", "label": "Found"}],
                        "xAxis": "month",
                        "height": 200,
                        "stacked": false,
                        "horizontal": false,
                        "barRadius": 4,
                        "showLegend": true,
                        "showTooltip": true,
                        "animate": true,
                        "showGrid": true,
                        "showYAxis": true,
                        "yAxisFormat": "auto"
                      }
                    ]
                  }
                ]
              },
              {
                "cssClass": "gap-4 grid-cols-2",
                "type": "Grid",
                "children": [
                  {
                    "cssClass": "gap-4",
                    "type": "Column",
                    "children": [
                      {
                        "type": "Card",
                        "children": [
                          {
                            "type": "CardContent",
                            "children": [
                              {
                                "cssClass": "gap-2",
                                "type": "Column",
                                "children": [
                                  {
                                    "name": "checkbox_12",
                                    "value": true,
                                    "type": "Checkbox",
                                    "label": "Towel packed",
                                    "disabled": false,
                                    "required": false
                                  },
                                  {
                                    "name": "checkbox_13",
                                    "value": true,
                                    "type": "Checkbox",
                                    "label": "Guide charged",
                                    "disabled": false,
                                    "required": false
                                  },
                                  {
                                    "name": "checkbox_14",
                                    "value": false,
                                    "type": "Checkbox",
                                    "label": "Babel fish inserted",
                                    "disabled": false,
                                    "required": false
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "type": "Condition",
                        "cases": [
                          {
                            "when": "{{ !pressed }}",
                            "children": [
                              {
                                "type": "Button",
                                "label": "This is probably the best button to press.",
                                "variant": "success",
                                "size": "default",
                                "disabled": false,
                                "onClick": {"action": "setState", "key": "pressed", "value": true}
                              }
                            ]
                          }
                        ],
                        "else": [
                          {
                            "type": "Button",
                            "label": "Please do not press this button again.",
                            "variant": "destructive",
                            "size": "default",
                            "disabled": false,
                            "onClick": {"action": "setState", "key": "pressed", "value": false}
                          }
                        ]
                      },
                      {
                        "type": "Card",
                        "children": [
                          {
                            "type": "CardHeader",
                            "children": [{"type": "CardTitle", "content": "Marvin's Mood"}]
                          },
                          {
                            "type": "CardContent",
                            "children": [
                              {
                                "cssClass": "gap-3",
                                "type": "Column",
                                "children": [
                                  {"content": "How's life?", "type": "P"},
                                  {
                                    "cssClass": "gap-2",
                                    "type": "Column",
                                    "children": [
                                      {
                                        "type": "Button",
                                        "label": "Meh",
                                        "variant": "default",
                                        "size": "default",
                                        "disabled": false,
                                        "onClick": {"action": "showToast", "message": "Noted. Enthusiasm levels nominal."}
                                      },
                                      {
                                        "type": "Button",
                                        "label": "Depressed",
                                        "variant": "info",
                                        "size": "default",
                                        "disabled": false,
                                        "onClick": {
                                          "action": "showToast",
                                          "message": "I think you ought to know I'm feeling very depressed."
                                        }
                                      },
                                      {
                                        "type": "Button",
                                        "label": "Don't talk to me about life",
                                        "variant": "warning",
                                        "size": "default",
                                        "disabled": false,
                                        "onClick": {
                                          "action": "showToast",
                                          "message": "Brain the size of a planet and they ask me to pick up a piece of paper."
                                        }
                                      }
                                    ]
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  },
                  {
                    "cssClass": "gap-4",
                    "type": "Column",
                    "children": [
                      {
                        "cssClass": "gap-3",
                        "type": "Column",
                        "children": [
                          {
                            "type": "Alert",
                            "variant": "destructive",
                            "icon": "triangle-alert",
                            "children": [{"type": "AlertTitle", "content": "Beware of the Leopard"}]
                          }
                        ]
                      },
                      {
                        "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"
                                  }
                                ],
                                "search": true,
                                "paginated": false,
                                "pageSize": 10
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "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,
                                                "max": 100.0,
                                                "variant": "default",
                                                "size": "default"
                                              }
                                            ]
                                          }
                                        ]
                                      }
                                    ]
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  "state": {
    "improbability": 42.0,
    "autoscale": true,
    "code_mode": true,
    "cache": false,
    "radio_16": false,
    "radio_17": false,
    "radio_18": true,
    "checkbox_12": true,
    "checkbox_13": true,
    "checkbox_14": false
  }
}
```
</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 | default:world }}!","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 | default:world }}","variant":"default"},{"type":"Badge","label":"Prefab","variant":"success"}]}]}]}}} playground=" ">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Card, CardContent, CardFooter, Column, H3, Muted, Input, Badge, Row
from prefab_ui.rx import Rx

name = Rx("name").default("world")

with Card():
    with CardContent():
        with Column(gap=3):
            H3(f"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(f"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 | default:world }}!", "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 | default:world }}",
                "variant": "default"
              },
              {"type": "Badge", "label": "Prefab", "variant": "success"}
            ]
          }
        ]
      }
    ]
  }
}
```
</CodeGroup>
</ComponentPreview>

## Installation

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

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

## What's in the Box

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/getting-started/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="/concepts/actions">
    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>

