Introduction
A form schema is a JSON object that fully describes the structure, behavior, and output of a dynamic form. Instead of building UIs by hand, you define what the form should contain — inputs, sections, logic — and how it should behave — conditions, validations, defaults — in a single configuration.
Instead of coding the UI manually, you describe what the form contains (fields, groups, modals…) and how it behaves (conditions, validations, default values…) — all from a single configuration file.
This approach makes it possible to build advanced forms without writing any frontend code, making it ideal for low-code or no-code platforms.
Why use a schema? • Design complex forms without Frontend development knowledge • Keep business logic and layout outside of your app code. • Reuse, version, and maintain forms like any other config.
The app reads your schema and renders the appropriate UI components. It also computes the output object that mirrors your structure, taking into account visibility rules, validations, default values, and user interactions.
In this guide, you’ll learn:
- How schemas are structured
- What components are available (text fields, selects, groups, modals, etc.)
- How to control visibility, read-only states, and validations
- How to define logic that reacts to user input
- How to structure the resulting data
Your entire form can be expressed declaratively, without writing any imperative UI code.
Schema overview
The schema is a plain JSON object. It doesn’t require a fixed root structure — it can start with a container (section, group, modal) or directly with form components.
What matters is that the schema is valid JSON and follows the documented format: each node must define its component or type, and use the appropriate structure (properties, label, validations, etc.) based on its role.
Each node represents a component — whether it’s an input, a container, or a layout element — and supports a consistent set of keys that define its type, behavior, and visibility.
Root structure
{
"type": "section",
"properties": {
"email": { "component": "text", "label": "Email" },
"details": {
"type": "group",
"properties": {
"first_name": { "component": "text" },
"last_name": { "component": "text" }
}
}
}
}
- The root object has a
typeorcomponent(section,group, etc.). - All child elements are listed under
properties(object of key/component pairs). - Every input has a
component, and optionally aname,label, and more.
⚠️ Structural components like section and group do not support label, except for modal, which has its own header rendering logic.
Common keys
| Key | Required | Description |
|---|---|---|
type or component | ✅ | The type of component to render. Aliases allowed. |
label | ❌ (not on structure) | Display label shown to the user. Only applies to inputs and modals. |
name | ✅ (for inputs) | Used as the key in the output object. |
properties | ✅ (for containers) | Dictionary of nested components. |
visible | ❌ | Boolean or array of conditions. |
readOnly / disabled | ❌ | Boolean or condition array. |
validations | ❌ | List of validation rules (string or object). |
default | ❌ | Initial value. |
onValueChange | ❌ | Reactions when value changes. |
See the Common properties page for complete details.
Evaluation order
When the schema is parsed, this is the evaluation flow for each node:
- Defaults are applied if no value is provided.
- Visibility is checked. If
visible === false, the field is not rendered. - If hidden and
keepValueIfHidden !== true, its value is dropped. - ReadOnly / Disabled states are computed.
- If visible and editable, user interactions are allowed.
- onValueChange triggers may update other fields.
- Validations are applied before submission.
Key rules
- Components inside a
groupwrite at the same level in the output object. - Components inside a
sectionormodalmay be prefixed depending on your use. - All keys must be unique within the same scope (i.e. same
propertieslevel). - You can nest groups and sections as deeply as needed.
- Each node should be explicit about its type (
type,component, or both).
Next: learn more about each component type and the properties they support → Common properties.