> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mzizi.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# The nine primitives

> Nine components written in Mzizi itself, gated in CI. Plus the packaging decision underneath them: primitives are copied source, not crates.

Nine `.mz` files live in `primitives/` in
[`mzizi-dev/mzizi`](https://github.com/mzizi-dev/mzizi). Every one parses clean under
`mz check` and CI gates the whole set on every push, so they are **verified source rather
than aspirational examples**.

| Primitive     | Shape                       | Why it is in the set                                                         |
| ------------- | --------------------------- | ---------------------------------------------------------------------------- |
| `button`      | variant × size              | The most-composed primitive, and the one carrying the touch-floor contract   |
| `input`       | size                        | Form foundation; the other interactive primitive with a touch floor          |
| `badge`       | variant                     | The simplest real variant table                                              |
| `alert`       | variant with an a11y column | A column that is not styling — `announce` pins the ARIA role to the severity |
| `card`        | container                   | Surface plus nested slots                                                    |
| `avatar`      | size, with fallback         | Two columns per variant, and `when` on an optional value                     |
| `separator`   | axis                        | The smallest useful primitive                                                |
| `spinner`     | size, `use motion`          | The capability declaration in practice                                       |
| `confirm_bar` | composition                 | Uses `button` and `alert` **with no import line**                            |

## What a primitive looks like

`button.mz`, in full, is the clearest single demonstration of what the language is for:

```mz primitives/button.mz theme={null}
## The pill button. Always rounded-full per brand; never below the 48px touch floor.
## Corpus reference: n2-primitives/button.tsx (variant + size via cva).
component button

  enum button_variant
    default      class "bg-primary text-primary-foreground hover:bg-primary/80"
    outline      class "border-border bg-input/30 hover:bg-input/50 hover:text-foreground"
    secondary    class "bg-secondary text-secondary-foreground hover:bg-secondary/80"
    ghost        class "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50"
    destructive  class "bg-destructive/10 hover:bg-destructive/20 text-destructive"
    link         class "text-primary underline-offset-4 hover:underline"
  end

  ## Sizes carry their own touch height as data, so the contract below can check every
  ## one of them. In the .tsx these heights live in Tailwind class strings only, which is
  ## how the same rule got violated five separate times across the corpus.
  enum button_size
    default   class "h-14 gap-2 px-5"     height 56
    sm        class "h-12 gap-1.5 px-4"   height 48
    lg        class "h-14 gap-2 px-6"     height 56
    icon      class "size-14"             height 56
    icon_sm   class "size-12"             height 48
  end

  prop variant: button_variant = default
  prop size: button_size = default
  prop label: text
  prop disabled: bool = false
  prop on_tap: event(none)

  view
    control
      slot = "button"
      portal = "https://mzizi.dev/components/button"
      role = "button"
      variant = variant
      size = size
      disabled = disabled
      class = "inline-flex items-center justify-center whitespace-nowrap rounded-full border border-transparent text-sm font-medium transition-all outline-none select-none shrink-0 disabled:pointer-events-none disabled:opacity-50 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] {variant.class} {size.class}"
      text = label
      tap = on_tap
    end
  end

  ## The rule the corpus kept breaking, as one line the compiler can hold us to.
  contract
    every button_size height at_least 48
    button_size.default height 56
    button_size.sm height 48
    button_variant.default class contains "bg-primary"
    slot is "button"
  end

end component button
```

The `height` column is the whole argument in miniature. The touch floor is a rule the
design system's own doctrine calls non-negotiable, and the TypeScript violated it in five
separate components — because there, the heights lived only inside Tailwind class strings,
where nothing could check them. Here the height is data on the variant, so one line holds
the whole table to the floor:

```mz theme={null}
every button_size height at_least 48
```

<Warning>
  That line **parses and is not evaluated.** Contract bodies are syntax today; the checker
  lands with contract evaluation, which is what will finally let `mz check` run them as
  tests. Until then these files are verified syntax and a verified grammar exercise — which
  is what Phase 0 needs and no more than it claims.
</Warning>

## No import lines, and why that is possible

`confirm_bar` uses `button` and `alert` without a single import statement. That follows from
two facts rather than from sloppiness:

* **The namespace is flat and names are globally unique.** The registry already enforces
  one component, one name. A bare `button` in a view is unambiguous.
* **Resolution is by hash, recorded outside the source.** Which `button` a component got is
  pinned in the project manifest, not written into the file. The source says *what*; the
  manifest says *which*. [The IR](/ir) is the mechanism underneath this.

So every import line in every component — ceremony carrying no decision, FM-6 — simply does
not exist. `use` in Mzizi is reserved for capabilities (`use motion`), which *is* a decision
and one worth reading.

## Primitives are not crates

This is the load-bearing packaging decision, and the answer differs by tier rather than
being uniform.

<Tabs>
  <Tab title="Toolchain and runtime — yes, crates">
    `mz`, the compiler and the runtime host bindings are ordinary Rust software. Cargo is
    the best package manager in existence and RFC-0002 §3 already names its UX as the bar
    to hit; there is nothing to gain from inventing a second one. An app depends on the
    runtime crate for its target (web / native / edge).

    <Note>
      The intended distribution is `cargo install mz`. It does not exist — the crate is
      `version = "0.0.0"`, `publish = false`, and unreleased. Build from source.
    </Note>
  </Tab>

  <Tab title="Primitives and components — no, not crates">
    Primitives are **`.mz` source, content-addressed, copied into your project** — the
    registry model, not a linked dependency. Four reasons, in order of weight:

    1. **Content addressing and semver are opposed.** A component *is* its hash; a crate
       dependency is a name resolving to a mutable version range. Shipping primitives as
       crates would forfeit all four wins content addressing buys.
    2. **The small-model target needs the source in context.** A vendored primitive is in
       the repository — readable, editable, patchable by whatever model is working. A crate
       dependency lives in `~/.cargo`: invisible to the agent, unpatchable without a fork.
    3. **You own the code.** A primitive you can edit is a primitive you can fix, without
       waiting on an upstream release.
    4. **Bandwidth is a real constraint.** One file over a slow link beats resolving and
       downloading a dependency tree. Not hypothetical for the people this is built for.
  </Tab>

  <Tab title="Rust interop — crates, when needed">
    Candle, `workers-rs`, and anything else from the Rust ecosystem come in as normal
    crates, at the runtime boundary. The escape hatch stays open; it is just not the
    default path.
  </Tab>
</Tabs>

## Where the primitives came from

Each file names its corpus reference in a doc comment — `button.mz` points at
`n2-primitives/button.tsx`, `connectivity_bar.mz` at `n7-shell/nyuchi-connectivity-bar`.
These are hand ports of components that already exist in the
[Mzizi registry](/ecosystem) with working TypeScript and partially-ported
Rust implementations, which is what makes them ground truth rather than invention. The same
corpus is the Phase 0 [benchmark](/benchmark) task set.
