Forms

A form collects information from visitors: a contact form, an enquiry, a booking request. You define the fields once in the admin, place the form on a page, and every submission is kept for you to read, optionally emailed to you as it arrives. By the end of this chapter you will have a contact form on a page.

Forms are a feature: a package you add to the site and list in site.config.ts. A site that was created with forms chosen already has this, and a contact form too. In that case go straight to “Make a form”.

Turn forms on

  1. In your site's folder, install the package:
pnpm add @jamiemcconnell/cms-forms
  1. Open site.config.ts, import forms and list it under features:
site.config.ts
import { defineConfig } from '@jamiemcconnell/cms';
import { forms } from '@jamiemcconnell/cms-forms';

export default defineConfig({
  // …the rest of your settings stay as they are…
  features: [forms()],
});
  1. Restart the site. In development, stop pnpm dev with Ctrl+C and run it again. No migration is needed. Forms now appears in the admin's sidebar.

Make a form

  1. In the admin, open Forms and choose New form.
  2. Give it a Name, which only you see, and a Key. The key is lowercase letters, digits and hyphens, such as contact. Blocks refer to the form by its key.
  3. Open the Fields tab and choose Add field for each thing you want to ask. Each field has a Label (what the visitor reads), a Name (what it is called in the stored answers), a Type and a Required box.
  4. In “Email each submission to”, list the addresses that should get a copy of each message, separated by commas. Leave it empty for no email.
  5. Choose Save.

The field types are Text, Email address, Phone number, Number, Paragraph (a longer, multi-line answer), Drop-down, Checkbox and Image upload. A drop-down takes a list of choices, and an image upload takes the most pictures one answer may carry.

Put the form on a page

  1. Open the page in the editor and add a Form block, from the Forms group of the block picker.
  2. In the block's Form field, pick the form you made.
  3. Add a Form field block inside it for each thing the visitor fills in. Each one has a Field select that lists the form's fields.
  4. Publish the page. Publishing checks that every required field of the form is placed, because a form with a required field the page does not show could never be sent.

A Form field can be half width, so two sit side by side, and can have its own label, placeholder, help text and number of rows. The Form block holds the words for the button and for every message the visitor might see, so they can be in your own voice.

The starter site's contact page is a form like this one.

Read the submissions

Every submission is kept. Open Forms and choose a form to see its Submissions, with the unread ones counted on the Forms list. Open a row for the whole submission, including any uploaded images as thumbnails that open full size. Download CSV gives you all of them in a spreadsheet, and Mark all read clears the count.

The email each submission sends is one of the site's emails, and its wording is under Content → Emails. It only goes out once the site has a real email provider (Going live). Until then the submissions are safe in the admin, but nothing is emailed.

What the visitor sees afterwards

After sending, the visitor lands on the form's success page. Every form gets one, which you edit like any page under Content → Callback pages. Visitors can only reach it through the form. To send them somewhere else instead, open the form, find “After submitting” on the Fields tab and choose another callback page.

Let visitors send pictures

A field of type Image upload lets visitors attach images, up to the number you set on the field. Images upload when the visitor presses Send, with a progress bar, and are stored beside the site's media without appearing in the Media library.

The site sets the limits in site.config.ts. These are the defaults, except that types allows every image type the cms serves (JPEG, PNG, WebP, GIF and AVIF) unless you list fewer:

site.config.ts
features: [
  forms({
    uploads: {
      maxBytes: 5 * 1024 * 1024,
      maxFiles: 5,
      types: ['image/jpeg', 'image/png'],
    },
  }),
],

Spam and forgery

Sign-in, registration and every form are protected by two checks. A CSRF token, which the page fetches, stops other websites posting to your forms. A proof-of-work check, from a tool called ALTCHA, makes a bot do some work before it can send. It solves itself in the background as soon as the visitor focuses a field, and no third party is involved.

The check is invisible by default: nothing on the page and no room taken. You can change it in site.config.ts:

site.config.ts
// Show an “I'm not a robot” box above the button again:
security: { captcha: { display: 'standard' } },

// Ask for more work from every browser, for a site under pressure:
security: { captcha: { cost: 5000 } },

// Turn the check off:
security: { captcha: false },

Use one of these lines, not all three. The check needs a secure context, which means https or localhost, so a site on a plain-http address on your local network should turn it off. While the check is on, visitors need JavaScript to send a form; with it off, forms post without script.