AppSpring Docs

Public forms (PublicFormDecl)

Generated from the doc schema (CatalogDocSchema, @canonify/kernel-catalog/doc): each field’s type, default and description are the schema’s own, and each example is a bundle file that readBundle decodes. A field’s Example is its value in one of those examples.

PublicFormDecl

A public form (runtime, C34).

The forms slot of the doc holds these, keyed by id. In a bundle each is one file, forms/<name>.json, named by its slug, which the file then leaves out.

Field Type Required Default Example Description
id FormId yes (propose assigns it; a new declaration leaves it out) — — A public form id (fm_…); renames keep it.
action ActionId yes — "ac_1b3d5f7h9k" The action a submission calls; it has no subject.
slug Ident yes — "contact" The form’s name in its public address.
title Text yes — "Contact us" The title shown on the form.
inputs Ident[] yes — ["name","email","message"] The action inputs the form shows, in field order.
fixed Record<Ident, Expr> no — {"source":"'web'"} Inputs the form sets itself: actor, clock and literal CX values only.
identity "anonymous" | "email_pin" yes — "email_pin" Who submits: anyone, or a person who proves an email address with a PIN (authz).
onSubmit PublicFormDecl.onSubmit no — (see the example) What a submission does besides the call.
challenge "turnstile" no — "turnstile" A human check the visitor must pass before the submission is looked at; without a passed check it refuses with form.challenge_failed.
silentThankYou true no — true The form accepts that when a rule over other rows refuses a submission (a unique key, a no_overlap, an invariant that reads past its own row), the visitor is thanked as if all were well and nothing is written or sent, so no stranger learns that a row exists. Any refusal after the action starts writing gets the same thanks, a fault in the form too, and only the audit row says why; a fail trigger on the action can tell the author. A form its action can meet such a rule on does not compile without it (form.silent_thank_you_undeclared); a form that cannot is refused for declaring it (form.silent_thank_you_unneeded). To say "taken" instead, add a precondition over a type its visitors read.
open boolean yes — true Whether it accepts submissions; a closed form refuses with form.closed.

forms/contact.json

{
  "action": "ac_1b3d5f7h9k",
  "title": "Contact us",
  "inputs": ["name", "email", "message"],
  "fixed": { "source": "'web'" },
  "identity": "email_pin",
  "onSubmit": {
    "emit": {
      "to": "email.send_template",
      "input": { "recipient": "me.email", "template_id": "'received'" },
      "maps": { "params": { "name": "input.name" } }
    },
    "message": { "text": "Thank you. We will answer within a day." }
  },
  "challenge": "turnstile",
  "silentThankYou": true,
  "open": true
}

PublicFormDecl.onSubmit

What a submission does besides the call.

Field Type Required Default Example Description
emit PublicFormDecl.onSubmit.emit no — (see the example) A delivery sent with the submission, in the same transaction.
message MsgRef yes — {"text":"Thank you. We will answer within a day."} What the person sees after submitting.

PublicFormDecl.onSubmit.emit

A delivery sent with the submission, in the same transaction.

Field Type Required Default Example Description
to string (matching ^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$) yes — "email.send_template" A delivery operation: the only I/O, sent after commit (e.g. webhook.post).
input Record<string, Expr> yes — {"recipient":"me.email","template_id":"'received'"} The CX value of each input of the delivery operation.
maps Record<string, Record<string (matching ^[A-Za-z][A-Za-z0-9_]*$), Expr>> no — {"params":{"name":"input.name"}} The inputs that hold an object (e.g. params, or a webhook body): each field name with its CX value.

This page as Markdown