Skip to main content

Best Practices

Practical guidelines to keep your FormBuilder schemas clear, predictable, and easy to maintain.


Group your fields

Even if your overall structure depends on the form’s goal, it’s a good idea to wrap fields in at least one group.

Why

  • Easier to condition visibility for a coherent block of fields.
  • Keeps related inputs scoped and readable.

Important

  • readOnly and disabled do not cascade from a group to its children.
    Define those flags on each child that needs them.

Example

{
"company_information": {
"type": "group",
"properties": {
"is_company": {
"component": "checkbox",
"label": "Is a company?"
}
},
"company_name": {
"component": "text",
"label": "Company name",
"visible": [{ "property": "is_company", "assertion": "isTrue" }]
}
}
}

English snake_case

Your schema defines the data produced by the form. Names must be explicit, stable, and readable.

Rules

  • Always use English and snake_case: first_name, invoice_date, total_amount.
  • Pick names that represent the value behind them (not the UI).
  • Treat the schema as the source of truth for the output JSON structure.

DO

  • first_name, policy_start_date, contact_email

DON’T

  • FirstName, policyStart, input1

Example

{
"user": {
"type": "section",
"properties": {
"first_name": { "component": "text", "label": "First name" },
"last_name": { "component": "text", "label": "Last name" },
"age": { "component": "number", "label": "Age" }
}
}
}

Keep it simple

When conditions become complex (multiple groups of conditions; cross-field logic), don’t encode everything directly in the schema.
Base your visible / disabled / readOnly on a single, clear output from a dedicated workflow_validation module.

Why

  • The schema stays readable and maintainable.
  • Real complexity lives in a specialized module (versioned, tested).

Pattern

  • Let your workflow compute a boolean or a small set of flags (e.g., can_edit_company_block, requires_manager_approval).
  • Use those flags in schema conditions.

Example

{
"manager_data": {
"type": "group",
"properties": {
"manager_comment": {
"component": "text",
"label": "Manager comment",
"visible": [
{
"property": "workflow.requires_manager_approval",
"assertion": "isTrue"
}
],
"disabled": [
{
"property": "workflow.can_edit_manager_comment",
"assertion": "isFalse"
}
]
}
}
}
}

Use non-breaking space

For translated labels or any text where the final punctuation (e.g., ?, !, :) must not wrap to the next line, insert a non-breaking space before the character.

Why

  • Prevents the punctuation from appearing alone at line start.
  • Produces a cleaner, more professional UI.

How

  • Use a non-breaking space between the last word and the punctuation:
    • HTML:  
    • Unicode: \u00A0
    • Shortcut: MacOS : option + space, Windows : Ctrl+Maj+Space

Examples

  • Do you agree ?
  • Amount to pay :
  • Are you sure\u00A0?

Use this inside your translation values (the keys stay clean), for example:

{
"accept_terms": {
"component": "true_false",
"label": "t:accept_terms_label" // translation value: "Do you agree ?"
}
}

Quick checklist

  • Wrap related fields in a group to simplify conditional display.
  • Use English snake_case names that mirror the actual data.
  • Push complex logic to a workflow/validation module and consume its outputs.
  • Insert non-breaking spaces before punctuation to avoid orphan punctuation on new lines.

Keep schemas simple; push complexity to where it belongs. Your future self (and your teammates) will thank you.