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