Skip to main content
api.mzizi.dev is the registry API. It is served by mzizi-dev/mzizi-api-gateway, a Hono Cloudflare Worker written in TypeScript. It has no origin, no database and no Supabase. Everything it serves is a file from the registry repository, bundled into the Worker when it is built. It has served api.mzizi.dev since 29 September 2026, when it took over from the registry’s own Worker.
An earlier plan for this repository was a pure-Rust workers-rs proxy in front of the registry’s own API handlers. That proxy is retired, and so are the handlers: the registry removed its Next.js app, /api/* handlers included, on 2 October 2026. The gateway is Hono, and it implements the whole public /v1 API itself, from files.

Using it

No sign-in and no key. The API is read-only: a path with a GET handler answers OPTIONS with 204, and every other method with 405. Both /v1/... (canonical) and /api/v1/... answer. api.mzizi.dev/v1/* redirects here. Every response carries a header naming the Worker and the registry commit it was built from. The pin moves (see how the pin moves), so read it from the header rather than from this page:
The answer has this shape, with the first twelve characters of the pinned registry commit:
For example, on 30 September 2026 it read registry=9b86e034ffd8. That is an example, not the current value; the header is. From registry commit 9b86e03 on, /v1/rs/{name} serves the twelve Mzizi Roots brand components, and its crate field names each component’s own crate, with a git field for the source repository. See the Rust route.

How the data flows

Three properties follow from that shape:
  • The registry’s files are the data layer. Components, doctrine, brand, changelog, skills and samples are files in mzizi-dev/mzizi-registry. The gateway reads them at build time, not at request time.
  • The shapes are the registry’s own. The build calls the registry’s readers rather than reimplementing them. The Supabase client is replaced with a stub that throws, so a reader that reached for a database would fail the build instead of shipping an empty answer.
  • A registry change reaches the API only through a commit. Moving to newer registry content means changing the pin, which CI checks. A bot is built to open that commit: see how the pin moves.
The bundle is about 917 KiB gzipped, well under the Workers limit, so the data ships inside the Worker rather than in separate storage.

How the pin moves

The pin is ref in the gateway’s scripts/registry-ref.json. The owner decided on 30 September 2026 to keep the pin and move it automatically, and the gateway has a bot built to keep it on registry main. The gateway’s README describes it under Registry pin bump.
  1. Every hour the bot compares the pin with registry main. When they differ, it opens or updates one pull request, from the branch bot/registry-pin, that moves the pin. The pull request lists the registry commits the bump brings in.
  2. Every check runs on it, including parity in strict mode against production https://api.mzizi.dev: any difference at all between the bump and what is live fails it.
  3. It merges itself (rebase) only when every check is green, including parity and the checks main’s rules require. The merge deploys as usual.
  4. Anything else waits for a person. A failed check gets a comment listing what failed, and the bot leaves the pull request for review. An unexplained parity difference usually means the registry changed a file the gateway reads, and the gateway’s route has to follow it.
The bot runs on its own token, the RELEASE_BUMP_TOKEN Actions secret (a fine-grained token with Contents, Pull requests and Workflows read and write), and it is live: on 2 October 2026 it opened mzizi-api-gateway#29 and, for the MCP server’s pin, agent-tools#169. It merges its own pull request only if the token also has Checks: Read-only and Commit statuses: Read-only, because it reads the bump’s check runs and commit status before merging; without them that read fails with a 403 and the pull request waits for a person. A bump by hand keeps working too, and the bot steps aside for it: while another open pull request moves the pin to registry main it opens none, and when a bump lands any other way it closes its own. The MCP server’s pin has the same bot.

What it answers besides data

  • 308 for renamed components. Former nyuchi-* names redirect to their mzizi-* names on /v1/ui and /v1/rs, keeping the sub-path and query. For example, /v1/ui/nyuchi-sidebar answers 308 to /v1/ui/mzizi-sidebar.
  • 410 Gone for retired routes: /v1/docs, and the retired axis and layer models under /v1/architecture/.
  • 308 /mcp to https://mcp.mzizi.dev/mcp.
  • /.well-known/security.txt, with the contact security@nyuchi.com.
/v1/search searches the registry’s files. It takes up to three parameters, which combine, and at least one is required: layer is a deprecated alias of node, kept so older clients keep their results. A request that uses it gets the same results, plus a Deprecation: true header and a meta.deprecation note. node wins when both are given. Use node; layer will be removed.

The Rust route

/v1/rs/{name} answers with a component’s Rust (Dioxus) source where one exists, and 404 where there is none. The document names the crate the component ships in, and the crate differs by node: mzizi-ui for the primitives, mzizi-brand for the brand components, mzizi-shell for the app chrome, and so on. For example, on 30 September 2026:
Read the crate field rather than assuming one crate for every component. The route is a read surface: to use a component, depend on its crate. See Mzizi Roots.

One route answers 503

/v1/ui/{name}/versions answers 503. Component version history is written by releases into the console’s database, and it is not one of the registry’s files, so this API does not serve it. The response says so and points to /v1/changelog for release history. Earlier builds also answered 503 on /v1/search, /v1/ui/{name}/docs and /v1/ai/instructions/{name}. Their data is in files, and from registry commit ce68c64 they are served from files. The discovery document no longer carries a database block; its data block reads "source": "files".

The discovery document and OpenAPI text

/v1 and /openapi are served from the registry, and from ce68c64 on both say that files are the data layer and that Mzizi owns and operates the API. Neither names Supabase as a data source or Nyuchi as operator. Two mentions of Supabase remain in /openapi, and both are accurate: the /data-layer route describes the wider ecosystem’s data layer, and the retired /docs route notes that its old table is historical.

Parity

The acceptance test for the cutover was scripts/parity.mjs. It sends read-only requests to a baseline and a candidate: every route, every component slug on /v1/ui/{name} and /v1/rs/{name}, the renamed names, the filters, the error paths and the method handling. It diffs status, Location, content type, the CORS, cache and security headers, and the body. Intentional differences are listed in the script with their reasons. Before the domain moved, parity against the deployed Worker ran 1,359 requests with 0 unexplained differences. Only two differences are intentional: the bare /v1 now serves the discovery document instead of an HTML 404, and an unknown path gets a small JSON 404.

Rollback, in brief

There is no older Worker to fall back to. The registry’s own Worker served the app the registry removed on 2 October 2026, and it is being deleted, so api.mzizi.dev stays on the gateway. To undo a bad change, revert it in a pull request; the merge redeploys. To undo a bad deploy faster than that, roll the mzizi-api-gateway Worker back to its previous deployment (wrangler rollback, or Deployments in the Cloudflare dashboard), then revert on main so the next deploy does not bring the change back.

Developing

The repository is rebase-only. See its CONTRIBUTING.md for changing a route or moving the pin.