Skip to main content
Three enforcement layers catch mistakes for you; one checklist covers what only you can judge. Validation lives in Studio, because Studio is the only thing that publishes: the lint rules below run automatically when you publish, and nothing with errors ships. Errors block; warnings flag judgment calls (e.g. an untyped global slot); hints suggest niceties (a missing states fixture). Each message cites the doc that owns the rule.

πŸ›‘οΈ Layer 1 β€” The JSON Schema (as you type)

rx/_schema/unoverse.schema.json validates every definition in your editor (wiring in 01). Structural, zero false positives. It catches:
  • missing envelope fields (unoverse, kind, name, root; components also need category β€” discovery meta lives in the manifest)
  • an unknown primitive type (the closed set is encoded)
  • broken primitives β€” Switch without cases, Each without template + a list (literal items or bind.items), Ref without ref, ComponentSlot without select
  • illegal conditions β€” only eq / ne / in / truthy exist; and/or/arithmetic are rejected by design (derive in the node, 03)
It validates two shapes: envelope files (with the unoverse field) and bare node partials (layouts/, states/, components/, atoms). One-off sweep of everything from the CLI, if you want it (needs ajv once: npm i -D ajv at the repo root; Studio runs the same schema as you type):

πŸ›‘οΈ Layer 2 β€” The lint rules (Studio, at publish)

The same rules the platform’s guard tests enforce in CI, run by Studio before anything publishes: The platform’s own CI additionally runs the theme-contract and discoverability-meta guards, and the SDK build enforces the closed set at the renderer level β€” you can’t drift past them even if a rule were missed at publish.

πŸ›‘οΈ Layer 3 β€” Your judgment (the conformance checklist)

What no linter can decide β€” audit every artifact against this before calling it done: Structure
  • Structure is earned β€” flat if it can be; components//states//layouts/ only when the shape demands them
  • Few shallow discriminants, not boolean soup; same-shape states collapsed into one data-driven state
  • No self-guarding states; mutually exclusive views in ONE Switch
Data
  • Every bind has a prop/state key with a default
  • Derived values computed in the node, sent as plain fields β€” no logic simulated in the definition
State (04)
  • Reaction contract respected β€” a component writes only its own slice; template surfaces react via select.where; setTemplateValue only for the template’s own chrome
  • Locked state respected β€” lifecycle from derived flags, voice via callState, host chrome via props
Templates (05)
  • No component-type rules in slots; reaction surfaces select by where; components own their size and faces
  • Manifest binds the workflow; whenToUse outcome-first, disqualifies by property
Style (06)
  • Semantic tokens only; no invented component-named tokens

🚒 Ship

Publishing happens in Studio and nowhere else β€” assets never deploy through the core platform:
  1. Preview, mock β€” prop defaults + the state picker; exercise every state fixture.
  2. Preview, live (07) β€” stream real data through it, watch the stream log stay clean. The preview runs the production path, so it is the release test.
  3. Publish β€” Studio lints (Layer 2 blocks on any error) and publishes to your universe over the API, authenticated by a publish key (unoverse key). The item is live in every canvas immediately: no build, no restart, no deploy.

Next: 09 β€” Troubleshooting.