Skip to Content
Prism UI
Core Concepts

Architecture Overview

The three UI layers and how they fit together.

Prism's architecture is organized into three layers, each with a distinct ownership boundary.

Layer 1: Primitives

Copy-in, Tailwind-based, accessible components (Input, Label, Select, Checkbox). Consumer-owned once installed, no Prism runtime dependency, no PrismProvider requirement. Installed via the CLI, styled with CSS variables so retheming means editing variables, not component source, see Customization Model.

Layer 2: Field components

Copy-in wrappers (TextField, SelectField, and so on) that accept Prism's normalized field-binding contract and can wrap any UI library, not only Prism's own Layer 1 primitives. A field component's only real obligation is to forward field.value/field.onChange/field.onBlur/field.error to whatever it renders, see Custom Fields.

Layer 3: Form engine

The only Prism-owned, installed-as-a-dependency layer: @prismrepo/forms, @prismrepo/adapter-rhf, and @prismrepo/adapter-zod. Resolves a configured field's type through the consumer's own registry at render time, never by statically importing a consumer's component, see Registry System.

How a form actually renders

  1. defineRegistry({...}) declares which field components exist, each keyed by a type name.
  2. createFormBuilder(registry).defineForm<TValues>({...}) declares which fields a specific form has, type-checked against the registry.
  3. usePrismForm(definition, options) creates a real React Hook Form instance from that definition.
  4. <PrismField form={form} name="..." /> resolves the field's configured type against form.registry at render time and binds it through RHF's Controller.

No step in this chain requires a PrismProvider; a FormDefinition already carries its own registry. PrismProvider/usePrismRegistry (@prismrepo/react) exist for consumers who want a registry available ambiently across part of a tree instead of threading it through props, see Package Responsibilities.

On this page