Validate before it renders
A malformed schema should fail at load with a useful message, not halfway through a form a respondent is filling in.
A form engine turns a data structure into a working form. You describe the fields, rules and flow once; the engine handles rendering, validation, conditional visibility, navigation and submission. The form becomes data you can version and review rather than components you maintain by hand.
The terms get used interchangeably, but they solve different halves of the problem.
Manages state, validation and submission for a form you have already built. You write the JSX for every field, wire each one to the library, and express conditional logic in your own component code.
You own the markup. The library owns the state.
Takes a description of the form and renders it. Fields, validation rules, conditional visibility, multi-step navigation and submission all come from the same object, so adding a question is a data change rather than a code change.
You own the schema. The engine owns the rest.
Neither is better in the abstract. A library is the right tool for a login box. An engine earns its place when forms are numerous, change often, or are authored by someone who does not write React.
This is a complete, working form — four fields, one of which appears only when the budget answer warrants it. There is no component code, and the conditional rule is a property rather than a branch.
{
"version": "1.0",
"sections": [
{
"id": "contact",
"title": "Get in touch",
"questions": [
{ "id": "name", "type": "short_text", "label": "Name", "required": true },
{ "id": "email", "type": "email", "label": "Email", "required": true },
{
"id": "budget",
"type": "single_select",
"label": "Budget",
"options": [
{ "value": "small", "label": "Under $5k" },
{ "value": "large", "label": "$5k+" }
]
},
{
"id": "details",
"type": "long_text",
"label": "Tell us more",
"showIf": { "field": "budget", "operator": "eq", "value": "large" }
}
]
}
]
}When you do not. A single short form with no conditional logic is more code with an engine than without one. Reach for a library, or plain React.
A renderer that maps field types to components is not an engine. These are the parts that make it one.
A malformed schema should fail at load with a useful message, not halfway through a form a respondent is filling in.
Visibility and computed values depend on other answers, which depend on others. That is a dependency graph, and evaluating it in declaration order gets stale results.
If a question can be hidden, then step counts, progress and the meaning of “next” all change at runtime.
Where a response goes is a deployment concern, not a form design one. The schema should not know your database.
FieldCraft is a schema-driven form engine for React, MIT licensed and self-hosted. 18 input field types, 25 condition operators, 14 validator rules and 16 ready-made schemas. Responses go straight from the browser to an endpoint you control — there is no server of ours in the path.