Form submissions
for static sites.
Self-hosted · One binary · No SaaS
<form action="https://your-server.com/f/YOUR_FORM_ID" method="POST"> <input type="hidden" name="_redirect" value="https://yoursite.com/thanks"> <input type="text" name="name" placeholder="Your name" required> <input type="email" name="email" placeholder="Your email" required> <textarea name="message" placeholder="Your message" required></textarea> <button type="submit">Send</button> </form>
| Field | Purpose |
|---|---|
_redirect | Where to send the user after submission |
_subject | Custom email subject line |
_honeypot | Hidden spam trap — bots fill it, humans don't |
Get notified on every submission — in your Slack workspace, Discord server, or any HTTP endpoint. Configure per-form in the admin UI. Email remains optional.
{
"form_name": "Contact",
"form_id": "abc123",
"submitted_at": "2026-03-26T14:30:00Z",
"fields": {
"name": "Jane",
"email": "jane@example.com",
"message": "Hello!"
}
}
Webhooks fire in a background goroutine — never blocking the form response. A built-in "Test Webhook" button in the admin UI lets you verify your endpoint before going live.
A form notifies you. A waitlist captures unique people and emails them back. Collect signups by email, show each person their place in line, and broadcast to the whole list when you launch — all self-hosted, no mailing-list SaaS.
<form action="https://your-server.com/w/YOUR_WAITLIST_ID" method="POST"> <input type="email" name="email" required> <button>Join the waitlist</button> </form> // JSON response (Accept: application/json) { "success": true, "position": 1247, "already_joined": false }
Optional per-waitlist confirmation email sends the moment someone joins — with {{name}}, {{position}} and {{email}} variables — fired in a background goroutine so it never blocks the response. Manage waitlists, signups, CSV export and broadcasts from the admin Waitlist tab.
Requires Docker + Docker Compose. A $5 VPS is enough.