A contact form needs three things: a reply address, a routing category, and enough detail for the receiving team to act.
Ask only what the team will use
const contact = defineForm({
id: "contact",
title: "Contact us",
pages: [{
id: "message",
blocks: [
{ id: "name", kind: "short_text", label: "Name", required: true },
{ id: "email", kind: "email", label: "Email", required: true },
{
id: "topic",
kind: "dropdown",
label: "Topic",
required: true,
options: [
{ id: "product", label: "Product question" },
{ id: "billing", label: "Billing" },
{ id: "security", label: "Security" },
],
},
{ id: "message", kind: "long_text", label: "How can we help?", required: true, maxLength: 2000 },
],
}],
settings: {
submitLabel: "Send message",
successTitle: "Message received",
successMessage: "We'll review it during support hours.",
},
});Configure Team notification email and the optional respondent receipt in the dashboard. Those mail settings stay workspace-managed and aren't overwritten by publishable-key schema sync.
Route without leaking answers
When the topic should pick a ticket queue, use Zapier or a webhook. The direct Slack integration sends a Fillo response link by default and lets a manager allowlist at most three fields — don't select sensitive messages for a broad channel.
Test what you've promised
Check the notification recipient, reply workflow, rate-limit behavior, invalid email error, long-message layout, success state, and destination retry. And make sure the confirmation copy matches your real support coverage.
Try it
Start with a prompt and your coding agent builds the first form, staged for your review — or open the editor.
Related
- Notifications: Configure owner emails and respondent receipts.
- Spam protection: Understand honeypot, timing, and rate-limit controls.
- Support intake example: Try a more structured routing form.