Forms
Add forms to any page. Write form: on its own line followed by indented YAML — sitemd renders it as an interactive form that submits via webhook.
Quick example
form:
webhook: https://hooks.example.com/contact
submitLabel: Send
fields:
- id: email
type: email
label: Email
required: true
- id: message
type: longtext
label: Message
placeholder: Your message...
Thank you for your submission!
Forms submit a JSON payload to the webhook URL via POST. No backend needed from sitemd — bring your own endpoint (Zapier, Make, n8n, a serverless function, etc).
Field types
Short text
Single-line text input. The default type if type is omitted.
form:
webhook: https://hooks.example.com/demo
fields:
- id: company
type: shorttext
label: Company Name
placeholder: Acme Inc.
Thank you for your submission!
Long text
Multi-line textarea.
form:
webhook: https://hooks.example.com/demo
fields:
- id: bio
type: longtext
label: Tell us about yourself
placeholder: A few sentences...
Thank you for your submission!
Input with built-in email validation.
form:
webhook: https://hooks.example.com/demo
fields:
- id: email
type: email
label: Email Address
required: true
placeholder: you@example.com
Thank you for your submission!
Phone
form:
webhook: https://hooks.example.com/demo
fields:
- id: phone
type: phone
label: Phone Number
Thank you for your submission!
Number
Supports min and max constraints.
form:
webhook: https://hooks.example.com/demo
fields:
- id: quantity
type: number
label: Quantity
min: 1
max: 100
Thank you for your submission!
Date
form:
webhook: https://hooks.example.com/demo
fields:
- id: startDate
type: date
label: Start Date
Thank you for your submission!
Name
Composite field that renders first and last name side by side. Submitted as { first: "...", last: "..." }.
form:
webhook: https://hooks.example.com/demo
fields:
- id: fullName
type: name
label: Full Name
required: true
Thank you for your submission!
Use name-first or name-last for standalone single-name fields.
Dropdown
form:
webhook: https://hooks.example.com/demo
fields:
- id: plan
type: dropdown
label: Plan
options:
- Free
- Pro
- Enterprise
Thank you for your submission!
Radio
Single-select radio buttons.
form:
webhook: https://hooks.example.com/demo
fields:
- id: priority
type: radio
label: Priority
options:
- Low
- Medium
- High
Thank you for your submission!
Checkbox
Multi-select checkboxes. Submitted as an array.
form:
webhook: https://hooks.example.com/demo
fields:
- id: interests
type: checkbox
label: Interests
options:
- Product Updates
- Technical Blog
- Case Studies
Thank you for your submission!
Rating
Star rating (1–5). Uses your theme's accent color.
form:
webhook: https://hooks.example.com/demo
fields:
- id: rating
type: rating
label: How would you rate us?
Thank you for your submission!
Country
Dropdown with ~195 countries. Countries listed in settings/forms.md under countrySortToTop appear first.
form:
webhook: https://hooks.example.com/demo
fields:
- id: country
type: country
label: Country
Thank you for your submission!
Address
Composite field with street, city, state, zip, and country. Submitted as a nested object.
form:
webhook: https://hooks.example.com/demo
fields:
- id: address
type: address
label: Mailing Address
Thank you for your submission!
Heading and paragraph
Display-only fields for structuring your form. Not included in the submission payload.
form:
webhook: https://hooks.example.com/demo
fields:
- id: section1
type: heading
text: Personal Information
- id: section1desc
type: paragraph
text: Fields marked with * are required.
- id: name
type: shorttext
label: Your Name
required: true
Personal Information
Fields marked with * are required.
Thank you for your submission!
Hidden
Not visible to the user. Useful for tracking data or passing context via URL prefill.
form:
webhook: https://hooks.example.com/demo
fields:
- id: source
type: hidden
default: landing-page
Consent
Required agreement checkbox. The label text appears inline beside the checkbox. Always required — the form cannot be submitted without checking it.
form:
webhook: https://hooks.example.com/demo
fields:
- id: terms
type: consent
label: I agree to the terms and conditions.
Thank you for your submission!
Field properties
Every field requires id and type. All other properties are optional.
| Property | Description |
|---|---|
id |
Unique identifier. Used in the webhook payload and URL prefill. |
type |
Field type (see above). |
label |
Display label shown above the field. |
description |
Help text shown below the label. |
placeholder |
Placeholder text inside the input. |
required |
Set to true to require this field before submission. |
options |
List of choices for dropdown, radio, and checkbox types. |
default |
Default value. For dropdowns/radios, pre-selects the matching option. |
text |
Display text for heading and paragraph types. |
min / max |
Numeric constraints for number type. |
prefill |
Custom URL parameter name for prefilling (defaults to id). |
showWhen |
Conditional visibility — fieldId = value or fieldId != value. |
showWhenAny |
Show if any condition matches (OR logic). List of conditions. |
showWhenAll |
Show if all conditions match (AND logic). List of conditions. |
Form settings
| Property | Description |
|---|---|
webhook |
URL to POST form data to (required). |
submitLabel |
Text on the submit button. Default: "Submit". |
thankYou |
Message shown after successful submission. |
redirectUrl |
URL to redirect to after submission (instead of thank you message). |
Conditional logic
Show or hide fields based on other field values using showWhen:
form:
webhook: https://hooks.example.com/demo
fields:
- id: contactMethod
type: dropdown
label: Preferred Contact Method
options:
- Email
- Phone
- Mail
- id: contactEmail
type: email
label: Email Address
showWhen: contactMethod = Email
- id: contactPhone
type: phone
label: Phone Number
showWhen: contactMethod = Phone
- id: contactAddress
type: address
label: Mailing Address
showWhen: contactMethod = Mail
Thank you for your submission!
For complex conditions, use showWhenAny (OR) or showWhenAll (AND):
- id: urgentNote
type: paragraph
text: We'll prioritize your request.
showWhenAll:
- priority = High
- contactMethod = Phone
Multi-page forms
Split forms into pages with optional conditional routing. Use pages instead of fields:
form:
webhook: https://hooks.example.com/apply
thankYou: Application received!
submitLabel: Submit Application
pages:
- id: info
title: Your Info
fields:
- id: name
type: name
label: Name
required: true
- id: role
type: radio
label: Role
options:
- Developer
- Designer
next:
- when: role = Developer
goto: dev
- default: general
- id: dev
title: Developer Questions
fields:
- id: language
type: dropdown
label: Primary Language
options:
- JavaScript
- Python
- Rust
- id: general
title: General
fields:
- id: about
type: longtext
label: Tell us about yourself
required: true
Your Info
Step 1 of 3Developer Questions
Step 2 of 3General
Step 3 of 3Application received!
Pages flow sequentially by default. Add next rules to route conditionally — the first matching when condition wins, or default is used as a fallback. The last page shows the submit button.
URL prefill
Pre-populate form fields by adding query parameters to the URL. By default, the parameter name matches the field id:
https://yoursite.com/contact?email=jane@example.com&source=newsletter
Use the prefill property to map a different URL parameter to a field:
- id: email
type: email
label: Email
prefill: user_email
Now ?user_email=jane@example.com fills the email field.
Answer piping
Reference field values in labels and descriptions using {{fieldId}}:
- id: name
type: shorttext
label: Your Name
- id: feedback
type: longtext
label: Thanks {{name}}, what's on your mind?
The label updates live as the user types.
Webhook payload
When a form is submitted, sitemd POSTs JSON to your webhook URL:
{
"formId": "form-1",
"submittedAt": "2026-03-16T14:30:00.000Z",
"page": {
"title": "Contact Us",
"url": "https://yoursite.com/contact"
},
"fields": {
"email": "jane@example.com",
"message": "Hello!",
"name": { "first": "Jane", "last": "Smith" },
"interests": ["Product Updates", "Case Studies"],
"rating": "4",
"address": {
"street": "123 Main St",
"city": "Austin",
"state": "TX",
"zip": "78701",
"country": "United States"
}
},
"meta": {
"referrer": "https://google.com",
"userAgent": "Mozilla/5.0...",
"locale": "en-US"
}
}
- Composite fields (
name,address) submit as nested objects - Checkboxes submit as arrays
- Hidden conditional fields are excluded
- Display-only fields (
heading,paragraph) are excluded
Global settings
Configure defaults for all forms in settings/forms.md:
---
# Countries to sort to top of country dropdown
countrySortToTop:
- United States
- United Kingdom
- Canada
- Australia
# Default submit button label
submitLabel: Submit
# Default thank you message
thankYou: Thank you for your submission!
# Anti-spam honeypot field (invisible, catches bots)
honeypot: true
---
Per-form settings override these defaults.
Notes
- Forms inside fenced code blocks are displayed as text, not rendered.
- Multiple forms can appear on the same page — each gets a unique ID.
- Forms inherit your theme's colors, fonts, and border radius automatically across light, dark, and paper modes.
- The honeypot field is invisible to users but catches bots. When a bot fills it, the form silently "succeeds" without actually submitting.
- Validation runs client-side. Required fields show inline error messages. Email fields validate the format automatically.
- Forms work with sitemd's instant navigation — they reinitialize after page transitions.