Prefab: a Python UI framework that renders components through React
🎨 The generative UI framework that even humans can use.
At a glance
- What is it?
- Prefab is a Python DSL for composing interactive interfaces out of more than a hundred prebuilt components, which compile to a JSON protocol and get rendered by a bundled React frontend. It is aimed at Python tool builders and at agents generating interfaces, and it ships as a package called prefab-ui.
- Who is it for?
- Prefab suits Python developers who need to ship an interactive interface next to their logic, especially MCP server authors and anyone building dashboards or forms, because the definition stays in Python and the output is a serializable component tree.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly HTML, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A component tree in Python that compiles to JSON
Prefab is a UI framework for building rich, interactive interfaces in Python. The stated use cases are MCP Apps, data dashboards and interactive tools, assembled from a library of more than a hundred prebuilt components, with a bundled React renderer that turns the result into a self-contained application.
The mechanism is a domain specific language built on Python context managers. A component tree is declared with nested with blocks, and the tree compiles to a JSON protocol that a separate React frontend, built on shadcn/ui, renders. The interface definition therefore stays in Python next to the data it presents.
The documentation is explicit about the design goal: the north star is composition, not construction. The intent is assembling existing components into interfaces rather than authoring new components in Python. That single sentence explains most of the framework's trade-offs, including its main limitation, which is that a design nobody anticipated as a component has to be built in the React renderer rather than in the Python layer.
The output is declarative and serializable, and the project argues that this is what makes interfaces safe for agents to generate, simple to validate and portable across any transport. A JSON tree can be checked by a schema, shipped over a wire and rendered identically by the same bundle, which is the property that makes the agent use case work at all.
The hello world is a card with a reactive binding
The example the project leads with is an interactive card, and it is worth reading closely because it shows the whole model in a dozen lines.
from prefab_ui.components import *
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")Three things are happening. The with blocks build the component hierarchy, so nesting in the source is nesting in the interface. The Rx class binds a named piece of client-side state, and its default method supplies a fallback value used before the user types anything. And the interpolated values, the H3 heading and the first Badge, read that same binding, so the text updates as the input changes without any JavaScript being written.
The project describes the DSL as token-efficient and streaming-compatible as a result of using context managers, which is a practical point for agent use: a generated interface is a sequence of small declarative statements, and it can be emitted progressively rather than assembled and then serialized. The reactive state system handles client-side interactivity with no JavaScript required.
Installing is one pip command on Python 3.10
The package is published to PyPI as prefab-ui, and the installation is a single command:
pip install prefab-uiPython 3.10 or newer is required, which matches the requires-python setting in the project metadata and the classifiers that list support for 3.10 through 3.13. The package declares a Typing :: Typed classifier, so type information ships with the distribution.
The runtime dependencies are modest for a UI framework: pydantic at version 2.11 or newer, cyclopts at version 4 or newer, and rich at version 13 or newer. No React toolchain is needed to install or import the package, because the renderer is a prebuilt static bundle that ships with it. That is the point of the bundled renderer approach, and it is a real difference from frameworks that expect a Node build step in your pipeline.
A console script is registered as prefab, pointing at the CLI entry point in the package. The repository also ships a justfile, so the development workflow is driven by tasks such as these:
uv run --frozen pytest -xvs tests
uv run --frozen ty check
uv run --frozen prek run --all-filesThose three are the test suite, the type checker and the pre-commit hooks respectively, all pinned to a frozen environment. The presence of a separate renderer development server, started with npm run dev inside the renderer directory, tells you that the React side has its own toolchain even though consumers of the package never touch it.
Built for MCP Apps rather than for dashboards
The project says it was designed from the ground up for MCP Apps, bringing interactive frontend capabilities to the Python MCP ecosystem, and that it ships as a native part of FastMCP. The scope of support covers everything from hand-authored declarative interfaces to fully agent-generated UIs within one framework.
The transport options are described as MCP and REST backends supported out of the box, optionally. That is the practical shape of the thing: the component tree is data, so it can travel over MCP or over a conventional HTTP API, and the renderer is a static bundle that a client loads.
The inspiration is stated as FastUI, which pioneered declarative component protocols rendered by a separate frontend. Prefab takes that idea into the MCP ecosystem with a self-contained static renderer and a DSL meant to serve both developers and agents. The design influence is worth naming because it explains the unusual split: a Python package that emits a protocol, plus a frontend that knows how to draw that protocol, with no bespoke per-project frontend work.
The examples directory shows the range of shapes the framework is meant to cover, including budget-allocator, custom-pipes, forms, generative-ui, hitchhikers-guide, mini, presentation, pypi-downloads and todo. A forms example and a todo example are the most direct demonstrations, and a generative-ui example is the clearest statement of the agent angle.
Choosing between composition and building your own
The alternative to Prefab is the path most Python projects have taken: a separate frontend codebase, a JavaScript or TypeScript build, and a hand-written API contract between the two halves. The framework's argument against that path is that it means working in two languages and two ecosystems for what are often small interfaces, and the argument for it is equally real, because a bespoke React tree can do anything and a component protocol can only do what the component library covers.
That is the real trade-off. Prefab wins when the interface is made of standard pieces, a dashboard, a form, a card, a table, a chart, because assembling them is fast and the result is agent-generatable. It loses when the design is genuinely custom, because then you are back to writing React, and the Python layer becomes a serialization layer for markup someone else wrote.
There is a middle path worth knowing about, and the project is open about it. The protocol reference pages are generated from the Pydantic models of the components, which means the component set is introspectable and a schema can be validated against. A custom component therefore has to be added to the renderer and then declared in Python, which is a bigger change than writing a React component in a separate frontend project.
The framework is also young in practical terms. The releases move fast, with v0.20.0, v0.20.1 and v0.20.2 all landing within a few weeks in May and June 2026, and the documentation itself carries a warning that the project is under very active development. A version numbered 0.20 signals a surface that is still changing, and the versioning scheme built from git tags with a bump setting means the package version moves with commits rather than with a hand-managed release plan.
Apache-2.0 with a very recent push and fast moving tags
The licence is Apache-2.0, declared in the project metadata and covered by the LICENSE file at the repository root. The package metadata also lists the license classifier as Apache Software License, and the source tree carries a .pre-commit-config.yaml, an AGENTS.md and a CLAUDE.md, which suggests the project is being worked on with tooling aimed at automated contributors.
The repository is not archived, and the last push was on 2026-10-18, on the default branch named main. The most recent releases are v0.20.2, titled Fine Print, from 2026-06-03, v0.20.1, titled Wire Fraud, from 2026-05-23, and v0.20.0, titled Wire Transfer, from 2026-05-23.
Two observations follow. The release titles are playful, and the spacing between them is short, so pinning to a tag is reasonable but expecting stability between tags is not. And the gap between a June release and an October push means the branch head is well ahead of the last published version, so a decision to depend on prefab-ui is a decision about whether to pin, and if so which pin.
The VISION.md file at the root and the dev-docs directory are where the longer-term direction is written down, and the docs directory carries a VISION.md alongside the site content. For a framework whose stated purpose is to be generated by agents, having the intended end state written in the repository rather than only in announcements is a reasonable sign of how the maintainers intend to work.
Editorial conclusion
Prefab suits Python developers who need to ship an interactive interface next to their logic, especially MCP server authors and anyone building dashboards or forms, because the definition stays in Python and the output is a serializable component tree. It does not suit a team that wants full control of bespoke React components, since the north star is assembling existing components rather than authoring new ones, and it is Apache-2.0 with a moving surface while releases are still frequent. Before adopting it, install prefab-ui on Python 3.10 or newer, run the hello world card in the playground, and check whether the MCP backend or the REST backend matches the transport you already use.
Frequently asked questions
How do I install Prefab?
Install the package prefab-ui from PyPI with pip install prefab-ui. Python 3.10 or newer is required, and the runtime dependencies are pydantic, cyclopts and rich, so no Node build step is needed to use the bundled renderer.
What does the Prefab Python DSL produce?
The component tree compiles to a JSON protocol which a bundled React frontend built on shadcn/ui renders. The interface definition stays in Python, and the output is declarative and serializable, which is what makes it portable across transports.
How does Prefab handle interactivity without JavaScript?
The reactive Rx class binds a named piece of client-side state, and components read that binding. In the hello world card, the heading and a badge both interpolate the same Rx value bound to a text input, so the text updates as the user types.
Is Prefab related to MCP?
Yes. The project states it was designed from the ground up for MCP Apps and ships as a native part of FastMCP, with MCP and REST backends supported out of the box, alongside fully agent-generated interfaces.
Can I build my own components with Prefab?
The stated north star is composition rather than construction, meaning assembling existing components into interfaces. A component that does not exist in the library has to be added to the React renderer and then declared in Python, so the Python layer is not the place to author new visual components.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/prefecthq-prefab)Was this useful?