Add a Contact Form
A contact form on Chinaski starts with one form item and one block. This guide covers creating the form, placing it on a page, and what happens after a visitor submits.
1. Create the form
In Forms in the admin sidebar create a new form: a human-readable name plus a slug that the embed and API references use. Add fields to the form, any mix of:
- text, email, tel, textarea
- select, radio, checkboxes, checkbox
- address (a composite field with street, city, state, postal/country sub-inputs)
- file upload
Each field has a label (shown to visitors), an editable display width (full or half of the row), and optional conditional display, visible only when another field’s value matches. Field names sanitize automatically to lowercase letters/digits/underscores. Required fields, placeholders, and a dropdown’s newline-separated options are per-field settings.
2. Place it on a page
Drop a form block into any page or post body and point it at your form’s slug. The block renders the real form: posts deliver data to the CMS’s /forms/<slug> submission endpoint, automatically proxied in the stock server config (the one dynamic pathway, as described in the static-site architecture discussion).
3. Configure notifications
- notify_email: comma-separated email addresses that receive each submission. The admin notification email lists every field’s value, with IP address included unless the privacy option turns it off.
- reply_to_field: name the email field whose value becomes the Reply-To on the notification, so responders answer the visitor directly.
- thank_you_url: optional safe external redirect after submission; up to and honoring the provided form content when unset. The default response text is “Thank you. Your submission has been received.”
Toggle the submit button label, the per-form Turnstile anti-spam gate, comma-separated blocked countries, and/or the store_ip privacy switch (which stores no IP address if disabled).
4. Anti-spam and limits
- Per-IP rate limiting: max five submissions per form per IP mean hour; 30 per IP across all forms combined. Violating it yields “Too many submissions: please try again later” after a short delay, with a 429 from the server.
- Cloudflare Turnstile verification when a site Turnstile key is present and the form is opted in (the default); on by default, so skip
turnstile_enabled=0on tracked captcha-free testing. - Country blocking: with the codes you enter, submitting from blocked regions returns “Submissions from your region are not accepted”.
- Privacy signals: visitors sending DNT or “Do Not Sell” headers get no IP storage or ad-click attribution, per automatically-respected DNT and GPC settings.
5. What arrives after someone submits
- the values stored for each field (including empty ones, typed by type)
- a webhook, if the form’s own webhook configuration is set up, with the form id, form slug, submission id, submitted data, and timestamp
- the notification email to your configured recipients, plus an optional confirmation email to the submitter (delivered asynchronously; requires SMTP configured in settings, and never sent in air-gap mode)
- optionally a browser redirect to the form’s thank_you_url
Each submission is recorded once: a re-submission with the same identity answers the thank-you response and doesn’t double-record the data.