Media and Forms

Media holds the images and files your content points at. Forms collect input from visitors and store it against the site. Both are per site, and both end up in the build.

The media library

The Media page has two top level views: Media (the uploaded library, tracked in the database) and Static (raw theme assets on disk).

Media view

Uploads are organised into three folders, shown as tabs: All Media, Pages, and Posts. The upload folder is chosen for you when you upload from inside an editor.

You can switch between grid and list, pick a card size from XS to L, rename a file, delete one, or select several and delete them in a batch. Clicking an image opens a lightbox.

Resizing images

An image can be resized to an exact width and height, and you choose what happens to the original: create a new image or replace it. Replace rewrites the existing file, so anything already pointing at that URL picks up the new version.

Storage backends

A site stores media locally by default, and can instead be pointed at S3 or Supabase through a saved storage connection. The current backend’s name is printed next to the Media heading, so you always know where an upload is going. Connections can be tested before you save them and re-tested afterwards.

Static view

Static files are raw assets served from your site’s static/ directory, with their original filenames and no database row. Use it for fonts, stylesheets, and scripts that your theme references directly. Allowed extensions are woff2, woff, ttf, otf, css, js, svg, json, and map, capped at 5 MB per file. Uploads can go into a subdirectory, for example fonts.

How media reaches the built site

Media URLs are served under /media/{site_slug}/.... At build time the whole media library is copied into the output, so featured images and inline images resolve in the exported site. Site level static assets are copied afterwards and override theme files of the same name.

Forms

The Forms page lists your forms with their slug, creation date, and submission count.

Building a form

New Form starts with a template picker (or Blank), then drops you into the builder. A form is:

  • a name, a slug, and an optional description
  • one or more steps, each with a name, an optional description, and an optional display condition
  • fields inside each step, each with a label, a type, an order, a required flag, a placeholder, help text, a default value, validation rules (minimum and maximum length, minimum and maximum value), and options for choice fields

Multi step forms are supported directly: steps carry conditions, so later steps can depend on earlier answers.

Form settings

SettingEffect
Submit labeltext on the submit button
Success messagewhat the visitor sees after submitting
Redirect URLwhere to send the visitor instead of showing a message
Notify emailsaddresses that receive a notification per submission
Send confirmationemails the submitter
Webhook URLposts the submission to your own endpoint
Add to membersadds submitters with a valid email field to the site’s Members
Enable Turnstileadds a Cloudflare Turnstile challenge

Notification and confirmation mail goes out through the site’s SMTP configuration, so set that up first in Settings, Email.

Putting a form on a page

There is exactly one embed mechanism that works: an HTML comment marker in the content.

<!-- wpp:form slug="contact" -->

The build replaces each marker with the rendered form HTML. It works in pages (both rich text and Tera mode) and in posts.

You do not have to type it. The form’s page has an “add it to your site” panel that copies the marker, or writes it straight into a page you pick from a dropdown, which avoids an editor round trip mangling the comment. The editors also have an insert-form toolbar button.

Submissions

Each form has a Submissions view: one row per submission, one column per input field, in field order, plus the submission time. It is paginated at 20 per page and has a search box. Individual submissions can be deleted.

The public submit endpoint lives at:

POST /api/v1/sites/{site_slug}/forms/{form_slug}/submit

which is what the rendered form posts to when the site’s api_url is configured. Without an api_url the form still renders but has no action URL to submit to.

Esc