The anatomy
A complete component in four files: a product card that shows as a compact tile, and opens into a full page.- The envelope declares the faces.
gridandpageare the two states this card can be in. The first declared is where it arrives. - Every state names its layout.
layout: layouts/gridis a path, so nothing is assumed from the state’s name. - The card opens itself. The tile is a
Buttonwhose action writesstate: pageinto the card’s own data, and the page writes it back. Each state may name itsplace:, so the card moves from the rail to the main panel and back. - Prop defaults are the preview. studio draws the card from them before any workflow exists, so write realistic content.
root: tree, no
states and no manifest, is a complete component.
Two tiers. Your components live in components/ at the root of your org repo and
belong to that org alone. Two orgs may each have a component of the same name, because the
org is part of what an item is. The design system’s are shared by every org. Yours may reference a design-system
component, never the reverse, and may never take a design-system name. Both are lint
errors.
Where each thing lives
Everything a component shows has exactly one home, and the lint rejects anything in the wrong one:
Declare in
props every field the outside can fill, and mark each one input: true: those
are the fields on the component’s tool. A prop marked input: false keeps its default and is
never on the tool. A
prop typed unoverse-markdown is a body: the platform compiles the document’s typed
components onto that field, from the atoms in the markdown category, so the prop’s
description is the whole instruction for the body. Any prop can take the type,
whatever fills it. Bind it to a Markdown primitive by name. An
array, an object or a URL in values: is the tell for a mistake. That is content to
hardcode, or data to declare as a prop. Anything computed is computed in the workflow and
arrives as a plain field.
Prop names are the data contract. Source data fills a component by name, with no
mapping layer. A bind whose name the source does not carry renders the preview default
instead. That failure is quiet and specific: the title streams in while the image and
tagline stay on their mocks. Rename the prop to match the source field, and never add
glue.
A component fed by your content binds to a fixed set of field names.
Interface data lists them, and names which of them arrive with
the delivery and which are fetched when a detail state opens.
A component can also fetch its own data at a declared moment, such as a page hydrating
when it opens. Lifecycle hooks is the one code carve-out.
States
A component with more than one arrangement declares a state tree. External states sit at the top level, and internal steps nest inside them:grid for
the compact face and page for the full detail face are the standard names, so a card
using them matches any template, in any org, with no mapping.
One question settles the first decision:
If the screen must rearrange to show it, make it external. If nothing would move, nest it.The same product is a compact tile in
grid and a full page in page. Both move the
screen, so both are external. Stepping from detail to apply inside that page moves nothing,
so it nests.
State is the full model: what writes a state, how everything else reacts,
and how to model a tree well.
Describing a field
Describe what a field is on its prop, the same way you would document any parameter. The prop is the field’s whole contract: what it is, whether the outside fills it, and its limits.input decides who fills it. input: true puts the field on the component’s tool, so an
Agent or a workflow writes it. input: false keeps it the component’s own, drawn from its
default. That is the only switch: there is no separate writer role and nothing on the
layout grants it.
Two things come from writing that description well:
- Any Agent using the component knows what belongs in the field.
- unoverse can fill the field for you. An Agent writes the content from your description, drawing on search results rather than inventing anything.
maxLength. A list says the count it
should hold, and describes its items the same way:
How an Agent finds it
Yourmanifest.yaml carries the four fields that decide whether this is ever chosen:
title, description, whenToUse and category. The rules are identical for every kind,
they are enforced by the deploy lint, and
Node discoverability is the contract.
A component that asks
A form or wizard that hands answers back to the Agent needs two things, and nothing else:submit sends back exactly the outputs keys from its own data, and the Agent carries on with
them. The component then steps aside to its card in the conversation, where the person can
reopen it. A ✕ that should stop the
question writes type: cancel, and the Agent hears that the person cancelled.
Steps, tabs and states in between answer nothing. Only submit and cancel do. This is native
MCP elicitation, so a
host like ChatGPT shows its own form from the same outputs.
Next steps
State
The full reaction contract between a component and whatever holds it.
manifest.yaml
Every field a component can declare, with its type.

