# Public form question types

_Every database field kind an unauthenticated Form may collect, its control and stored value, plus visibility, validation, steps, and publishing rules._

Canonical: https://snoze.dev/help/form-question-types/

A Form is bound to one database. Its field configurations refer to database
field keys; the database schema remains the authority for each kind, option
list, requiredness, and record validation. A public submission goes through the
normal Database record-create path after Form-specific validation.

The current contract contains 11 public-collectable kinds. The canonical list
is generated so a new kind cannot be added silently.

<!-- GENERATED:public-collectable-field-kinds:START -->

Canonical contract values:

- `text`
- `long_text`
- `number`
- `date`
- `select`
- `multi_select`
- `status`
- `checkbox`
- `url`
- `email`
- `phone`

<!-- GENERATED:public-collectable-field-kinds:END -->

## Question kinds

### Short text `text`

A single-line text answer, trimmed before storage. It supports placeholder,
requiredness, help text, case-sensitive regex validation, minimum and maximum
length, custom tooltip, and custom error message. An empty answer is omitted so
the database can enforce requiredness and defaults.

### Long text `long_text`

A multi-line text answer with the same length, pattern, message, placeholder,
and required settings as Short text. It stores one trimmed string; it is not a
Page rich-text block.

### Number `number`

A finite numeric answer. Display can be a normal input, slider, numbered scale,
stars, or rating symbols. Slider and scale use minimum, maximum, and step;
scales may label endpoints; ratings can set a symbol count and icon. Validation
can separately enforce numeric minimum and maximum. The server converts the
submitted string to a number and rejects non-finite input.

### Date `date`

A date-control answer stored as a trimmed date string and then revalidated by
the Database kernel. It has no Number display variants. Its meaning and time
zone follow the underlying Date field settings.

### Select `select`

One option key from the database field. It can render as dropdown, radio group,
or buttons. Options are sorted by database option order and carry their names
and colours to the public renderer. The Database kernel rejects a key that is
not an allowed option.

### Multi-select `multi_select`

Several database option keys. The public endpoint accepts an array or a
comma-separated string, trims each value, and omits an empty list. Option
membership is still checked by the Database kernel. The Select radio/button
variant settings do not redefine the multi-choice control.

### Status `status`

One lifecycle option key. Like Select, it can render as dropdown, radio, or
buttons and uses the database's ordered, coloured options. It stores one key;
the field's option order and completion semantics remain part of the Status
field rather than the Form.

### Checkbox `checkbox`

A boolean answer. The public endpoint accepts a boolean or the case-insensitive
string `true`; other strings become false. False is a real value, not an empty
answer. It has no text-length or numeric-bound behaviour.

### URL `url`

A URL-oriented single-line input stored as a trimmed string. Requiredness and
the underlying Database URL validation apply. Form regex and length rules can
add stricter project-specific checks, but the Form does not fetch the URL.

### Email `email`

An email-oriented input stored as a trimmed string and checked by the Database
field rules. It can also use Form length and regex rules. Passing validation
does not prove the mailbox exists.

### Phone `phone`

A phone-oriented input stored as a trimmed string. Formatting is preserved as
accepted by the Database Phone field; the Form contract does not resolve a
country or promise deliverability.

## Fields public Forms do not collect

User, File, Place, JSON, and Relation are writable database kinds but are
excluded from unauthenticated collection because their IDs or payloads could
expose internal resources or accept unsafe references. Computed, system, Button,
and Time-tracking kinds are not writable answers. If a schema-required field is
not public-collectable, the Form cannot safely publish a valid submission path.

The synthetic record-title question uses key `__record_title__`. It is not a
database field kind and is hidden until explicitly enabled.

## Field configuration

Each question can override its label and icon, visibility, requiredness, help
text, placeholder, display, validation, step number, and order. A schema-required
field is always visible. The synthetic title is opt-in. Every other database
field defaults to visible even when it was added after the Form was last saved;
hide new internal fields explicitly.

Requiredness is enforced by the record-create path. Form validation is checked
in the client for immediate feedback and repeated in the kernel for public
submissions. Invalid regular-expression patterns are ignored rather than
blocking every response, so test a custom pattern before publishing.

## Form flow and publishing

With no steps, all questions share one implicit step. Otherwise each Form step
has an ID, optional title, and description, and question `step` values assign
them by array position. Themes support traditional or conversational flow,
card or plain frame, background colour/gradient/image, radius, colour scheme,
and scoped text, input, accent, and button colours.

Builder edits can live in `draft`; public and in-app respondents read only the
published top-level content. Public config needs `enabled` and an optional
normalised slug. A public response receives no draft fields or internal
uncollectable fields from the resolver.