> ## Documentation Index
> Fetch the complete documentation index at: https://docs.penbox.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Form Templates (Flows)

> Design and build form templates in Penbox Studio

A **Form Template** (called a "Flow" in Penbox) defines the structure, appearance, and behavior of forms sent to contacts. This is what you design and build in **Penbox Studio** - the form builder interface.

<Note>
  **For Administrators & Creators**: This documentation is for users who design and create form templates. If you just need to send forms to contacts, see [Forms](/get-started/core_concepts#forms).
</Note>

## Understanding Form Templates

A Form Template is the blueprint for your forms. It defines:

* **Form structure**: Steps, fields, and validation
* **Portal experience**: Welcome page, form pages, confirmation page
* **Notifications**: Invitations, reminders, completion emails
* **Automations**: Actions triggered when forms are submitted
* **Appearance**: Branding, layout, and styling
* **Behavior**: Conditional logic, calculations, integrations

## Template Versioning

Form Templates support versioning, which allows you to iterate on designs while keeping existing forms stable.

### How Versioning Works

1. **Create a template** - Starts as version 1
2. **Make changes** - Edit in draft mode
3. **Publish version** - Lock this version for use
4. **Create new version** - Continue iterating
5. **Publish when ready** - New forms use latest published version

### Version Properties

* **Version number**: Auto-incremented integer (1, 2, 3...)
* **Published status**: Published versions can be used in Form Presets
* **Deprecated status**: Mark old versions as deprecated
* **Active version**: Form Presets link to latest published version by default

<Info>
  Existing forms always use the version they were created with. Publishing a new version doesn't change existing forms - only newly created forms use the new version.
</Info>

## Template Structure

### Basic Information

| Field           | Description                                | Required       |
| --------------- | ------------------------------------------ | -------------- |
| **Name**        | Template identifier (max 64 chars)         | Yes            |
| **Slug**        | URL-friendly identifier                    | Auto-generated |
| **Version**     | Version number                             | Auto           |
| **Locale**      | Default language (2-char code)             | Yes            |
| **Description** | What this template is for (max 1000 chars) | No             |

### Multi-Language Support

Templates support multiple languages through the `locales` and `strings` configuration:

**Locales Array**

```json theme={null}
["en", "fr", "es", "de"]
```

**Strings Object**

```json theme={null}
{
  "en": {
    "welcome_title": "Welcome",
    "submit_button": "Submit"
  },
  "fr": {
    "welcome_title": "Bienvenue",
    "submit_button": "Soumettre"
  }
}
```

Users can switch languages in the portal, and all text will update accordingly.

## Portal Pages

Form templates include three main portal pages that contacts see:

### 1. Welcome Page

The first page contacts see when opening the form.

**Configuration options:**

```json theme={null}
{
  "welcome": {
    "enabled": true,
    "options": {
      "image": "cdn://pen-fill/hello.svg",
      "title": "Hello",
      "message": "<p>Please use this secure form to provide the required data</p>",
      "start-button": "Let's get started",
      "help-text": "Need help?",
      "show-help-button": true,
      "show-privacy-policy": true,
      "custom-privacy-policy": ""
    }
  }
}
```

**Customizable elements:**

* Header image
* Title text
* Welcome message (HTML supported)
* Start button text
* Help button and text
* Privacy policy link

<Tip>
  A welcoming, clear welcome page increases completion rates. Explain what the form is for, how long it takes, and why you need the information.
</Tip>

### 2. Submit (Review) Page

Shown after all form steps are completed, before final submission.

**Configuration options:**

```json theme={null}
{
  "submit": {
    "enabled": true,
    "options": {
      "valid-image": "cdn://pen-fill/one_last_thing.svg",
      "valid-title": "Send your responses!",
      "valid-message": "Please click Send to complete.",
      "valid-submit-button": "Send",
      "valid-modify-button": "Modify",
      "valid-confirmation-message": "By sending, you confirm the information is correct.",
      "invalid-image": "cdn://pen-fill/one_last_thing.svg",
      "invalid-title": "Your responses are incomplete!",
      "invalid-message": "We still need some information from you.",
      "invalid-button": "Back to the form"
    }
  }
}
```

**Customizable elements:**

* Images for valid/invalid states
* Titles for valid/invalid states
* Messages and instructions
* Button text
* Confirmation message

### 3. Ending Page

Shown after successful form submission.

**Configuration options:**

```json theme={null}
{
  "ending": {
    "enabled": true,
    "options": {
      "image": "cdn://pen-fill/ended.svg",
      "title": "Your answers are being treated!",
      "message": "You can now close this window.",
      "rate-ux": true,
      "redirect-url": ""
    }
  }
}
```

**Customizable elements:**

* Confirmation image
* Thank you title
* Closing message
* UX rating widget (optional)
* Redirect URL (optional - redirect after N seconds)

## Form Steps

The core of your template is the form itself, composed of steps and elements.

### Creating Steps

Each step is a page in the form. Steps contain elements (fields) that collect data.

**Step structure:**

```json theme={null}
{
  "id": "step_1",
  "label": "Company Information",
  "enable": true,
  "elements": [
    // Elements go here
  ]
}
```

**Step properties:**

* **id**: Unique identifier (required)
* **label**: Step name shown to users
* **enable**: Show/hide the step (can use conditional logic)
* **elements**: Array of form elements

<Warning>
  Every step must contain at least one element with `"type": "submit"` or it won't be submittable. Alternatively, use elements with `submit_on_change` enabled.
</Warning>

### Conditional Steps

Use JSON expressions to show/hide steps based on data:

```json theme={null}
{
  "id": "business_details",
  "label": "Business Details",
  ":if": { ":cmp": "{data.account_type}", ":eq": "business" },
  "elements": [...]
}
```

The step only appears if the condition evaluates to true.

## Form Elements

Elements are the building blocks of your form - the actual input fields and content.

### Element Structure

```json theme={null}
{
  "id": "company_name",
  "key": "company_name",
  "type": "text",
  "title": "Company Name",
  "required": true,
  "help": "Legal name of your company",
  "placeholder": "Acme Corporation"
}
```

### Common Element Properties

| Property        | Description                   | Required                |
| --------------- | ----------------------------- | ----------------------- |
| **id**          | Unique identifier within step | Auto (from key or type) |
| **key**         | Data storage key              | Recommended             |
| **type**        | Element type                  | Yes                     |
| **title**       | Label shown to user           | No                      |
| **required**    | Must be filled                | No (default: false)     |
| **help**        | Help text                     | No                      |
| **placeholder** | Placeholder text              | No                      |

### Element Types

<AccordionGroup>
  <Accordion title="Visual Elements">
    **No data collection - for display only**

    * **card**: Content card with title and text
    * **image**: Display an image
    * **paragraph**: Text content block

    Example:

    ```json theme={null}
    {
      "type": "paragraph",
      "title": "Important Information",
      "text": "Please ensure all information is accurate."
    }
    ```
  </Accordion>

  <Accordion title="Text Input">
    **Type:** `text`

    Single-line or multi-line text input.

    ```json theme={null}
    {
      "key": "description",
      "type": "text",
      "title": "Description",
      "multiline": true
    }
    ```

    **Options:**

    * `multiline`: Enable textarea
    * `pattern`: Regex validation
  </Accordion>

  <Accordion title="Checkbox">
    **Type:** `checkbox`

    Single checkbox for yes/no or agreement.

    ```json theme={null}
    {
      "key": "terms_accepted",
      "type": "checkbox",
      "title": "I agree to the terms and conditions",
      "required": true
    }
    ```
  </Accordion>

  <Accordion title="Multiple Checkboxes">
    **Type:** `checkboxes`

    Multiple options with checkboxes.

    ```json theme={null}
    {
      "key": "services",
      "type": "checkboxes",
      "title": "Select services you're interested in",
      "options": [
        { "value": "consulting", "label": "Consulting" },
        { "value": "development", "label": "Development" },
        { "value": "support", "label": "Support" }
      ],
      "min": 1,
      "max": 3
    }
    ```
  </Accordion>

  <Accordion title="Radio Buttons / Dropdown">
    **Type:** `radio` or `autocomplete`

    Single selection from multiple options.

    ```json theme={null}
    {
      "key": "country",
      "type": "autocomplete",
      "title": "Country",
      "options": [
        { "value": "US", "label": "United States" },
        { "value": "UK", "label": "United Kingdom" },
        { "value": "FR", "label": "France" }
      ],
      "searchable": true
    }
    ```
  </Accordion>

  <Accordion title="Date & DateTime">
    **Type:** `date` or `datetime`

    Date picker for selecting dates.

    ```json theme={null}
    {
      "key": "birth_date",
      "type": "date",
      "title": "Date of Birth",
      "min": "1900-01-01",
      "max": "today",
      "format": "YYYY-MM-DD"
    }
    ```
  </Accordion>

  <Accordion title="File Upload">
    **Type:** `file`

    File upload field.

    ```json theme={null}
    {
      "key": "documents",
      "type": "file",
      "title": "Upload Documents",
      "accept": [".pdf", ".jpg", ".png"],
      "multiple": true,
      "maxFiles": 5,
      "maxSize": 10485760
    }
    ```

    **Options:**

    * `accept`: Allowed file types
    * `multiple`: Allow multiple files
    * `maxFiles`: Maximum number of files
    * `maxSize`: Maximum file size in bytes
  </Accordion>

  <Accordion title="Rating">
    **Type:** `rating`

    Star or numeric rating input.

    ```json theme={null}
    {
      "key": "satisfaction",
      "type": "rating",
      "title": "How satisfied are you?",
      "max": 5,
      "icon": "star"
    }
    ```
  </Accordion>

  <Accordion title="Toggle">
    **Type:** `toggle`

    Switch/toggle input.

    ```json theme={null}
    {
      "key": "newsletter",
      "type": "toggle",
      "title": "Subscribe to newsletter",
      "default": false
    }
    ```
  </Accordion>

  <Accordion title="Hidden Field">
    **Type:** `hidden`

    Store data without displaying to user.

    ```json theme={null}
    {
      "key": "source",
      "type": "hidden",
      "value": "email_campaign"
    }
    ```
  </Accordion>

  <Accordion title="Submit Button">
    **Type:** `submit`

    Button to submit the step.

    ```json theme={null}
    {
      "type": "submit",
      "label": "Next",
      "align": "right"
    }
    ```
  </Accordion>
</AccordionGroup>

### Conditional Elements

Show/hide elements based on other field values:

```json theme={null}
{
  "key": "company_registration",
  "type": "text",
  "title": "Company Registration Number",
  ":if": { ":cmp": "{data.account_type}", ":eq": "business" }
}
```

## Variables

Variables allow you to define global values, static or computed, accessible throughout the form.

### Defining Variables

**Object format** (no dependencies):

```json theme={null}
{
  "variables": {
    "company_email": "support@company.com",
    "max_upload_size": 10485760
  }
}
```

**Array format** (with dependencies):

```json theme={null}
{
  "variables": [
    { "base_price": 100 },
    { "tax_rate": 0.2 },
    { "total_price": "{base_price} * (1 + {tax_rate})" }
  ]
}
```

### Using Variables

Reference variables anywhere in the form using `{variable_name}`:

```json theme={null}
{
  "type": "paragraph",
  "text": "For support, contact us at {company_email}"
}
```

<Warning>
  Do not use `user`, `data`, or anything starting with `$` as variable names - these are reserved.
</Warning>

## Automations

Automations are actions that trigger automatically based on form events.

### Automation Structure

```json theme={null}
{
  "automations": [
    {
      "id": "uuid",
      "name": "Send confirmation email",
      "delay": 0,
      "icon": "envelope",
      "on": ["responses:completed"],
      "actions": [
        {
          "type": "email",
          "config": {
            "to": "{user.email}",
            "subject": "Thank you for your submission",
            "body": "We received your information..."
          }
        }
      ]
    }
  ]
}
```

### Automation Triggers

Available event triggers:

* `responses:created` - Form response is created (draft)
* `responses:updated` - Form response is updated
* `responses:completed` - Form is completed/submitted
* `responses:declined` - Form is declined
* `requests:expired` - Form expires without completion
* `manual` - Triggered manually by team member

### Automation Actions

<Tabs>
  <Tab title="Email">
    Send an email.

    ```json theme={null}
    {
      "type": "email",
      "config": {
        "to": "{user.email}",
        "cc": ["team@company.com"],
        "subject": "Your submission",
        "body": "Thank you, {user.given_name}...",
        "from": "no-reply@company.com"
      }
    }
    ```

    **Available in email content:**

    * Form data: `{data.field_key}`
    * User info: `{user.email}`, `{user.given_name}`, etc.
    * Form reference: `{reference}`
    * Variables: `{variable_name}`
  </Tab>

  <Tab title="SMS">
    Send an SMS message.

    ```json theme={null}
    {
      "type": "sms",
      "config": {
        "to": "{user.phone}",
        "body": "Thank you for your submission. Reference: {reference}"
      }
    }
    ```
  </Tab>

  <Tab title="Webhook">
    Send data to external API.

    ```json theme={null}
    {
      "type": "webhook",
      "config": {
        "url": "https://api.example.com/webhook",
        "method": "POST",
        "headers": {
          "Authorization": "Bearer token"
        },
        "body": {
          "form_data": "{data}",
          "user": "{user}"
        }
      }
    }
    ```
  </Tab>
</Tabs>

### Automation Delays

Add delays before triggering automations:

```json theme={null}
{
  "delay": 1440,  // 24 hours in minutes
  "name": "Send reminder if not completed",
  "on": ["responses:created"],
  "actions": [...]
}
```

## Notifications

Notifications are emails sent to contacts about the form itself (not from automations).

### Notification Types

**To Contact:**

* **Invitations**: When form is sent
* **Reminders**: If form not completed
* **Confirmation**: When form is submitted

**To Team:**

* **On submission**: Notify team when form completed
* **On bounce**: Notify if email bounces

### Notification Configuration

```json theme={null}
{
  "notifications": [
    {
      "type": "email",
      "to": [{ "email": "admin@company.com" }, { "role": "owner" }],
      "on": ["responses:completed"]
    }
  ]
}
```

### Invitation Template

Configure the invitation email template:

```json theme={null}
{
  "invitations": {
    "subject": "Action required: Complete your information",
    "body": "Please complete the form at {link}",
    "reminders": {
      "count": 3,
      "interval": 2,
      "unit": "days"
    }
  }
}
```

## Publishing Templates

### Publish Process

1. **Create and test** your template
2. **Validate** all steps and elements work correctly
3. **Set published: true**
4. Template version is locked
5. Can now be used in Form Presets

### Template Validation

Before publishing, ensure:

* All steps have submit buttons or auto-submit elements
* Required fields are clearly marked
* Conditional logic works as expected
* All images and assets load
* Multi-language strings are complete (if using)
* Automations are correctly configured
* Test submission works end-to-end

## Best Practices

<AccordionGroup>
  <Accordion title="Design mobile-first">
    Most contacts will complete forms on mobile devices. Test your forms on small screens and ensure they're easy to use.
  </Accordion>

  <Accordion title="Keep forms short">
    Only ask for information you truly need. Each additional field decreases completion rates.
  </Accordion>

  <Accordion title="Use multi-step wisely">
    Break long forms into logical steps, but don't create too many steps. 3-5 steps is usually optimal.
  </Accordion>

  <Accordion title="Provide clear help text">
    Use the help property to explain what you need. Especially important for complex or uncommon fields.
  </Accordion>

  <Accordion title="Test before publishing">
    Always test the complete form flow before publishing. Submit test data and verify automations work.
  </Accordion>

  <Accordion title="Use conditional logic">
    Only show fields that are relevant. This keeps forms clean and improves completion rates.
  </Accordion>

  <Accordion title="Set up confirmations">
    Always send a confirmation when forms are completed. This builds trust and provides a receipt.
  </Accordion>

  <Accordion title="Version thoughtfully">
    Don't create new versions for small changes. Batch changes together to avoid version sprawl.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Form Presets" icon="sliders" href="/core-concepts/form-presets">
    Configure presets from templates
  </Card>

  <Card title="Automations" icon="bolt" href="/automations/overview">
    Learn about automation actions
  </Card>

  <Card title="Forms" icon="rectangle-list" href="/core-concepts/forms">
    Understand form instances
  </Card>

  <Card title="Studio Guide" icon="wand-magic-sparkles" href="/guides/studio">
    Complete guide to Penbox Studio
  </Card>
</CardGroup>
