Motivation Form

Survey syntax reference

Extended Motivation Form field types, media embedding, conditional logic, and page-based pagination — all via .md frontmatter.

This page covers the extended syntax available in Motivation Form .md files beyond the core 10 field types. Use these when you are building surveys, NPS studies, A/B comparisons, or any form where standard text/choice inputs are not enough.

The core 10 types (text, email, textarea, number, radio, checkbox, select, date, image, file) remain unchanged and are documented in Field types.


Pagination with page:

Add a page: integer to any field to control how fields are grouped into pages. There is no separate "survey mode" to enable — the layout is derived entirely from which fields share a page number.

What you writeWhat you get
No page: on any fieldAll fields on a single page (classic form)
Fields sharing the same page: valueThose fields appear together on one page
Each field has a unique page: valueOne field per page (classic survey)
fields:
  # Page 1 — two fields grouped together
  - id: name
    type: text
    label: Your name
    page: 1
  - id: email
    type: email
    label: Email address
    page: 1

  # Page 2 — one field alone
  - id: recommend
    type: nps
    label: How likely are you to recommend us?
    page: 2

  # Page 3 — another field alone
  - id: feedback
    type: textarea
    label: Any other thoughts?
    page: 3

Page labels

Name each page with page_labels: (list indexed from 0):

page_labels:
  - About you
  - Satisfaction
  - Open feedback

Backward compatibility: The legacy step: attribute and type: survey are still accepted and will continue to work. step: is a direct alias for page:. type: survey is treated as assigning each field a unique page automatically. Migrate to page: for new forms.


Global settings

settings:
  progress_bar: true          # show a progress bar at the top (default: false)
  randomize_options: true     # shuffle option order for radio/checkbox/select/ranking (default: false)

New field types

All fields share the common properties (id, label, required, help_text, page, show_if).

rating

Star (or emoji) rating. Response value: integer 1–max.

- id: overall_experience
  type: rating
  label: How would you rate your overall experience?
  max: 5        # 1–10 supported; default: 5

scale

Labelled numeric scale (Likert-style). Response value: integer.

- id: ease_of_use
  type: scale
  label: This product is easy to use.
  min: 1
  max: 7
  min_label: Strongly disagree
  max_label: Strongly agree

nps

Net Promoter Score. Renders as 11 numbered buttons (0–10) with anchors. Response value: integer 0–10.

- id: recommend
  type: nps
  label: How likely are you to recommend us to a colleague?
  low_label: Not at all likely
  high_label: Extremely likely

yes_no

Binary choice. Response value: "yes" or "no".

- id: used_before
  type: yes_no
  label: Have you used a similar product before?

ranking

Drag-and-drop ordered list. Response value: ordered array of option strings.

- id: priority_order
  type: ranking
  label: Rank these features by importance to you.
  options:
    - Speed
    - Price
    - Reliability
    - Customer support
    - Documentation

matrix

Grid of rows × columns. Each row is one question; columns are the shared response options. Response value: { row_id: selected_column } object.

- id: satisfaction_grid
  type: matrix
  label: Rate each aspect of the product.
  rows:
    - id: onboarding
      label: Onboarding experience
    - id: performance
      label: Performance
    - id: docs
      label: Documentation
  columns:
    - Very dissatisfied
    - Dissatisfied
    - Neutral
    - Satisfied
    - Very satisfied

statement

Read-only informational block. No user input. Use for section headings, instructions, or consent text within a multi-step form. Not included in the response payload.

- id: intro_text
  type: statement
  label: "Before you begin"
  help_text: |
    This survey takes about 3 minutes. Your responses are anonymous
    and will only be used to improve the product. Thank you.

Media embedding

Any field can display rich media above its input with the media: property. Media is for display only — it does not affect the response value.

- id: logo_preference
  type: radio
  label: Which logo do you prefer?
  media:
    type: image
    url: https://cdn.example.com/logo-options.png
    alt: Two logo concepts for the rebrand.   # optional
  options:
    - Option A
    - Option B
    - Neither

Supported media types

typeurl formatHow it renders
imageURL (external) or Supabase Storage URL<img> with lazy loading
youtubeFull YouTube URL or 11-char video ID<iframe> nocookie embed
videoDirect .mp4 / .webm URLHTML5 <video> player (no autoplay)
model3d.glb / .gltf URL<model-viewer> web component

image

media:
  type: image
  url: https://cdn.example.com/comparison.png
  alt: Before and after redesign.

youtube

media:
  type: youtube
  url: https://www.youtube.com/watch?v=dQw4w9WgXcQ
  alt: Product walkthrough (2 min).

video

media:
  type: video
  url: https://cdn.example.com/demo.mp4
  alt: Click play to watch the demo before answering.

model3d

media:
  type: model3d
  url: https://cdn.example.com/product.glb
  alt: Drag to rotate the 3D model.

Media on individual options

For visual A/B comparisons, attach media: to individual options. When any option in a radio or checkbox field has a media: key, the field renders as a visual card grid instead of a text list.

- id: design_preference
  type: radio
  label: Which design direction resonates most?
  options:
    - label: Minimal
      media:
        type: image
        url: https://cdn.example.com/design-a.png
    - label: Bold
      media:
        type: image
        url: https://cdn.example.com/design-b.png
    - label: Playful
      media:
        type: image
        url: https://cdn.example.com/design-c.png

Conditional logic

Show or hide any field based on the current value of another field with show_if:.

show_if:
  field: <other_field_id>
  op: eq | neq | gt | lt | gte | lte | includes | excludes
  value: <scalar or string>

The field is hidden on page load and revealed client-side when the condition is met. Hidden fields are excluded from the submitted payload.

Operators

OpMeaningWorks on
eqequalsany scalar
neqdoes not equalany scalar
gtgreater thannumber, rating, scale, nps
ltless thannumber, rating, scale, nps
gtegreater than or equalnumber, rating, scale, nps
lteless than or equalnumber, rating, scale, nps
includesarray contains valuecheckbox, ranking
excludesarray does not contain valuecheckbox, ranking

Examples

# Show follow-up only for detractors (NPS 0–6)
- id: detractor_reason
  type: textarea
  label: What would need to change for you to rate us higher?
  show_if:
    field: recommend
    op: lte
    value: 6

# Show feature request field only when "New feature" is checked
- id: feature_detail
  type: textarea
  label: What feature would you like?
  show_if:
    field: feedback_type
    op: includes
    value: New feature

# Show competitor name only when respondent says they use another product
- id: competitor_name
  type: text
  label: Which product do you use today?
  show_if:
    field: uses_competitor
    op: eq
    value: "yes"

Complete survey example

Each field gets a unique page: number so they appear one at a time.

---
title: Product Experience Survey
slug: product-survey
settings:
  progress_bar: true
branding:
  primary_color: "#6366f1"
notifications:
  email:
    - team@example.com
fields:
  - id: recommend
    type: nps
    label: How likely are you to recommend us to a colleague?
    low_label: Not at all likely
    high_label: Extremely likely
    required: true
    page: 1

  - id: detractor_reason
    type: textarea
    label: What would need to change for you to rate us higher?
    show_if:
      field: recommend
      op: lte
      value: 6
    page: 2

  - id: promoter_reason
    type: textarea
    label: What do you love most about the product?
    show_if:
      field: recommend
      op: gte
      value: 9
    page: 2

  - id: ease_of_use
    type: scale
    label: The product is easy to use.
    min: 1
    max: 5
    min_label: Strongly disagree
    max_label: Strongly agree
    page: 3

  - id: top_feature
    type: ranking
    label: Rank these features by how much you rely on them.
    options:
      - CLI / MCP integration
      - Email notifications
      - Response dashboard
      - Branding options
      - File uploads
    page: 4

  - id: overall
    type: rating
    label: Overall, how satisfied are you?
    max: 5
    page: 5

  - id: extra_thoughts
    type: textarea
    label: Anything else you'd like to share?
    required: false
    page: 6
---

Thank you for taking this survey. Your feedback shapes the roadmap.

On this page