Appearance
Contact form → email automation
Build a public contact form — name, email, message and a file attachment — that stores every submission for you to read, and runs a flow on submit to email you a heads-up. Nothing here needs code.
What you'll build
Two things happen on every submit: the submission is always stored (so a published form can never silently lose data), and — if you wire it — an on-submit flow runs with the submitted values.
1. Create the form
- In your project, create a new form file and open it in the designer.
- Add the fields your form needs. For a contact form:
- a TextField named
name, label "Your name", required - a TextField named
email, label "Email", required - a multi-line TextField named
message, label "Message", required - a FileUpload named
attachment, label "Attachment (optional)"
- a TextField named
- For the FileUpload, set the accept filter to limit file types, e.g.
image/*,.pdf.
See Forms & fields for the full field catalogue and Validation for how required fields are enforced.
NOTE
Marking a field required is checked twice: in the browser, and again on the server when the submission arrives — client-side validation is bypassable, so the server has the final say.
2. Understand the file upload
When a visitor picks a file, the FileUpload field uploads it immediately to your project's private storage and writes the returned gated URL into a hidden field. That URL is captured as part of the submission like any other value — you don't wire anything. Files are capped at 10 MB and served only to project members. See File uploads.
3. Build the notification flow
Create a new flow file in the same project.
Drop three nodes and wire them in a line: Start → Email → End.
Select the Email node and configure it:
Field Value To ${secrets.NOTIFY_EMAIL}Subject New contact form submissionBody You have a new message. Open your Responses inbox to read it.Add a secret named
NOTIFY_EMAIL(your address) in the secrets vault so the recipient isn't hard-coded.
WARNING
Today the Email node resolves ${secrets.X} and ${env.X} in its fields, but it does not interpolate per-submission values like ${start.message} into the subject or body. So keep the email a fixed notification — the actual name, email and message live in your Responses inbox (next step). This keeps the tutorial honest; richer templating in outbound nodes is on the roadmap.
4. Wire the form to the flow
- Go back to the form file. With nothing selected on the canvas, the right-hand panel shows Page settings.
- Find On submit → run flow and choose your notification flow.
The submitted data is handed to the flow's Start node, so inside the flow those values are available as references (start.name, start.email, start.message) — handy if you later add a MongoDB insert or a Template step. The flow runs best-effort: if it errors, your submission is still captured. See Form submissions.
5. Publish and share
Publish the form (public pages serve the last published snapshot, not your live draft), then share its public URL with visitors. See Publish & share.
6. Read your responses
Open the Responses inbox for the form from your dashboard. Every submission — name, email, message and the attachment link — is listed there, and you can export to CSV. See Submissions inbox.
INFO
📸 Screenshot — the Page settings panel with the "On submit → run flow" dropdown open, showing the notification flow selected.