How to define forms with FieldCraft's schema format.
A FormEngineSchema is the single source of truth for your form. It describes every field, section, validation rule, and behavior in a declarative JSON-compatible structure.
Minimal Schema
const schema: FormEngineSchema = {
id: "contact",
version: "1.0.0",
title: "Contact Us",
submitAction: { type: "callback" },
sections: [
{
id: "main",
title: "Your Details",
questions: [
{ id: "name", type: "short_text", label: "Name", required: true },
{ id: "email", type: "email", label: "Email", required: true },
],
},
],
};
Top-Level Properties
| Property | Type | Required | Description |
|---|
id | string | Yes | Unique schema identifier |
version | string | Yes | Semver version for response tracking |
title | string | Yes | Human-readable form title |
submitAction | SubmitAction | Yes | What happens on submit |
sections | Section[] | Yes | One or more form sections |
settings | FormSettings | No | Progress, drafts, branding |
branding | BrandingConfig | No | Logo, colors, fonts |
Sections
Each section groups related questions. Multi-section schemas render as wizard-style multi-step forms with automatic navigation.
{
id: "personal",
title: "Personal Information",
description: "Tell us about yourself", // optional
showIf: { /* ConditionExpression */ }, // optional — conditional section
onExit: { /* SectionExitAction */ }, // optional — branching rules
questions: [ /* ... */ ],
}
Questions
Questions are the individual fields in your form. Every question needs an id, type, and label.
{
id: "email",
type: "email",
label: "Email Address",
required: true,
placeholder: "you@example.com",
helpText: "We'll never share your email.",
showIf: { field: "wants_updates", operator: "eq", value: true },
validation: [
{ type: "pattern", value: "^[^@]+@[^@]+\.[^@]+$", message: "Enter a valid email" },
],
config: { /* type-specific config */ },
}
Submit Action
Controls what happens when the form is submitted:
// Callback — your code handles submission
submitAction: { type: "callback" }
// Redirect — navigate after submit
submitAction: { type: "redirect", url: "/thank-you" }
Settings
settings: {
showProgress: true,
progressStyle: "steps", // "bar" | "steps" | "percentage"
allowDraftSave: true,
draftTtlHours: 168, // 7 days
showSectionNumbers: true,
submitButtonText: "Send",
}
Schema Validation
Use validateSchema to check a schema at runtime. It throws a FormEngineSchemaError with detailed Zod issues if the schema is invalid.
import { validateSchema, FormEngineSchemaError } from "@squaredr/fieldcraft-core";
try {
const validated = validateSchema(rawSchema);
// validated is a typed FormEngineSchema
} catch (err) {
if (err instanceof FormEngineSchemaError) {
console.error(err.issues); // ZodIssue[]
}
}