Skip to main content
View as Markdown

Multi-Step Forms

Long forms are easier to complete when they are broken into manageable pieces. The layout property chooses how a form's fields are presented: all at once, split into steps with previous/next navigation, or one field per screen Typeform-style. Steps support conditional skipping and branching so the path through the form can adapt to the submitter's answers.

app.yaml
forms:
  - id: 1
    name: onboarding
    title: Set up your workspace
    layout: multi-step
    submitTo: { table: workspaces }
    fields:
      - { kind: standalone, name: workspace_name, inputType: short-text, required: true }
      - { kind: standalone, name: team_size, inputType: number }
      - { kind: standalone, name: use_case, inputType: long-text }
    steps:
      - { id: basics, title: The basics, fields: [workspace_name] }
      - { id: team, title: Your team, fields: [team_size] }
      - { id: goals, title: Your goals, fields: [use_case] }

Layout Modes

Mode Description
single-page All fields on one page (default). Steps are ignored.
multi-step Fields grouped into steps[] with previous/next navigation.
one-question One field per screen, advancing automatically. Driven by the same steps[] model.

Step Definitions

When layout is multi-step or one-question, the steps array partitions the form's fields into ordered screens. Each step references field names defined in the parent fields array.

Property Description
id Unique step id within the form (kebab-case recommended, ≤64 chars). Required.
title Step title shown above the fields.
description Step intro paragraph.
fields Field names belonging to this step. Each must match a field's name (standalone/calculation/signature) or column (table-field). At least one.
visibleWhen Whole-step visibility rule. When false, the entire step is skipped. Uses the conditional shape.
goToWhen Branching rules. The first matching rule jumps to its goTo step instead of the linear next step.

By default a multi-step form advances linearly: step 1 → step 2 → step 3. Two mechanisms override that flow.

Skip a step with a step-level visibleWhen — when the condition is false the step is removed from the sequence entirely.

Branch to a different step with goToWhen. Each rule has a when condition and a goTo target step id; the first matching rule wins, otherwise linear flow continues.

app.yaml
steps:
  - id: plan
    title: Choose a plan
    fields: [plan]
    goToWhen:
      # Enterprise plans skip self-serve billing and route to a sales step
      - when: { field: plan, operator: eq, value: enterprise }
        goTo: sales
  - id: billing
    title: Payment
    fields: [card_number]
  - id: sales
    title: Talk to sales
    fields: [company, seats]
    # only relevant for enterprise; hidden otherwise
    visibleWhen: { field: plan, operator: eq, value: enterprise }

One-Question-at-a-Time

The one-question layout presents a single field per screen for a focused, conversational experience. It reuses the same steps[] model — typically one field per step — and the same visibleWhen / goToWhen branching applies.

app.yaml
forms:
  - id: 2
    name: survey
    title: Quick survey
    layout: one-question
    submitTo: { storeSubmission: true }
    fields:
      - {
          kind: standalone,
          name: nps,
          inputType: rating,
          label: How likely are you to recommend us?,
        }
      - {
          kind: standalone,
          name: reason,
          inputType: long-text,
          label: What's the main reason for your score?,
        }
    steps:
      - { id: q1, fields: [nps] }
      - { id: q2, fields: [reason] }

Display Overrides

The display object adjusts how the form looks without affecting submission semantics.

Property Description
submitLabel Submit button label (Submit by default). Supports $t: keys.
theme Per-form overrides: primaryColor, backgroundColor, borderRadius.

The progress bar is not configurable. multi-step and one-question always render one; single-page has no step boundary to advance through and never does. Field layout is likewise fixed at a single column.

app.yaml
forms:
  - id: 3
    name: registration
    title: Event registration
    layout: multi-step
    display:
      submitLabel: Complete registration
      theme:
        primaryColor: '#4f46e5'
        borderRadius: 0.5rem
    submitTo: { table: registrations }
    fields:
      - { kind: table-field, column: first_name, required: true }
      - { kind: table-field, column: last_name, required: true }
      - { kind: table-field, column: email, required: true }
      - { kind: table-field, column: dietary_notes }
    steps:
      - { id: name, title: Your name, fields: [first_name, last_name] }
      - { id: contact, title: Contact & preferences, fields: [email, dietary_notes] }
  • Form Fields — the fields distributed across steps.
  • Field Groups — the single-page alternative to splitting a form into steps.
  • Conditional Logic — the condition shape used by visibleWhen and goToWhen.
  • Forms Overviewlayout, steps, and display in the full form schema.
  • Submissions — what happens after the final step.

Last updated August 11, 2026

This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta. Contributions and corrections are welcome.

Built with Sovrium