The survey builder supports multiple ways to create survey content: Outline (importing from text format) and detailed follow-up question configuration. This is convenient when:

  • You already have the survey designed in a document and prefer to import the structure instead of dragging and dropping questions in the visual builder.
  • You want to lay out complex flows with repeatable sections or branching logic before wiring the final details in the UI.
  • You need fine-grained control over follow-up text inputs for specific options.

New: You can also create surveys using our AI-Assisted Survey Generator, which helps you design surveys through natural conversation instead of writing markdown manually.

Also new: If you already have the survey as a Word document or pasted text, the Import from document tab converts it into the outline format for you.

This document covers:

For more details on repeats, see Repeats (Nested, Repeatable Sections).

Import from document

The Outline page has a From document tab (shown when AI features are enabled): upload a .docx file or paste text, and the AI converts it into the outline format. Nothing is imported automatically β€” the converted outline is placed in the Outline tab for you to review and edit before importing.

What the AI does

  • Converts every numbered or bulleted item into a question, preserving the author's wording.
  • Infers question types from phrasing: "rate 1–5" β†’ Likert scale (with min:/max:), "tick all that apply" β†’ multi-select, yes/no phrasing β†’ Yes/No, and open questions β†’ text.
  • Infers and creates sections from the document's structure, grouping related questions even when the document has no explicit headings.
  • Uses datasets where they match: if a dropdown question's options correspond to a dataset available to your survey (NHS trusts, medical specialities, and so on), the AI links it with a dataset: <key> line instead of inventing option lists. Emitted dataset references are verified against your accessible datasets β€” anything else is stripped with a warning.
  • Suggests templates: if the converted outline closely resembles a Question Bank template you can access (for example Professional details), you'll see a passive suggestion with a link to the Question Bank. Template content is never added automatically.

How to use it

  1. Open From document on the Outline (Add questions) page.
  2. Upload a .docx, .txt, or .md file, or paste the survey text.
  3. Click Convert to outline. The AI's working streams into the panel so you can see progress; conversion is usually quick.
  4. The converted outline appears in the Outline tab with the live structure preview. Edit anything you want to change β€” wording, types, sections, or add branching and repeats.
  5. Import as usual from the Outline tab.

Limits and troubleshooting

  • Legacy binary .doc files are not supported β€” save as .docx first, or paste the text.
  • Uploads are capped (2 MB by default) and very long documents are truncated for conversion; a warning tells you when that happens.
  • If the AI cannot produce a valid outline, the extracted document text is placed in the Outline tab instead so you can format it manually β€” nothing is lost.
  • Document text is sent to the self-hosted LLM service for conversion and is not stored. See AI Security & Safety for the full security posture, including file validation, the published conversion prompt, and prompt-injection posture.

Bulk survey import

This document captures the grammar the importer recognises and the conventions that keep identifiers stable when you later edit the survey.

Authoring overview

Place the Markdown in the Import questions form for the survey you are editing. When you confirm the import, the system removes all existing question groups and questions owned by that survey and replaces them with the imported content. Collections, repeat groups, and branching conditions are created automatically. You can refine question copy, options, and wiring inside the builder after the import.

A minimal survey looks like this:

# Group title
Group description

## Question title
Question description
(type)

Spacing is flexible, but keep the relative order (heading β†’ optional description β†’ type). Blank lines are ignored.

Group headings

  • Use # <group title> for each group.
  • The first non-empty line after the heading (if it is not a question heading or type declaration) becomes the group description.
  • Optionally append a stable identifier by placing it in curly braces at the end of the heading: # Group title {group-id}. The importer slugifies the identifier and keeps it unique.

Question headings

  • Use ## <question title> inside a group.
  • The next non-empty line that is not a type declaration becomes the question description.
  • Declare the question type on a dedicated line wrapped in parentheses: (text), (mc_single), etc.
  • Append a stable identifier with curly braces just like groups: ## Question {question-id}.
  • Mark a question as required by adding an asterisk * after the question title (before the ID if present): ## Question title* {question-id}.

Supported question types

Type name Description
text Free-text short answer
text number Numeric input validation
text date Date picker (aliases: date). Optional min: / max: range lines
text time Time picker (aliases: time). Optional min: / max: range lines
text datetime Date and time picker (aliases: datetime, date/time). Optional min: / max: range lines
mc_single Multiple choice (single answer)
mc_multi Multiple choice (multiple answers)
dropdown Select menu
orderable Rank the provided items
yesno Yes/No toggle
image Image choice
long_text Long text (textarea). Aliases: textarea, paragraph
likert categories Likert scale with category labels (one per - line)
likert number Likert scale defined by number range

Options and Likert metadata

  • For option-based questions, supply each option on its own line starting with - (hyphen + space).
  • Follow-up text inputs: To add a follow-up text field for any option, add an indented line starting with + (plus + space) immediately after the option. The text after + becomes the label for the follow-up input field that appears when the participant selects that option.
  • For likert number, add key-value metadata lines after the type:
  • min: 1
  • max: 5
  • Optional left: and right: labels.
  • Optional render: slider (default) or render: radio to control how the scale is presented to respondents (see Likert render mode).
  • For likert categories, an optional render: radio line after the category list switches the scale from a slider to radio buttons.
  • For text date, text time and text datetime, optional range lines restrict the picker:
  • min: 2026-01-01 / max: 2026-12-31 for dates
  • min: 09:00 / max: 17:00 for times
  • min: 2026-01-01T09:00 / max: 2026-01-31T17:00 for date & time

Likert render mode

By default, Likert questions render as a slider (range input). Add a render: metadata line to render the same scale as radio buttons instead. This works for both likert number and likert categories.

With radio buttons, no default midpoint is pre-selected β€” respondents must make an explicit choice. The submitted value is identical to the slider (the numeric value for likert number, the category label for likert categories), so branching, exports, and aggregation are unaffected.

likert number as radio buttons:

## Overall satisfaction {overall-satisfaction}
(likert number)
min: 1
max: 5
left: Very dissatisfied
right: Very satisfied
render: radio

likert categories as radio buttons:

## Agreement with the statement {agreement}
(likert categories)
- Strongly disagree
- Disagree
- Neutral
- Agree
- Strongly agree
render: radio

Valid values are slider (default) and radio. Unknown values are ignored and the slider is used. The render mode can also be changed in the visual builder via the "Render as" toggle in the Likert section.

Example with follow-up text:

## Employment status
(mc_single)
- Employed full-time
- Employed part-time
  + Please specify your hours per week
- Self-employed
  + What type of business?
- Unemployed
  + Are you actively seeking employment?
- Student
- Retired

Follow-up guidelines:

  • Follow-up lines must start with + and be indented (at least 2 spaces or a tab)
  • The text after + becomes the label for the follow-up input field
  • Works with mc_single, mc_multi, dropdown, orderable, and yesno question types
  • For yesno questions, you can optionally provide 2 options (for Yes and No) with follow-up labels
  • Not all options need follow-upsβ€”only add them where additional context is needed
  • Follow-up responses are stored alongside the selected option in the survey response

Follow-up questions

Follow-up text inputs allow you to conditionally show additional text fields based on respondents' answers. This is useful when you need more detail for specific options (e.g., "If you selected 'Other', please explain").

Compatible question types

Follow-up text inputs work with:

  • Multiple choice β€” single (mc_single)
  • Multiple choice β€” multiple (mc_multi)
  • Dropdown (dropdown)
  • Yes/No (yesno)
  • Orderable list (orderable)

Configuration methods

You can add follow-up text inputs in three ways:

  1. Outline (this document) - Use the + syntax shown above
  2. Visual builder - Check "Enable follow-up text" for each option in the question editor
  3. API - Include followup_text in the options structure

How it works for respondents

When a respondent selects an option that has follow-up text enabled:

  • A text input field appears with your custom label
  • The field is hidden if they select a different option
  • For multiple-choice questions with multiple selections, they see follow-up fields for each selected option that has it enabled

Visual indicator

Questions with follow-up inputs configured show a badge in the question card listing which options have follow-up text. This helps you quickly identify questions with this feature when managing your survey.

Data structure

Options with follow-up text are stored as:

{
  "label": "Employed part-time",
  "value": "Employed part-time",
  "followup_text": {
    "enabled": true,
    "label": "Please specify your hours per week"
  }
}

For complete implementation details and examples, see Branching Logic & Repeating Questions.

Required questions

Mark a question as required by adding an asterisk * immediately after the question title. Required questions must be answered before participants can submit the form.

Example:

## Age* {patient-age}
Age in years
(text number)

## Email address*
Please provide your email
(text)

## Consent to participate* {consent}
(yesno)

Guidelines:

  • Place the asterisk directly after the question title, before any identifier in curly braces
  • Works with all question types
  • Required questions are validated on form submission
  • The asterisk will appear in red in the preview

Preview Viewer

The Outline also has a real-time preview viewer. As you enter text the view renders it below - this is helpful because a unique identifier for each question and question-group automatically renders in the preview. This is needed if you choose to use the branching notation (see below).

Additional Function

You may not want to use this function and the Outline works without it. You may simply want to convert a Word document to text format and import the questions wholesale - you can add function for repeat questions (such as patients) or conditional branching in the Question Builder afterwards. But if you wish to use advanced features during import, it is possible to use the notation described below for some questions or groups to be iterative or show conditionally depending on answers that users give. This is detailed below.

Repeatable collections

You can mark a group as repeatable so respondents can add multiple entries (e.g., visits, household members). Place REPEAT on the line immediately above the group heading.

REPEAT-5
# Patient details

> REPEAT
> # Visit
> ...

Guidelines:

  • REPEAT allows unlimited repeats; REPEAT-5 limits the maximum to five entries; REPEAT-1 means one allowed.
  • Use > to indicate nested collections and repeat the REPEAT marker at the same depth as the child group heading.
  • Nesting is limited to one level (parent β†’ child). Deeper levels are ignored.
  • Groups without a preceding REPEAT line become normal, non-collection groups.

Conditional branching

Branching rules let you jump respondents to other questions or groups based on their answers. They follow this pattern, placed under the (type) line:

? when <operator> <value> -> {target-id}

Example:

# Intro {intro}
## Consent {intro-consent}
(text)
? when equals "Yes" -> {follow-up}
? when equals "No" -> {intro-exit}

Notes:

  • Operators match the in-app condition builder: equals, not_equals, contains, greater_than, greater_equal, less_than, exists, and their not_ variants.
  • Values may be quoted. Operators like exists do not take a value.
  • The target in curly braces can reference a group ID (jump to that group) or a question ID (jump directly to the question).
  • IDs are normalised to lowercase slugs; ensure each ID is unique across all groups and questions.

Section menu layout

Add a SECTION_MENU block at the top of the outline (before any group headings) to switch the survey to the section menu layout, where participants pick which sections to complete. Mark pickable sections with ~ pickable on the section heading; sections without ~ are mandatory (always included).

SECTION_MENU
  prompt: "Which areas would you like to cover?"
  min: 1
  max: 4
  order: authored
  select_all: true
  estimated_time: true

# Demographics {demographics}
## Name {name}
(text)

# Medical history {medical-history}    ~ pickable
## Condition {condition}
(text)

# Medications {medications}    ~ pickable, 5 min
## Drug {drug}
(text)

Config lines are indented under SECTION_MENU:

  • prompt β€” the picker prompt text (quoted).
  • min β€” minimum number of pickable sections the participant must select.
  • max β€” maximum (blank or omitted = no cap).
  • order β€” authored (use the Organise page order) or participant (use the order the participant ticked the boxes).
  • select_all β€” true / false; show a "Select all" button on the picker.
  • estimated_time β€” true / false; show per-section estimated times on the picker.
  • Place ~ pickable after the section heading (and after the {id} if present). Add , N min to set an estimated time.
  • Sections without ~ are mandatory β€” the participant cannot deselect them.
  • A blank line ends the config block. Section headings below it are the actual survey content.

See Survey Layouts for the full guide to when to use the Section menu layout.

Randomised (RCT) layout

Add a RANDOMISED block at the top of the outline to switch the survey to the randomised trial layout, where the system assigns each participant to an arm at first access. Each arm sees only its own sections. Mark which sections belong to which arm with ~ arm:<name> on the section heading; a section can be in multiple arms (e.g. a shared demographics section). Sections without ~ arm: are reachable by all arms (the union of all arm group sets).

RANDOMISED
  strategy: balanced
  seed: 7

# Demographics {demographics}    ~ arm:intervention, arm:control
## Name {name}
(text)

# Intervention {intervention}    ~ arm:intervention
## Dose {dose}
(text)

# Control {control}    ~ arm:control
## Placebo {placebo}
(text)

Config lines are indented under RANDOMISED:

  • strategy β€” balanced (permuted blocks of size sum(ratios) so arm counts stay close to the ratios) or simple (independent weighted random draw per participant).
  • seed β€” optional integer for reproducible dry-runs. Leave blank for real trials so allocation is unpredictable per participant.
  • Place ~ arm:<name> after the section heading (and after the {id} if present). Comma-separate multiple arms: ~ arm:intervention, arm:control.
  • Sections without ~ arm: are reachable by every arm.
  • Arms are created in the order their names first appear in the outline. Allocation ratios default to 1; adjust them on the Organise page after import.
  • A blank line ends the config block.

See Survey Layouts for the full guide to when to use the Randomised (RCT) layout.

Staged (longitudinal) layout

Add a STAGED block at the top of the outline to switch the survey to the staged (longitudinal) layout, where sections unlock over time in defined phase windows. Each phase has a window measured in integer days from an anchor (participant enrolment or survey open). Mark which sections belong to which phase with ~ phase:<name> on the section heading; a section can be in multiple phases (e.g. a demographics section open in every phase). Sections without ~ phase: are in no phase (unreachable; warned on the Organise page).

STAGED
  anchor: enrolment
  phase Baseline: 0 .. 14
  phase Follow-up: 14 .. 28
  phase Review: 180

# Demographics {demographics}    ~ phase:Baseline, phase:Follow-up
## Name {name}
(text)

# Baseline {baseline}    ~ phase:Baseline
## BQ {bq}
(text)

# Follow-up {followup}    ~ phase:Follow-up
## FQ {fq}
(text)

Config lines are indented under STAGED:

  • anchor β€” enrolment (default; each participant's clock starts at their first access) or survey_open (all participants move through phases on the same calendar schedule, offset from Survey.start_at).
  • phase <name>: <start> [.. <end>] β€” defines a phase window in integer days. <end> is optional (blank = open-ended). Windows are half-open: [anchor + start, anchor + end).
  • Place ~ phase:<name> after the section heading (and after the {id} if present). Comma-separate multiple phases: ~ phase:Baseline, phase:Follow-up.
  • Sections without ~ phase: are in no phase (unreachable).
  • Phases are created in the order their names first appear in the outline. Phases referenced only via ~ phase: suffixes (no config line) default to start=0, end=None (open from the anchor).
  • A blank line ends the config block.

See Survey Layouts for the full guide to when to use the Staged (longitudinal) layout.

Guided layout

The Guided layout shows one question per screen with Next/Back navigation, instead of scrolling through all questions on a single page. It is a rendering change β€” it composes with the other layouts (a Section menu or RCT survey in guided layout still shows the picker / assigns the arm first, then walks the chosen sections one question at a time).

The Guided layout has no outline grammar β€” it is set on the Organise page, not via the outline. Branching, repeats, follow-ups, autosave, and save-and-resume all work unchanged.

See Survey Layouts for the full guide to when to use the Guided layout.

Matrix (free navigation) layout

Add a MATRIX block at the top of the outline to switch the survey to the matrix (free navigation) layout, where all sections appear as cards on a landing page. The participant jumps in and out of any section in any order, with completion indicators showing which sections are done. No ~ suffixes are needed β€” every section in the survey is a card on the matrix landing page by default.

MATRIX
  prompt: "Choose a section to begin"
  order: participant
  allow_revisit: false

# Demographics {demographics}
## Name {name}
(text)

# History {history}
## Condition {condition}
(text)

Config lines are indented under MATRIX:

  • prompt β€” the landing-page prompt text (quoted).
  • order β€” authored (use the Organise page order) or participant (order by the order the participant first visited each section).
  • allow_revisit β€” true / false; whether participants can revisit and edit completed sections before final submission.
  • A blank line ends the config block.

The grammar is optional β€” the Organise page UI is the primary config path. The grammar exists so the AI builder and power users can import/export matrix surveys via the outline.

See Survey Layouts for the full guide to when to use the Matrix (free navigation) layout.

Error handling and validation

The Outline provides comprehensive error detection and reporting at two levels:

Live preview (immediate feedback)

As you type your Markdown in the import form, the live structure preview on the right side of the page parses your content in real-time and displays:

  • The hierarchical structure of groups and questions
  • Extracted IDs with color-coded badges (groups in purple, questions in teal)
  • Question types and branching rules
  • Repeat collection indicators
  • Required field markers (red asterisks)
  • Warnings for issues like questions appearing before group headings

This live preview uses the same parsing logic as the backend, so you'll catch most formatting issuesβ€”incorrect notation, missing indentation, malformed branching rules, etc.β€”before you even submit the form. The preview updates instantly as you edit, making it easy to iterate and fix problems.

Backend validation (on submit)

When you click "Create survey", the backend parser performs a complete validation pass and will reject the import if any errors are found. The system checks for:

  • Empty markdown: The document must contain at least one group and question
  • Questions before groups: Questions must be declared inside a group (after a # heading)
  • Missing question types: Every question must have a type declaration in parentheses
  • Invalid branch syntax: Branching rules must include when, a valid operator, and a target ID in curly braces
  • Invalid operators: Only recognised operators (equals, contains, greater_than, etc.) are allowed
  • Missing branch targets: Branch rules must reference a valid group or question ID
  • Empty target IDs: IDs in curly braces cannot be empty
  • Collection syntax errors: REPEAT markers and nested collections must follow correct indentation patterns

If validation fails, the import form redisplays with:

  • Your original Markdown content preserved in the textarea
  • A prominent error alert at the top of the page describing exactly what went wrong and which line number (when applicable)
  • The live preview still active so you can see the structure

This two-layer validation approach ensures that formatting and syntax errors are caught early (in the live preview) while data integrity issues are prevented by the backend before any database changes occur.

Workflow tips

  1. Draft the structure in Markdown using a familiar editor or export from a specification document.
  2. Paste the text into the Outline form and review the live preview to confirm IDs, repeat badges, and branch targets look correct.
  3. When ready, choose Create survey, acknowledge the overwrite warning, and import. The importer recreates question groups, questions, branching conditions, and collections.
  4. Use the visual builder to fine-tune wording, add advanced logic, or connect the imported sections with additional navigation rules.

Troubleshooting

  • Missing (type): Every question must declare a type on the line immediately after the description. The importer fails with a helpful error referencing the question title.
  • Unknown IDs: Branch targets must refer to an existing group or question ID. Check the live preview to confirm spelling.
  • Duplicate IDs: If two headings share the same curly-brace ID, the importer automatically de-duplicates by appending -2, -3, etc. Prefer choosing distinct IDs yourself for clarity.
  • Collections without groups: A REPEAT marker must be followed by a valid group heading at the same nesting level.

Refer back to this guide whenever you need to import surveys in bulk or explain the syntax to collaborators.