Configure the form › In the workspace

Define the form

The Define tab is where you shape the form: create it — or import one you already have — and add its fields. The prompts that drive the extraction come afterwards, in Engineer.

The form header with the Define tab highlighted
The Define tab, in the form's header — next to it, the version you are editing.

Note

Before you change anything, check the version chooser next to the tabs — what you edit here belongs to the version selected there.

Create a form

Before you can open a form's Define tab, the form has to exist. Open Forms in your workspace and click Create form: give it a name — people see it, your code never does — and you land in the editor with an empty draft.

The Forms page with the Create form button highlighted
Forms → Create form.

From then on, four things identify the form — three of which your code passes to start a session:

  • Its name — for people, shown in the workspace.
  • Its generated key (spnr_…) — form.key in your code.
  • A version, each with its own key (v1, v2, …) — form.version. The fields belong to the version; the first one is created with the form.
  • A language among those the version supports — form.language. The prompts are written per language.

Note

Which of these decide what, and how a version is published, is in Configure the form › In the workspace › Publish.

Import a form

You can also import a form you already have instead of creating it field by field: Import, next to Create form, takes a JSON of the form's fields, so a form that already exists in your application never has to be retyped. It accepts a file or pasted JSON and creates a draft version. The import carries no prompts: you write them yourself in the Engineer tab afterwards, and publish the version, like for any other form.

The Forms page with the Import button highlighted
Forms → Import.

Note

Prompts are not part of the JSON for the moment — carrying them along is an upcoming feature. Until then an import brings the fields, and Export produces the same shape from any version: the fields, never the prompts or the languages.

JSON structure: import and export

One document per form: a name and a fields array, in the order your form shows them. Per field, field_id is required — imports never invent ids, they are your contract — and everything else falls back to a sensible default: label (the id), type (text), options and range (null unless the type needs them) and code_defined_config (false). The same document comes back out of Export.

json
{
  "name": "Patient intake",
  "fields": [
    {
      "field_id": "full_name",
      "label": "Full name",
      "type": "text",
      "options": null,
      "range": null,
      "code_defined_config": false
    },
    {
      "field_id": "insurance",
      "type": "select",
      "options": ["None", "Public", "Private"]
    },
    {
      "field_id": "severity",
      "type": "slider",
      "range": [0, 10]
    }
  ]
}

Generate the JSON from your existing form

Paste this prompt into your AI coding agent together with your form — a component file, a screenshot, a schema — and it produces the import JSON above, with your real field ids:

text
You are converting an existing form into a Speechineer form-import JSON. The form is
whatever I give you as context: a screenshot, an HTML/JSX/Vue/Angular/Svelte template, a
form-library schema, a database table, or a description. If I gave you a repository, find
the form and read the real field names.

Return one JSON document per form: {"name": "...", "fields": [...]} — with per field:
- "field_id" (required): the identifier my application already uses for that field — the
  name/id attribute, the form-control key, the column name. Copy it EXACTLY, including
  camelCase; never tidy it into another style. It must start with a letter and contain
  only letters, digits or underscores. Only invent an id (from the label, snake_case)
  when I gave you no code.
- "label": the human name of the field.
- "type": one of text, textarea, email, phone, url, integer, float, checkbox, date, time,
  datetime, select, multiselect, slider. The control wins over the meaning: an
  <input type="range"> is a slider even when it counts something.
- "options": the exact stored values for select/multiselect (the value, not the display
  label) — required for those types, at least one. Otherwise null.
- "range": [min, max] for slider — required for it. Otherwise null.
- "code_defined_config": true ONLY when the values are not fixed at design time (options
  from my database, or that change per user or language). Still include representative
  options/range — the form is tested against them in the workspace; at runtime my code
  supplies the real ones. When torn, use false.

Do not include prompts in the JSON — the import carries the form's shape only; extraction
prompts are written in the workspace afterwards. Instead, list under the JSON one suggested
extraction prompt per field (one sentence: what to pull out and how to resolve what a
speaker says — units, formats, relative dates), for me to paste into the workspace.

Skip fields nobody would speak: passwords, one-time codes, card numbers, captchas, file
uploads. Name what you skipped. Make reasonable choices instead of asking questions, and
list the assumptions you made.

Add a field

Add one field per input your form has. The order of the list is the order your form shows, and one field set serves every language of the version. Each field has an id, a label, a type and, for choice and slider fields, its options.

The Define tab of a freshly created form with the Add field button highlighted
The editor right after Create form: Add field opens the first field.

Tip

Saving stores the fields as a draft of the version. A draft is never served — publishing is a separate, deliberate step, described in Configure the form › In the workspace › Publish.

Field ID

The field id is how recognized values reach your code: they arrive keyed by it, exactly as configured. Ids must start with a letter and continue with letters, digits or underscores (any script; case-sensitive; at most 128 characters), and be unique within a version.

Warning

Choose the identifiers your application already uses — full_name, guestEmail — and then treat them as frozen: changing an id in a later version breaks every integration still writing to the old one, with no error on either side.

Label

The label is the field's human name in the workspace — what you and your colleagues read in the editor and in the Engineer tab. It never changes what your application renders, and it is not what the extraction reads: that is the field's prompt, written per language in Engineer.

Type

The type says what kind of value the field holds, and so what the extraction is allowed to return for it:

TypeHoldsRequired configuration
texta short free-text value — a name, a city
textarealonger free text — notes, descriptions
emailan email address
phonea phone number
urla link
integera whole number — age, count, years
floata decimal — amount, weight, temperature
checkboxyes or no — consent, an opt-in
datea calendar date
timea time of day
datetimea date with a time
selectone value from a fixed listoptions — at least one
multiselectany number of values from a fixed listoptions — at least one
slidera number on a bounded scalerange — [min, max]

Options

select and multiselect take a list of options, a slider a range. The options are the exact strings your application expects back — recognized values are matched against them and the match is returned verbatim.

Warning

Write the options as the values your application stores, not as the text it shows. If your app saves private and displays “Private insurance”, the option must be private: what comes back is the option exactly as written here, and a display text would reach your code as a display text.

A choice or slider field can be marked set by code: its options or range then come from your application at session start — options loaded from your database, day names in the language being spoken — instead of the configuration saved in the workspace. You mark it with Set by your code in the field's editor. The workspace keeps its own options or range for the field — representative values that the Engineer tab tests against — and your application replaces them when a session starts. Typical uses: lists that live in your data (products, departments, locations), values that differ per user, or values that differ per language, such as day names.

Warning

The workspace still requires a configuration on a field marked set by code — representative options or a range — because that is what the Engineer tab runs against; at runtime it is ignored and your code's values win. A marked field with no entry stops the session from starting; an entry for an unmarked field is ignored — the workspace's own configuration wins.