Contact flow and 404
A form, its sent page and a 404 for any Site, built like Ledgerhouse's intake, and what a static host does with a form post.
Every Site needs three pages no visitor asks for by name: the form that takes an inquiry, the page that thanks them, and the page an unknown address lands on. Ledgerhouse, a two-partner bookkeeping firm, takes new clients through an eight-field intake this way.
Prerequisites
- A Site's
navandfooter, from Build a landing page. - Somewhere to receive a post, such as the Worker in Ship a Site.
Ask for what you need
cta-form takes one to eight fields. Each has a lowercase name, a type of text, email, select or textarea, a label of 16 characters and a placeholder of 32; a select lists up to 12 options. The button label runs to 24, and a note under it to 80.
{
"$schema": "https://next.mdxui.dev/schema.json",
"theme": "vaultline",
"frame": "none",
"template": "contact",
"title": "Intake · Ledgerhouse",
"description": "Eight questions. A partner replies within two working days with a fixed fee and a start date.",
"sections": [
… 1 more section
{sections.1 · cta-form
"kind": "section",
"shell": { "inset": "contained", "density": "section" },
"block": {
"type": "cta-form",
"head": {
"eyebrow": "Intake",
"title": "Eight answers, one fixed fee.",
"lede": "A partner reads every intake. The reply names a fee and a start date within two working days."
},
"action": "/intake/sent",
"fields": [
{ "name": "name", "type": "text", "label": "Name" },
{
"name": "email",
"type": "email",
"label": "Email",
"placeholder": "you@business.example"
},
{ "name": "business", "type": "text", "label": "Business name" },
{
"name": "entity",
"type": "select",
"label": "Entity",
"options": ["Sole owner", "Partnership", "Corporation", "Not sure"]
},
{
"name": "software",
"type": "select",
"label": "Software",
"options": [
"A cloud package",
"A desktop package",
"Spreadsheets",
"None yet"
]
},
{
"name": "volume",
"type": "select",
"label": "Transactions",
"options": [
"Under 150 a month",
"150 to 400 a month",
"400 to 1,000 a month",
"Over 1,000 a month"
]
},
{
"name": "behind",
"type": "select",
"label": "Books behind",
"options": [
"Up to date",
"1 to 3 months",
"4 to 12 months",
"More than a year"
]
},
{
"name": "notes",
"type": "textarea",
"label": "Anything else",
"placeholder": "Payroll, owners, deadlines"
}
],
"submit": "Send intake",
"note": "A partner replies within two working days."
}
},
… 2 more sections
]
}
Send the post somewhere that answers
The form renders method="post" to its action, with no script. A static host answers only GET and HEAD, so a post to a file is never received. Route the action to a function: on Cloudflare, worker.ts from Ship a Site forwards each field and answers with a redirect to the sent page. The worked Sites on these docs are static files, so their forms do not send.
{
"$schema": "https://next.mdxui.dev/schema.json",
"theme": "vaultline",
"frame": "none",
"template": "contact",
"title": "Intake · Ledgerhouse",
"description": "Eight questions. A partner replies within two working days with a fixed fee and a start date.",
"sections": [
… 1 more section
{sections.1 · cta-form
"kind": "section",
"shell": { "inset": "contained", "density": "section" },
"block": {
"type": "cta-form",
"head": {
"eyebrow": "Intake",
"title": "Eight answers, one fixed fee.",
"lede": "A partner reads every intake. The reply names a fee and a start date within two working days."
},
"action": "/intake/sent",
"fields": [
{ "name": "name", "type": "text", "label": "Name" },
{
"name": "email",
"type": "email",
"label": "Email",
"placeholder": "you@business.example"
},
{ "name": "business", "type": "text", "label": "Business name" },
{
"name": "entity",
"type": "select",
"label": "Entity",
"options": ["Sole owner", "Partnership", "Corporation", "Not sure"]
},
{
"name": "software",
"type": "select",
"label": "Software",
"options": [
"A cloud package",
"A desktop package",
"Spreadsheets",
"None yet"
]
},
{
"name": "volume",
"type": "select",
"label": "Transactions",
"options": [
"Under 150 a month",
"150 to 400 a month",
"400 to 1,000 a month",
"Over 1,000 a month"
]
},
{
"name": "behind",
"type": "select",
"label": "Books behind",
"options": [
"Up to date",
"1 to 3 months",
"4 to 12 months",
"More than a year"
]
},
{
"name": "notes",
"type": "textarea",
"label": "Anything else",
"placeholder": "Payroll, owners, deadlines"
}
],
"submit": "Send intake",
"note": "A partner replies within two working days."
}
},
… 2 more sections
]
}
Thank them
The sent page is an article page: the nav, a page-head with a title of 64 and a lede of 200 that says what happens next, and the footer. Give it meta.noindex, so no search engine lists it.
{
"$schema": "https://next.mdxui.dev/schema.json",
"theme": "vaultline",
"frame": "none",
"template": "article",
"title": "Intake received · Ledgerhouse",
"description": "Your intake reached Ledgerhouse.",
"meta": { "noindex": true },
"sections": [
{sections.0 · nav
"kind": "nav",
"shell": {
"inset": "bleed",
"density": "none",
"surface": "glass",
"sticky": true
},
"block": {
"type": "nav",
"menu": "none",
"brand": { "href": "/", "text": "Ledgerhouse", "mark": "landmark" },
"links": [
["/services", "Services"],
["/pricing", "Fees"],
["/about", "About"]
],
"cta": { "href": "/intake", "label": "Start intake" }
}
},
{sections.1 · page-head
"kind": "section",
"shell": { "inset": "contained", "density": "section" },
"block": {
"type": "page-head",
"title": "Intake received.",
"lede": "A partner replies within two working days with a fixed fee and a start date."
}
},
{sections.2 · closing
"kind": "closing",
"shell": { "inset": "contained", "density": "closing" },
"block": {
"type": "closing",
"layout": "stack",
"head": { "eyebrow": "While you wait", "title": "See what a close holds." },
"actions": [
{
"href": "/services/monthly-close",
"label": "Monthly close",
"kind": "solid"
}
]
}
},
{sections.3 · footer
"kind": "footer",
"shell": { "inset": "contained", "density": "footer" },
"block": {
"type": "footer",
"layout": "columns",
"brand": { "href": "/", "text": "Ledgerhouse", "mark": "landmark" },
"blurb": "Bookkeeping and tax for small businesses, by two partners and no handoffs.",
"columns": [
{
"title": "The firm",
"links": [
["/services", "Services"],
["/services/monthly-close", "Monthly close"],
["/pricing", "Fees"],
["/about", "About"]
]
},
{
"title": "Clients",
"links": [["/intake", "Intake"], ["/terms", "Terms of engagement"]]
},
{
"title": "For agents",
"links": [
["/records.zip", "Site records (.zip)"],
["/services/monthly-close", "What a close report holds"]
]
}
],
"note": [
"Ledgerhouse is a worked example on mdxui.dev, not a customer.",
"Rendered by @mdxui/site. Forms here do not send."
]
}
}
]
}
Catch every lost address
The 404 record is a page-head and a closing with a way back, between the nav and the footer. A Site without one does not build: ship.ts stops on a missing 404.json, and the host serves the page with status 404.
{
"$schema": "https://next.mdxui.dev/schema.json",
"theme": "vaultline",
"frame": "none",
"template": "article",
"title": "Not found · Ledgerhouse",
"description": "No page at this address.",
"meta": { "noindex": true },
"sections": [
{sections.0 · nav
"kind": "nav",
"shell": {
"inset": "bleed",
"density": "none",
"surface": "glass",
"sticky": true
},
"block": {
"type": "nav",
"menu": "none",
"brand": { "href": "/", "text": "Ledgerhouse", "mark": "landmark" },
"links": [
["/services", "Services"],
["/pricing", "Fees"],
["/about", "About"]
],
"cta": { "href": "/intake", "label": "Start intake" }
}
},
{sections.1 · page-head
"kind": "section",
"shell": { "inset": "contained", "density": "section" },
"block": {
"type": "page-head",
"title": "Not in the books.",
"lede": "No page at this address."
}
},
{sections.2 · closing
"kind": "closing",
"shell": { "inset": "contained", "density": "closing" },
"block": {
"type": "closing",
"layout": "stack",
"head": { "eyebrow": "Not found", "title": "Back to the firm." },
"actions": [
{ "href": "/", "label": "Ledgerhouse", "kind": "solid" },
{ "href": "/services", "label": "Services", "kind": "ghost" }
]
}
},
{sections.3 · footer
"kind": "footer",
"shell": { "inset": "contained", "density": "footer" },
"block": {
"type": "footer",
"layout": "columns",
"brand": { "href": "/", "text": "Ledgerhouse", "mark": "landmark" },
"blurb": "Bookkeeping and tax for small businesses, by two partners and no handoffs.",
"columns": [
{
"title": "The firm",
"links": [
["/services", "Services"],
["/services/monthly-close", "Monthly close"],
["/pricing", "Fees"],
["/about", "About"]
]
},
{
"title": "Clients",
"links": [["/intake", "Intake"], ["/terms", "Terms of engagement"]]
},
{
"title": "For agents",
"links": [
["/records.zip", "Site records (.zip)"],
["/services/monthly-close", "What a close report holds"]
]
}
],
"note": [
"Ledgerhouse is a worked example on mdxui.dev, not a customer.",
"Rendered by @mdxui/site. Forms here do not send."
]
}
}
]
}
Result
The Result is the form under each Theme. Below, the 404 page of every worked Site, each in its own Brand.
{
"$schema": "https://next.mdxui.dev/schema.json",
"theme": "vaultline",
"frame": "none",
"template": "contact",
"title": "Intake · Ledgerhouse",
"description": "Eight questions. A partner replies within two working days with a fixed fee and a start date.",
"sections": [
… 1 more section
{sections.1 · cta-form
"kind": "section",
"shell": { "inset": "contained", "density": "section" },
"block": {
"type": "cta-form",
"head": {
"eyebrow": "Intake",
"title": "Eight answers, one fixed fee.",
"lede": "A partner reads every intake. The reply names a fee and a start date within two working days."
},
"action": "/intake/sent",
"fields": [
{ "name": "name", "type": "text", "label": "Name" },
{
"name": "email",
"type": "email",
"label": "Email",
"placeholder": "you@business.example"
},
{ "name": "business", "type": "text", "label": "Business name" },
{
"name": "entity",
"type": "select",
"label": "Entity",
"options": ["Sole owner", "Partnership", "Corporation", "Not sure"]
},
{
"name": "software",
"type": "select",
"label": "Software",
"options": [
"A cloud package",
"A desktop package",
"Spreadsheets",
"None yet"
]
},
{
"name": "volume",
"type": "select",
"label": "Transactions",
"options": [
"Under 150 a month",
"150 to 400 a month",
"400 to 1,000 a month",
"Over 1,000 a month"
]
},
{
"name": "behind",
"type": "select",
"label": "Books behind",
"options": [
"Up to date",
"1 to 3 months",
"4 to 12 months",
"More than a year"
]
},
{
"name": "notes",
"type": "textarea",
"label": "Anything else",
"placeholder": "Payroll, owners, deadlines"
}
],
"submit": "Send intake",
"note": "A partner replies within two working days."
}
},
… 2 more sections
]
}
{
"$schema": "https://next.mdxui.dev/schema.json",
"theme": "vaultline",
"frame": "none",
"template": "article",
"title": "Intake received · Ledgerhouse",
"description": "Your intake reached Ledgerhouse.",
"meta": { "noindex": true },
"sections": [
{sections.0 · nav
"kind": "nav",
"shell": {
"inset": "bleed",
"density": "none",
"surface": "glass",
"sticky": true
},
"block": {
"type": "nav",
"menu": "none",
"brand": { "href": "/", "text": "Ledgerhouse", "mark": "landmark" },
"links": [
["/services", "Services"],
["/pricing", "Fees"],
["/about", "About"]
],
"cta": { "href": "/intake", "label": "Start intake" }
}
},
{sections.1 · page-head
"kind": "section",
"shell": { "inset": "contained", "density": "section" },
"block": {
"type": "page-head",
"title": "Intake received.",
"lede": "A partner replies within two working days with a fixed fee and a start date."
}
},
{sections.2 · closing
"kind": "closing",
"shell": { "inset": "contained", "density": "closing" },
"block": {
"type": "closing",
"layout": "stack",
"head": { "eyebrow": "While you wait", "title": "See what a close holds." },
"actions": [
{
"href": "/services/monthly-close",
"label": "Monthly close",
"kind": "solid"
}
]
}
},
{sections.3 · footer
"kind": "footer",
"shell": { "inset": "contained", "density": "footer" },
"block": {
"type": "footer",
"layout": "columns",
"brand": { "href": "/", "text": "Ledgerhouse", "mark": "landmark" },
"blurb": "Bookkeeping and tax for small businesses, by two partners and no handoffs.",
"columns": [
{
"title": "The firm",
"links": [
["/services", "Services"],
["/services/monthly-close", "Monthly close"],
["/pricing", "Fees"],
["/about", "About"]
]
},
{
"title": "Clients",
"links": [["/intake", "Intake"], ["/terms", "Terms of engagement"]]
},
{
"title": "For agents",
"links": [
["/records.zip", "Site records (.zip)"],
["/services/monthly-close", "What a close report holds"]
]
}
],
"note": [
"Ledgerhouse is a worked example on mdxui.dev, not a customer.",
"Rendered by @mdxui/site. Forms here do not send."
]
}
}
]
}
{
"$schema": "https://next.mdxui.dev/schema.json",
"theme": "vaultline",
"frame": "none",
"template": "article",
"title": "Not found · Ledgerhouse",
"description": "No page at this address.",
"meta": { "noindex": true },
"sections": [
{sections.0 · nav
"kind": "nav",
"shell": {
"inset": "bleed",
"density": "none",
"surface": "glass",
"sticky": true
},
"block": {
"type": "nav",
"menu": "none",
"brand": { "href": "/", "text": "Ledgerhouse", "mark": "landmark" },
"links": [
["/services", "Services"],
["/pricing", "Fees"],
["/about", "About"]
],
"cta": { "href": "/intake", "label": "Start intake" }
}
},
{sections.1 · page-head
"kind": "section",
"shell": { "inset": "contained", "density": "section" },
"block": {
"type": "page-head",
"title": "Not in the books.",
"lede": "No page at this address."
}
},
{sections.2 · closing
"kind": "closing",
"shell": { "inset": "contained", "density": "closing" },
"block": {
"type": "closing",
"layout": "stack",
"head": { "eyebrow": "Not found", "title": "Back to the firm." },
"actions": [
{ "href": "/", "label": "Ledgerhouse", "kind": "solid" },
{ "href": "/services", "label": "Services", "kind": "ghost" }
]
}
},
{sections.3 · footer
"kind": "footer",
"shell": { "inset": "contained", "density": "footer" },
"block": {
"type": "footer",
"layout": "columns",
"brand": { "href": "/", "text": "Ledgerhouse", "mark": "landmark" },
"blurb": "Bookkeeping and tax for small businesses, by two partners and no handoffs.",
"columns": [
{
"title": "The firm",
"links": [
["/services", "Services"],
["/services/monthly-close", "Monthly close"],
["/pricing", "Fees"],
["/about", "About"]
]
},
{
"title": "Clients",
"links": [["/intake", "Intake"], ["/terms", "Terms of engagement"]]
},
{
"title": "For agents",
"links": [
["/records.zip", "Site records (.zip)"],
["/services/monthly-close", "What a close report holds"]
]
}
],
"note": [
"Ledgerhouse is a worked example on mdxui.dev, not a customer.",
"Rendered by @mdxui/site. Forms here do not send."
]
}
}
]
}