@canard/schema-form
JSON Schema-driven React form engine with a two-layer plugin architecture: a Validator plugin for JSON Schema validation and a UI plugin for form rendering components. Declare your data shape once in JSON Schema — the library builds, validates, and manages the full form state tree automatically.
Live Demo
Try the interactive form below to see what @canard/schema-form can build from JSON Schema alone.
This conference registration form demonstrates conditional fields, computed values, and 10+ input types — all driven by a single schema.
Explore 10 interactive examples covering if/then/else, oneOf, computed values, and more in the Examples section.
Each form above is rendered with the antd6-plugin. See individual plugin pages for component catalogs: antd5 | antd6 | MUI | antd-mobile
Architecture
JSON Schema
│
▼
nodeFromJsonSchema() ← builds a typed node tree
│
├── StringNode / NumberNode / BooleanNode / NullNode (terminal)
├── ObjectNode / ArrayNode (branch)
└── VirtualNode (conditional / computed)
│
▼
Plugin System
├── ValidatorPlugin ← compile(jsonSchema) → ValidateFunction
└── SchemaFormPlugin ← FormGroup / FormLabel / FormInput / FormError
+ formTypeInputDefinitions
│
▼
<Form> → React component tree
Plugin System
The library ships with no default validator and no default UI components.
Both must be supplied via plugins before rendering any form.
Plugins are registered globally with registerPlugin() and affect every
<Form> in the application.
- Validator plugin — integrates any validation library (AJV, Zod, Yup, etc.) by implementing
compile(jsonSchema). - UI plugin — provides
FormGroup,FormLabel,FormInput,FormErrorrenderer components andformTypeInputDefinitionsfor per-field input components.
Official plugin packages:
@canard/schema-form-ajv8-plugin— AJV 8 validator@canard/schema-form-antd5-plugin— Ant Design 5 UI@canard/schema-form-mui6-plugin— MUI 6 UI
Node Types
| Node | Schema types | Strategy |
|---|---|---|
StringNode | "string" | terminal |
NumberNode | "number", "integer" | terminal |
BooleanNode | "boolean" | terminal |
NullNode | "null" | terminal |
ObjectNode | "object" | branch (BranchStrategy or TerminalStrategy) |
ArrayNode | "array" | branch (BranchStrategy or TerminalStrategy) |
VirtualNode | conditional / oneOf / anyOf branches | special |
FormTypeInput Resolution Order
When rendering a field, the library resolves which input component to use in this priority order (highest first):
- Direct
FormTypeInputprop onForm.Group formTypeInputMappath mapping on<Form>- Form-level
formTypeInputDefinitionsprop FormProviderformTypeInputDefinitions- Plugin-provided
formTypeInputDefinitions
AI Agent Reference
AI Reference
Package: @canard/schema-form v0.10.5
Purpose: JSON Schema-driven dynamic form generation for React with two-layer plugin architecture.
Plugin system
import type { SchemaFormPlugin } from '@canard/schema-form';
import type { ValidatorPlugin } from '@canard/schema-form';
import { registerPlugin } from '@canard/schema-form';
Form component
import { Form } from '@canard/schema-form';
import type { FormProps } from '@canard/schema-form';
import type { FormHandle } from '@canard/schema-form'; // ref API: submit(), reset(), validate(), getValues()
import type { FormChildrenProps } from '@canard/schema-form'; // render-prop children
import type { FormLabelProps } from '@canard/schema-form';
import type { FormErrorProps } from '@canard/schema-form';
Node types
import type { SchemaNode } from '@canard/schema-form';
import type { StringNode, NumberNode, BooleanNode, NullNode } from '@canard/schema-form'; // terminal
import type { ObjectNode, ArrayNode } from '@canard/schema-form'; // branch
import type { VirtualNode } from '@canard/schema-form'; // conditional
Enums
import { NodeState } from '@canard/schema-form'; // Initialized | Mounted | Unmounted
import { ValidationMode } from '@canard/schema-form'; // OnChange | OnBlur | OnSubmit
import { NodeEventType } from '@canard/schema-form'; // ValueChange | StateChange | ...
import { SetValueOption } from '@canard/schema-form'; // Merge | Replace
Type guards & error utilities
import { isArrayNode, isBooleanNode, isBranchNode, isNumberNode } from '@canard/schema-form';
import { isSchemaFormError, isJsonSchemaError, isUnhandledError, isValidationError } from '@canard/schema-form';
import { JSONPointer } from '@canard/schema-form';
Architecture
- No default validator or UI — both via plugins:
registerPlugin(plugin) - Node tree: JSON Schema → nodeFromJsonSchema() → typed node tree
- Input resolution: Direct prop > formTypeInputMap > form-level > FormProvider > plugin