Appearance
Contact Form
Build a complete contact form that validates input, sanitizes data, saves submissions to the database, and sends an email notification.
Database Table
Create a table called submissions with these columns:
| Column | Type | Description |
|---|---|---|
id | int (auto) | Primary key |
name | varchar(255) | Submitter's name |
email | varchar(255) | Submitter's email |
subject | varchar(255) | Message subject |
message | text | Message body |
created_at | datetime | Submission timestamp |
UI Layout
Build this widget tree:
Form Container
├── Heading ("Contact Us")
├── Text Input (name: "name", label: "Your Name", required: true)
├── Text Input (name: "email", label: "Email Address", required: true)
├── Text Input (name: "subject", label: "Subject", required: true)
├── Textarea (name: "message", label: "Message", required: true)
└── Submit Button ("Send Message")Action Pipeline (onSubmit)
Configure the Form Container's onSubmit action with this pipeline:
Context
→ Rate Limit (maxRequests: 3, windowSeconds: 60, scope: "ip")
→ Validate
→ Sanitize
→ Set Field (created_at = now())
→ Save Row (tableId: submissions)
→ Send Email
→ OutputNode Configurations
Rate Limit:
maxRequests: 3
windowSeconds: 60
scope: "ip"Validate (rules):
json
[
{ "field": "name", "rule": "required" },
{ "field": "name", "rule": "min_length", "value": "2" },
{ "field": "email", "rule": "required" },
{ "field": "email", "rule": "email" },
{ "field": "subject", "rule": "required" },
{ "field": "message", "rule": "required" },
{ "field": "message", "rule": "min_length", "value": "10" }
]Sanitize (fields):
json
[
{ "field": "name", "method": "strip_tags" },
{ "field": "name", "method": "trim" },
{ "field": "email", "method": "sanitize_email" },
{ "field": "subject", "method": "strip_tags" },
{ "field": "subject", "method": "trim" },
{ "field": "message", "method": "esc_html" },
{ "field": "message", "method": "trim" }
]Set Field:
fieldName: "created_at"
expression: "now()"Save Row:
tableId: (your submissions table ID)Send Email:
to: "admin@example.com"
subject: "Contact Form: `{ {row.subject}}`"
body: "Name: `{ {row.name}}`\nEmail: `{ {row.email}}`\nSubject: `{ {row.subject}}`\n\nMessage:\n`{ {row.message}}`"How It Works
- The user fills out the form and clicks "Send Message".
- Context collects all form field values into a single object.
- Rate Limit blocks spam (max 3 submissions per minute per IP).
- Validate checks all fields. If validation fails, error messages are displayed next to the form fields.
- Sanitize cleans the data (strips HTML tags, trims whitespace, validates email format).
- Set Field adds the current timestamp.
- Save Row inserts the submission into the database.
- Send Email notifies the site admin.
- Output returns the result to the frontend (success or error).
Variations
Add a confirmation email to the submitter
Add a second Send Email node after the first:
to: "`{ {row.email}}`"
subject: "We received your message"
body: "Hi `{ {row.name}}`,\n\nThank you for contacting us. We will respond within 24 hours.\n\nBest regards,\nThe Team"Add a honey pot field for bot prevention
Add a hidden Text Input (name: "website", label: "Website"). In the Validate rules, add:
json
{ "field": "website", "rule": "max_length", "value": "0" }Bots fill in all fields; real users leave the hidden field empty.
TIP
Always include Rate Limit and Validate in public-facing form pipelines. Without them, anyone can spam your database and email by calling the REST endpoint directly.