Forms
Forms in a storefront — contact, quote request, sample order, callback, registration of interest — are built in Cockpit and rendered by the theme. A customer's team creates the form and its fields; your theme renders whatever they built.
That means a new form is not a deploy. It's a form the customer creates and an editor places on a page.
How it works
Cockpit → a form, with a slug and a field definition
↓
GET /v1/forms → the published form (status: live)
↓
GET /api/forms/{slug} → your BFF, localized for the buyer
↓
the `form` block → FormKit renders the definition verbatim
↓
POST /api/forms/{slug}/submit → POST /v1/forms/submissions
The definition is a FormKit schema — the same machinery the checkout uses. That's why an editor-built form gets real validation, conditional fields, and accessible markup without anyone writing a component for it.
The delivery route
| Route | What it does |
|---|---|
GET /api/forms/{slug} | Returns the published form for that slug — its name, its FormKit definition, and its settings. |
POST /api/forms/{slug}/submit | Records a submission. |
Both are on your own origin; the gateway call happens inside them. See The BFF pattern.
Three behaviours of the delivery route are worth knowing:
Only live forms are served. A draft form is a 404. There is no way for an unpublished form to appear on a storefront, which is the property you want — but it also means "the form 404s" usually means "it hasn't been published", not "the slug is wrong".
The definition is localized before it reaches the browser. Labels, validation messages, and the submit label are resolved to the buyer's locale server-side, so one form definition serves every language rather than one per language.
Settings come with it. The submit button label and the success message are the form's own, set by whoever built it — don't hard-code either in your theme.
The block
The form block renders a form on any page. It's in the standalone content group of the block catalog, so an editor can drop it into a content section like any other block.
Its distinguishing feature is how the form is chosen. Rather than typing a slug, the editor picks from the tenant's live forms in a picker: the theme registers a complex option type through a Blökkli module, and the option renders as a list of real forms rather than a free-text field.
That's the pattern to copy whenever an editor has to reference a platform record. A free-text id field guarantees typos; a picker cannot produce an invalid reference.
The block renders the same way on a live page, on the editor canvas, and in preview — so what the editor sees while placing the form is the form.
Submissions
A submission is recorded against the form on the platform. Submissions are then managed where the form was built, and are reachable from the CLI for scripting and export:
revenexx forms submissions-list --form-id <FORM_ID>
The full command set — create, list, get, update, delete, prune — is in the forms command reference.
Two things to be deliberate about:
- A form is a data-collection surface, so treat its payload as personal data. Don't log submission bodies from your server routes; see Logs.
- Don't use a form as an integration transport. If a quote request has to reach a CRM, build that in Integration Studio off the submission, rather than posting to a third party from your theme's submit route.
Adding your own fields
Because the definition is a FormKit schema, extending what a form can collect is a FormKit question, not a platform one. Register a custom input in the theme's FormKit configuration and it becomes available to schemas rendered by the theme.
The base layer already does this — the barcode-scanner input, for instance, is a custom FormKit input with a camera overlay, which is what makes "scan a SKU into a quick-order form" a field rather than a feature.
Next steps
- Catalog, cart and checkout — the same schema machinery, driving checkout steps.
- The BFF pattern — where the gateway call happens.
- Block options — complex option types, and when to register one.
- Forms command reference — managing forms and submissions from the CLI.
- Integration Studio — routing a submission onwards.