footer
The foot of a page: brand and blurb, link columns and a ruled note row.
{
"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."
]
}
}
{
"title": "footer",
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "footer"
},
"layout": {
"type": "string",
"enum": [
"columns",
"areas",
"row"
]
},
"brand": {
"type": "object",
"properties": {
"href": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"text": {
"type": "string",
"minLength": 1,
"maxLength": 16
},
"mark": {
"type": "string",
"enum": [
"activity",
"anchor",
"arrow-right",
"arrow-up-right",
"badge-check",
"bell",
"blocks",
"bot",
"check",
"chevron-down",
"chevron-left",
"chevron-right",
"clock",
"code",
"compass",
"copy",
"credit-card",
"database",
"file-code-2",
"file-text",
"files",
"film",
"fingerprint",
"gauge",
"git-commit-horizontal",
"globe",
"history",
"key-round",
"landmark",
"layers",
"layout-grid",
"library",
"link",
"list",
"map-pin",
"menu",
"message-square",
"mic",
"plug",
"radar",
"refresh-cw",
"search",
"shield-check",
"ship",
"shopping-cart",
"sliders-horizontal",
"sparkles",
"terminal",
"ticket",
"waves",
"webhook",
"x"
]
},
"suffix": {
"type": "string",
"minLength": 1,
"maxLength": 8
},
"tile": {
"type": "boolean"
}
},
"required": [
"href"
],
"additionalProperties": false
},
"blurb": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"columns": {
"maxItems": 4,
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {
"type": "string",
"minLength": 1,
"maxLength": 16
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 40
},
"links": {
"minItems": 1,
"maxItems": 12,
"type": "array",
"items": {
"type": "array",
"prefixItems": [
{
"type": "string",
"minLength": 1,
"maxLength": 160
},
{
"type": "string",
"minLength": 1,
"maxLength": 48
}
],
"items": false,
"minItems": 2,
"maxItems": 2
}
}
},
"required": [
"title",
"links"
],
"additionalProperties": false
}
},
"cta": {
"type": "object",
"properties": {
"href": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 24
},
"icon": {
"type": "string",
"enum": [
"activity",
"anchor",
"arrow-right",
"arrow-up-right",
"badge-check",
"bell",
"blocks",
"bot",
"check",
"chevron-down",
"chevron-left",
"chevron-right",
"clock",
"code",
"compass",
"copy",
"credit-card",
"database",
"file-code-2",
"file-text",
"files",
"film",
"fingerprint",
"gauge",
"git-commit-horizontal",
"globe",
"history",
"key-round",
"landmark",
"layers",
"layout-grid",
"library",
"link",
"list",
"map-pin",
"menu",
"message-square",
"mic",
"plug",
"radar",
"refresh-cw",
"search",
"shield-check",
"ship",
"shopping-cart",
"sliders-horizontal",
"sparkles",
"terminal",
"ticket",
"waves",
"webhook",
"x"
]
}
},
"required": [
"href",
"label"
],
"additionalProperties": false
},
"social": {
"maxItems": 6,
"type": "array",
"items": {
"type": "object",
"properties": {
"mark": {
"type": "string",
"enum": [
"bluesky",
"github",
"linkedin",
"npm",
"reddit",
"x",
"ycombinator"
]
},
"href": {
"type": "string",
"minLength": 1,
"maxLength": 160
}
},
"required": [
"mark",
"href"
],
"additionalProperties": false
}
},
"form": {
"type": "object",
"properties": {
"action": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 24
},
"placeholder": {
"type": "string",
"minLength": 1,
"maxLength": 32
},
"submit": {
"type": "string",
"minLength": 1,
"maxLength": 16
}
},
"required": [
"action",
"label",
"placeholder",
"submit"
],
"additionalProperties": false
},
"note": {
"type": "array",
"prefixItems": [
{
"type": "string",
"minLength": 1,
"maxLength": 96
},
{
"type": "string",
"minLength": 1,
"maxLength": 96
}
],
"items": false,
"minItems": 2,
"maxItems": 2
}
},
"required": [
"type",
"layout",
"brand",
"columns",
"note"
],
"additionalProperties": false
}When to use
End every page of a Site with one footer. columns sets two or three titled link columns beside the brand and its blurb, and one column is titled For agents. areas places the same columns in a grid with the call under the brand.
row puts the brand and a single row of links on one line, for a Site of a few pages. Every layout ends on a note of two lines, at most 96 characters each.
In the For agents column, link what an agent reads: the page records, the schema, llms.txt.
No neighbor does this job.
The record
{
"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."]
}
}Smallest that parses
{
"type": "footer",
"layout": "columns",
"brand": { "href": "/", "text": "Ledgerhouse" },
"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."]
}Fields and bounds
From @mdxui/site@7.0.0-alpha.0. A count reads as min–max × item; a string bound is its maximum length in characters, and links its refusal.
| Prop | Type and bound | Required |
|---|---|---|
layout | "columns" | "areas" | "row" | yes |
brand | object | yes |
brand.href | string ≤160 | yes |
brand.text | string ≤16 | no |
brand.mark | icon or mark name (52) | no |
brand.suffix | string ≤8 | no |
brand.tile | boolean | no |
blurb | string ≤160 | no |
columns | 0–4 × object | yes |
columns[].title | string ≤16 | yes |
columns[].label | string ≤40 | no |
columns[].links | 1–12 × [string ≤160, string ≤48] | yes |
cta | object | no |
cta.href | string ≤160 | yes |
cta.label | string ≤24 | yes |
cta.icon | icon or mark name (52) | no |
social | 0–6 × object | no |
social[].mark | "bluesky" | "github" | "linkedin" | "npm" | "reddit" | "x" | "ycombinator" | yes |
social[].href | string ≤160 | yes |
form | object | no |
form.action | string ≤160 | yes |
form.label | string ≤24 | yes |
form.placeholder | string ≤32 | yes |
form.submit | string ≤16 | yes |
note | [string ≤96, string ≤96] | yes |
Variants and counts
Three layouts: columns, areas and row. Any of them can carry a sign-up form and up to six social marks.
One record in five Themes
Shells
In three Businesses
Carried by every Template. Seen on pages/ledgerhouse/home.json, section 7.
Do and do not
{
"type": "footer",
"layout": "columns",
"brand": {
"href": "/sites/harbor/",
"text": "Harbor tides",
"mark": "waves"
},
"blurb": "Tide windows per berth, as an API.",
"columns": [
{
"title": "Product",
"links": [
[
"/sites/harbor/pricing",
"Pricing"
]
]
},
{
"title": "Partners",
"links": [
[
"/sites/harbor/integrations",
"Integrations"
]
]
},
{
"title": "Writing",
"links": [
… 21 more linesblockAccessibility
| Check, on the exemplar render | Limit | Now | Pass |
|---|---|---|---|
| Skipped heading levels | 0 | 0 | yes |
| Unnamed nav landmarks | 0 | 3 of 3 | no |
| Scroll regions a keyboard cannot reach | 0 | 0 of 0 | yes |
| Copy controls that announce the result | all | 0 of 0 | yes |
| Images and icons with no text alternative | 0 | 0 | yes |
Text pairs below AA across the 5 Themes and every scheme they emit: 5. See Render checks.
- Landmark The footer renders the page
footer, aftermain. Each link column is its ownnav; give it alabelto name it, as the check above counts. - Heading level Column titles render as
h4. - Focus order Tab runs brand, then each column top to bottom, then the form and the social marks.
Related
No neighbor does this job.