Skip to main content
In progress. Mzizi Roots is a conversion with its first batch done, not a finished library. The first batch is twelve brand components; most of the registry’s 434 branded items are still React only. The design is docs/roots/RFC-roots.md in the registry, merged with the status “proposed, 2026-09-29”. Where this page and that RFC disagree, the RFC is right.
Mzizi Roots is the name for Mzizi’s own branded components rebuilt in Rust: UI and server components, built for the agentic web. It is where new component work goes.

Rust first

  • Rust is the lead. Where a Rust implementation of a component exists, it is the one to use, and these docs present it first.
  • The React build keeps working. The React and TypeScript (.tsx) components stay in the registry and stay installable. They are deprioritised: not the lead, and not where new work goes. These docs call them the React build.
  • UI and server. Roots covers the handlers that serve a component as well as the component, which is the charter’s full-stack shape for Phase 1.
This follows from the owner’s direction for Mzizi as a whole: the frontend is either Astro with Mzizi UI (Roots) underneath, or pure Rust end to end, and everything built carries a contract. See the roadmap.

How Roots relates to the language

Roots components are written in Rust today, not in Mzizi. The language cannot produce them yet: no component lowers to Rust (a service does, to a local axum package, and a program, to a dependency-free Rust package), and Phase 1 waits on the benchmark (Status). Roots is built to support the language: it is meant to be the language’s component model, the way React is JavaScript’s, with Rust as the platform underneath. When the language lowers components to Rust, Roots is its target: the RFC writes every Roots contract in the language’s contract … end grammar. That is a design intention, gated on the benchmark like the rest of Phase 1. Until then, the components also do a second job. The registry’s components, React and Rust together, are the ground truth for the benchmark’s UI tasks. The nine primitives are hand ports of registry components, and the benchmark scores a candidate against a component’s Rust reference. That is one of the components’ jobs, not what they are, and not the benchmark’s goal, which is Mzizi against the best existing language for each kind of task (the benchmark).

What exists today

The Rust half of the registry lives in mzizi-rs/ in mzizi-dev/mzizi-registry, a Cargo workspace. All fourteen of its crates are on crates.io at 0.7.0 (checked 4 November 2026): eight node crates, one per node that has Rust, two umbrella crates that re-export them, and four supporting crates (mzizi-harness, mzizi-data, mzizi-mongodb and mzizi-activitypub). The crates move together. 0.1.0 was the first release (29 September 2026); 0.2.0 and 0.3.0 were published on 7 October 2026, 0.4.0 on 20 October for registry release v4.9.0, 0.5.0 with registry release v4.16.0, 0.6.0 with v4.17.0 (published 25 October 2026) and 0.7.0 on 1 November 2026. 0.4.0 was breaking for code that builds or matches Inline::Link (links now carry a title) or ListItem::children (now Vec<ListChild>), and 0.5.0 was breaking for mzizi-mongodb, which refuses cross-collection $lookup, $graphLookup and $unionWith in aggregate (use aggregate_joining) and returns Zeroizing wrappers from Uri::password and scram::salted_password. The registry’s changelog has each release in full. The render path. The components are Mzizi’s own, not borrowed from another framework. Their render path is moving to Mzizi’s own render(props) -> String: registry #506 and #510 are merged, with a skeleton and six static primitives. Dioxus is out of the stack (owner, 4 November 2026). The crates published on crates.io (0.7.0) still depend on it, in mzizi-ui, mzizi-brand, mzizi-shell, mzizi-docs and mzizi-roots, and the table below describes them as published. Removing it is tracked in mzizi-registry#635; what renders the Rust components once it is gone is not decided, and this page does not say.

Install

Each umbrella turns every feature on by default. mzizi-roots has the features ui, brand and shell, and always includes mzizi-tokens. mzizi-roots-server has assurance, fundi, docs and discovery; docs brings in the UI dependency that is being removed, because mzizi-docs also carries two documentation renderers. To take less, turn the defaults off and name what you need, or depend on a single node crate:
The node crates are the ones that compile each component, and they keep their names. cargo add takes the newest release, 0.7.0. To write the dependency by hand, use the requirement the crate READMEs use:

The first batch: twelve brand components

The first Roots batch converts twelve N3 brand components, where there was no Rust at all before: mzizi-alert-banner, mzizi-avatar-stack, mzizi-cover-header, mzizi-empty-state, mzizi-escalation-card, mzizi-gauge-card, mzizi-hero-stat, mzizi-meta-tile, mzizi-stats-row, mzizi-success-screen, mzizi-suitability-card and mzizi-user-card. They ship in mzizi-brand. Each one carries a contract, checked against its rendered output. The contract has two parts. The registry contract is the one every component has: one name, one set of variants, the same data-slot, data-portal and tokens as the React build, asserted against the .tsx sibling. On top of that, each module exports clauses in the language’s contract … end grammar, three to eight per component and 65 in all. The crate’s contract suite renders each component and evaluates every clause against the markup it emits. A clause it cannot evaluate fails. For example, from mzizi-alert-banner:
These clauses are evaluated by Rust tests in the registry, not by mz contract. The language’s own evaluator checks a .mz component against itself and cannot read Rust. The ports also fix six defects the React build still has, such as a 40px button under the 48px touch floor and an unclamped aria-valuenow. Each fix has a test.

The Markdown renderer

mzizi-ui carries MarkdownRenderer from 0.2.0. It shows Markdown, including text written by other people, safe by construction: it parses the text into a typed tree of blocks and inlines and renders that tree as UI elements. There is no HTML string anywhere, so there is no dangerous_inner_html to get wrong. Its props include content, links (a MarkdownLinks) and from (a MarkdownSource), and mzizi-roots re-exports mzizi-ui as mzizi_roots::ui through its default ui feature. A usage example is left out while the Rust render path is being replaced (owner, 4 November 2026); the source is at /v1/rs/markdown-renderer. With cargo add mzizi-ui instead, import from mzizi_ui directly.
  • Raw HTML is text. <script>, <img onerror> and <a href> in the source show as written.
  • Links pass an allow-list. By default (MarkdownLinks::Safe) http, https, mailto, tel and relative addresses are kept; MarkdownLinks::Https keeps https only. From 0.3.0, an address with whitespace or a control character inside is refused, and a web address needs a host and no credentials, so https://bank.example@evil.example is refused. A refused link keeps its words and loses its address. http and https links open in a new tab with rel="noopener noreferrer".
  • Rich text. from: MarkdownSource::Html (or Auto) reads an editor’s HTML into the same tree with a small reader that builds plain data, never a DOM. From 0.3.0 a nested list stays nested and <ol start> keeps its first number.
  • heading_base shifts # headings under a page’s own headings.
  • Hostile text stays linear. Each inline parse has a scanning budget, and nesting is bounded.
The Rust build is one of three under one contract, contracts/ui/markdown-renderer (1.1.0): the React build and a pure Astro build are held to the same states, including a hostile one, and the TypeScript and Rust suites run the same 55 shared cases. The Astro build installs from the registry (mzizi add markdown-renderer --target astro); the contract names @bundu/ui/MarkdownRenderer.astro from @bundu/ui 0.6.0, which is not on npm yet (0.5.0 was the latest on 7 October 2026). The Rust source is at /v1/rs/markdown-renderer, which names mzizi-ui, and api.mzizi.dev serves the safe React and Astro builds too.
The MCP server still serves the old React markdown-renderer. On 7 October 2026 mcp.mzizi.dev was pinned at registry 9f3631c (v4.5.0), from before the rebuild. Its mzizi_get_component answer for markdown-renderer leads with that React build, which builds an HTML string and injects it with dangerouslySetInnerHTML, and has no Rust or Astro build. Until the server’s pin moves past registry v4.6.0, install it from api.mzizi.dev: mzizi add markdown-renderer, the crate, or the shadcn command with the URL https://api.mzizi.dev/v1/ui/markdown-renderer. The server’s catalogue.json names its pin in source.registry.

Reading the Rust source

You can read a component’s Rust source over the API:
That route is a read surface, not an install path: depend on the crate instead. Each document’s crate field names the crate its component ships in, so it answers which one to depend on:
From registry commit 9b86e03 on, /v1/rs/{name} serves all twelve brand components, each naming mzizi-brand, alongside the primitives in mzizi-ui, the app chrome in mzizi-shell and the server rungs in their own crates. On 30 September 2026 the API was built from that commit, and so was the MCP server. Both pins move, so read the live one from the source: the API’s x-mzizi-source header, or the MCP server’s catalogue.json. The MCP server is Rust first too: mzizi_get_component leads with the component’s crate, its cargo add line, its contract and its .rs source, then gives the pure Astro build where there is one (from mzizi-mcp 0.12.0), and the React build last.

Where to go next

The registry

How the registry works, and how to install from it today.

The helix

The DNA-helix architecture every component, Rust or React, is placed on.

Browse the components

Every component, grouped by node, at mzizi.dev/components.

The MCP server

Read any component, its tokens and its doctrine from an agent.