You are viewing beta documentation for Formie 4.x.
Developers

Everything you need to know about Formie schemas

Formie schemas are PHP arrays that describe control panel UI — field settings tabs, integration form settings, notification editors, and page button panels. They replace ad-hoc Twig/Vue templates in the form builder with a structured, normalizable format built on SchemaForm. This guide explains when and why to use schemas, and patterns for fields and integrations.

For node anatomy, SchemaHelper method tables, conditions, layout nodes, table fields, and preview schema, see Schema.

Prerequisites

This guide covers CP builder schemas — not headless React consumer docs or GraphQL types.

Like Craft's Twig form macros, but in PHP

If you have built Craft plugin settings pages before, you have probably used Twig form macros (opens new window) such as forms.textField():

{{ forms.textField({
    label: 'Name' | t('app'),
    instructions: 'What this section will be called in the control panel.' | t('app'),
    id: 'name',
    name: 'name',
    value: section.name,
    errors: section.getErrors('name'),
    required: true,
}) }}

Formie schemas aim at the same developer experience — describe fields in PHP with translated labels, defaults, validation rules, and errors, and let the UI layer render them. The difference is that Formie's builder runs in React, so those arrays feed SchemaForm instead of Twig templates.

Your PHP side still owns the field definition:

$schema = [
    [
        '$field' => 'text',
        'name' => 'name',
        'label' => Craft::t('app', 'Name'),
        'instructions' => Craft::t('app', 'What this section will be called in the control panel.'),
        'required' => true,
        'validation' => 'required',
    ],
];

$formConfig = [
    'schema' => $schema,
    'values' => [
        'name' => $section->name,
    ],
    'errors' => [
        'name' => $section->getErrors('name'),
    ],
];

Formie's SchemaHelper methods are convenience wrappers around that same idea — shorter nodes for common field types, plus Formie-specific settings such as field handles, conditions, and integration mapping controls. See the Plugin Kit blog post on schema-driven forms for the broader picture of why Verbb built this pattern.

What a schema is

A schema is an ordered array of nodes. Each node describes an input, layout wrapper, or registered component. The form builder renders the array; saved values map to setting keys on the field, form, or integration model.

Prefer SchemaHelper for common inputs and Formie field settings. Use raw nodes when you need a field or layout the helper does not cover. See Schema for the intro example, Helpers, Schema Nodes, Conditions, Layout and HTML, and Tables.

Field schema methods

Custom fields implement tab-specific methods:

MethodTab
defineFormBuilderGeneralSchema()General
defineFormBuilderSettingsSchema()Settings
defineFormBuilderAppearanceSchema()Appearance
defineFormBuilderAdvancedSchema()Advanced
defineFormBuilderConditionsSchema()Conditions

Implement the tab-specific methods above for custom fields. Each method returns an array of schema nodes for that part of the builder.

Field previews in the builder palette use defineFormBuilderPreviewSchema() — see Preview Schema.

Integration form settings schema

Integrations that expose form-level settings implement defineFormSettingsSchema():

use verbb\formie\base\FormInterface;
use verbb\formie\helpers\SchemaHelper;

protected function defineFormSettingsSchema(FormInterface $form): array
{
    $schema = parent::defineFormSettingsSchema($form);

    $schema[] = SchemaHelper::textField([
        'label' => Craft::t('formie', 'Endpoint URL'),
        'instructions' => Craft::t('formie', 'Enter the URL this integration should send submissions to.'),
        'name' => 'endpointUrl',
        'required' => true,
    ]);

    return $schema;
}

Always start with parent::defineFormSettingsSchema($form) unless you have a specific reason not to — the parent includes the standard Enabled setting. Per-form integration UI is declared entirely through schema.

Settings schema vs front-end modules

Schema covers control panel configuration. Captchas and address providers also need client modules (getClientModule()) for browser behaviour — schema alone does not inject JavaScript.

See Captcha Integration for the full split.

Normalization and validation

Formie normalizes saved settings against schema definitions on save. Benefits:

  • Consistent defaults when new settings are added
  • Type coercion for numbers, booleans, and selects
  • Validation rules declared on nodes surface in the builder

When adding a new setting to an existing field type, add the schema node and a default in the field's settings model — old saved fields pick up defaults on next edit.

Debugging schema issues

SymptomCheck
Setting not savingname matches model attribute; no typo in if expression
Field hidden unexpectedlyif condition against wrong key in nested group
Preview blankdefineFormBuilderPreviewSchema() returns valid preview helpers
Integration tab emptydefineFormSettingsSchema() returns array; parent called

Hard-refresh the CP after PHP changes. Schema is server-rendered — no Vite rebuild for plugin PHP.