Today we are releasing Hashbrown v0.5.
This release focuses on a problem we keep running into while building AI features in real applications: it is not enough to get a model to return the right final answer. The application needs to stay responsive while the model is still working. The UI needs to be made from trusted components. The schema needs to be clear enough for the model to follow and strict enough for the app to trust.
That is the shape Hashbrown is built around.
Hashbrown is an open source framework for building generative user interfaces in React and Angular. You define the components, tools, and schemas your app supports. The model can choose from that trusted set, and Hashbrown streams the result back into your application.
With v0.5, we spent a lot of time tightening the foundation.
Release at a glance
- UI Kits for packaging reusable generative UI component sets.
- A rebuilt streaming JSON parser with parser-node state and better identity preservation.
- Improved Skillet schemas, including Standard JSON Schema support.
- Magic Text docs and React rendering support for streaming Markdown.
- Better docs for JSON parsing, UI Kits, CopilotKit, and migration from v0.4 output shapes.
- A refreshed homepage and Fast Food nutrition sample for the v0.5 story.
Why this release matters
Generative UI sounds simple until you try to ship it.
You want the model to render something useful, but you probably do not want it inventing arbitrary markup. You want streaming, but you do not want half-parsed JSON breaking your app. You want reusable patterns, but you do not want every screen hand-wiring the same component list, examples, and schema rules.
From my experience, the hard part is not calling a model. The hard part is making the model fit into the rest of the application.
Hashbrown v0.5 is about making that fit more explicit.
UI Kits
The biggest new primitive in v0.5 is UI Kits.
A UI Kit lets you package a set of trusted components into a reusable generative UI building block. Instead of passing the same component definitions everywhere, you can define a kit once and reuse it across chats, completions, examples, and direct rendering.
The goal is pretty straightforward:
const kit = useUiKit({
components: [
exposeComponent(Card, { ... }),
exposeComponent(Chart, { ... }),
exposeComponent(Metric, { ... }),
],
});
This is not necessary for every project. If you have one chat surface with a small number of components, passing components directly is fine. But as soon as you have a few related UI surfaces, UI Kits give you a better place to organize that contract.
The beauty of this approach is that the kit is still just your app's components. Hashbrown is not asking you to move into a separate UI runtime. It is giving the model a safe, typed description of the components you already trust.
Read the UI Kits recipe for React or UI Kits recipe for Angular to get started.
A rebuilt streaming JSON parser
Hashbrown v0.5 also includes a rebuilt streaming JSON parser.
This parser powers structured output and generative UI internally, but you can also use it directly from React and Angular. It parses JSON as text arrives, exposes parser state, and resolves partial values through Skillet schemas.
That matters because LLMs do not produce JSON all at once. They produce it one token at a time.
A normal JSON parser waits until the document is complete. Hashbrown's parser can tell you what is known right now:
- Which nodes are open or closed.
- Which values are partially available.
- Which object and array references can be preserved between updates.
- Which values match the schema as the response streams.
This unlocks a better user experience. Your app can show progress as the model is still writing, without treating every partial token as a finished value.
You can use the parser directly with React and Angular.
Skillet schema improvements
Skillet is Hashbrown's schema language. It is Zod-like, but intentionally limited to the shapes that LLM providers can realistically follow.
In v0.5, Skillet gets a few important improvements.
First, schemas now more closely match the JSON we ask the model to produce. Earlier versions relied more heavily on special discriminator helpers for complex anyOf cases. That worked, but it made the generated JSON harder to reason about and harder for some models to follow.
Next, Hashbrown can now ingest Standard JSON Schema objects. That means libraries that implement the ~standard schema interface can be normalized into Skillet at the Hashbrown boundary. Internally, Hashbrown still uses Skillet for parsing, validation, streaming, and rendering.
Finally, s.node(...) gives you access to parser-node metadata for a value. This is especially useful for generative UI props, where a component may want to know whether its props are still streaming or complete.
Let's break that down with a small example:
const markdown = s.object('Markdown component', {
children: s.node(s.streaming.string('Markdown content')),
});
The model still writes the inner value. Your app can read the resolved node state.
Magic Text
LLMs are good at producing Markdown, but most Markdown parsers assume the string is complete.
That is a mismatch for streaming.
Magic Text is Hashbrown's optimistic Markdown parser for streaming model output. It can render partial Markdown while text is still arriving, then converge on the final structure when the stream completes.
In v0.5, we expanded the Magic Text docs and added React support. You can use it for normal streaming assistant output, citations, and custom renderers.
For my use case, this is one of those features that feels small until it is missing. Streaming text should not flash broken Markdown syntax at users. It should feel like the interface understands that the response is still being written.
Start with the React Magic Text recipe or the Angular Magic Text recipe.
Documentation and examples
We also did a lot of release prep around the docs.
The v0.5 docs now include:
- Magic Text recipes for React and Angular.
- UI Kit recipes for React and Angular.
- Streaming JSON parser recipes for React and Angular.
- A CopilotKit recipe for React.
- Migration notes for persisted v0.4 JSON output.
- A refreshed homepage that explains the current Hashbrown capabilities.
We also cleaned up and deployed the Fast Food nutrition sample. That sample is useful because it exercises the kind of product workflow Hashbrown is meant for: structured data, model-assisted exploration, charts, and a real UI around the generated output.
Getting CI green is important. Getting a sample app to feel developer-green and user-green matters too.
Migrating from v0.4
Most apps do not need to do anything special.
The migration notes are only relevant if you persisted raw JSON generated from Hashbrown v0.4 schemas and now want to read that stored JSON with v0.5 code.
We decided not to add a public migration helper yet. That would expand the API surface for something most applications will never need. Instead, the docs explain the old shapes and the new shapes so teams with persisted output can handle that migration in their own data layer.
Your mileage may vary, but I think that is the right tradeoff for now.
Read the React migration notes or Angular migration notes for the details.
What to try next
If you are new to Hashbrown, start with the generative UI docs for React or Angular.
If you already have a Hashbrown app, I would look at UI Kits first. They are the clearest path to organizing reusable generative UI patterns without making every chat or completion know about every component directly.
And if you are building anything that consumes streamed JSON, take a look at the new JSON parser APIs. They are useful even outside of a full chat experience.
Hashbrown v0.5 is not a new runtime and it is not magic. It is a practical set of tools for making model output fit into real React and Angular applications.
