Page
A Page is one record: its Theme, an optional Template, its frame, its head and three to twenty sections, rendered as one document.
A Page is an addressable page of a Site, of a named type such as pricing, about one Thing or each member of a Collection.Page startupbuilder.dev
What mdxui renders
One record, parsed by PageSchema and rendered by renderPage. This is Harbor's pricing page, five sections; open the Record tab to read the record that drew it, or pick another Theme.
{
"$schema": "https://next.mdxui.dev/schema.json",
"theme": "quaypoint",
"template": "api-product",
"title": "Plans · Harbor tides",
"description": "Three plans for the Harbor tides API, by calls a month.",
"frame": "none",
"sections": [
{
"kind": "nav",
"shell": { "inset": "bleed", "density": "none", "surface": "glass", "sticky": true },
"block": {
"type": "nav",
"menu": "none",
"brand": { "href": "/", "text": "Harbor tides", "mark": "waves" },
"links": [
["/pricing", "Pricing"],
["/integrations", "Integrations"],
["/blog", "Blog"]
],
"cta": { "href": "/contact", "label": "Talk to the harbor" }
}
},
{
"kind": "section",
"shell": { "inset": "contained", "density": "section" },
"block": {
"type": "pricing",
"head": { "eyebrow": "Plans", "title": "Priced by the call." },
"layout": "ruled",
"tiers": [
{
"name": "Deck",
"price": "$0",
"note": "a month",
"features": ["1,000 calls a month", "Every berth", "Fourteen days ahead"],
"cta": "Start free",
"href": "/contact"
},
{
"name": "Bridge",
"price": "$49",
"note": "a month",
"features": ["50,000 calls a month", "Draft windows", "Webhook alerts"],
"cta": "Choose Bridge",
"href": "/contact",
"featured": true
},
{
"name": "Harbor",
"price": "$490",
"note": "a month",
"features": ["1,000,000 calls a month", "Every Bridge feature", "A named harbor master"],
"cta": "Talk to the harbor",
"href": "/contact"
}
],
"featuredBadge": "Most chosen"
}
},
{
"kind": "section",
"shell": { "inset": "contained", "density": "section" },
"block": {
"type": "plan-table",
"title": "Every plan, fact by fact",
"columns": ["Calls a month", "Days ahead", "Windows", "Alerts"],
"rows": [
{
"name": "Deck",
"cells": ["1,000", "14", "no", "no"]
},
{
"name": "Bridge",
"cells": ["50,000", "14", "yes", "yes"]
},
{
"name": "Harbor",
"cells": ["1,000,000", "30", "yes", "yes"]
}
]
}
},
{
"kind": "section",
"shell": { "inset": "contained", "density": "section" },
"block": {
"type": "faq",
"head": { "eyebrow": "Questions", "title": "Before you choose." },
"items": [
{ "q": "What counts as a call?", "a": "One request to any route. A tide table for 14 days is one call." },
{ "q": "What happens past the limit?", "a": "Calls past the month’s limit return 429 until the month turns. Nothing is billed past the plan." },
{ "q": "Can I change plans?", "a": "Yes, at any time. The new limit applies from the next call." }
]
}
},
{
"kind": "footer",
"shell": { "inset": "contained", "density": "footer" },
"block": {
"type": "footer",
"layout": "row",
"brand": { "href": "/", "text": "Harbor tides", "mark": "waves" },
"blurb": "Tide tables for every berth, as one API.",
"columns": [
{
"title": "Product",
"links": [
["/pricing", "Pricing"],
["/integrations", "Integrations"]
]
},
{
"title": "Harbor",
"links": [
["/blog", "Blog"],
["/contact", "Contact"],
["/terms", "Terms"]
]
}
],
"note": ["Harbor tides is a worked example on mdxui.dev, not a customer.", "Rendered by @mdxui/site. Forms here do not send."]
}
}
]
}
Each field decides one thing; a section decides its own layout and content.
From @mdxui/site@7.0.0-alpha.0.
| Field | Type and bound | Required | Decides |
|---|---|---|---|
theme | "certificate" | "vaultline" | "quaypoint" | "callboard" | "directory" | yes | The Brand the page wears: tokens, typefaces and policies |
template | "api-product" | "article" | "blog" | "post" | "contact" | "directory-list" | "directory-product" | no | The page kind; it names the slots the sections fill |
title | string ≤64 | yes | The document title and the share title |
description | string ≤320 | yes | The meta and share description |
meta | object | no | The head: canonical address, icons, share image, noindex |
meta.canonical | string ≤160 | no | — |
meta.type | "website" | "article" | no | — |
meta.icon | string ≤160 | no | — |
meta.iconFallback | string ≤160 | no | — |
meta.appleTouchIcon | string ≤160 | no | — |
meta.image | object | no | — |
meta.noindex | boolean | no | — |
jsonLd | 0–4 × object | no | Structured data, written into the head as given |
frame | "none" | "sheet" | "split" | yes | The frame around every section: none, one ruled sheet, or a split with an aside |
sections | 3–20 × section | yes | The page itself, in order |
Every bound, with its refusal, is on Page fields and bounds.
How it maps
| startupbuilder.dev | mdxui today | Status |
|---|---|---|
path | Not in the record: the file's place decides it, so pages/harbor/pricing.json serves /pricing | Gap: No counterpart in the record; the intended Noun drafts one |
kind | template, one of seven. A landing or pricing page is api-product; a terms page is article | Alpha: Renders today from the published packages |
from | Not in the record: no lineage back to a Hypothesis slot | Gap: No counterpart in the record; the intended Noun drafts one |
uses Components | sections, three to twenty, each one Section type | Alpha: Renders today from the published packages |
about one Thing | Literal props: the agent writes the Thing's facts into the record | Gap: No counterpart in the record; the intended Noun drafts one |
each member of a Collection | One record per member, written out | Gap: No counterpart in the record; the intended Noun drafts one |
Status
A Page record parses and renders today, and none of its fields is a Spec. The record binds to no other record: an agent fills every field with literal words, and the bounds keep those words inside the design.
Intended Noun
The three Page props the record lacks, drafted as the fields that close the gap.
noun: Page record
projects: startupbuilder.dev Page, quoted above; defines nothing new
adds:
path: { type: string, pattern: "^/[a-z0-9/-]*$", max: 160, required: true, note: the address under its Site; today the file path }
kind: { type: enum, values: the startupbuilder.dev page types, required: false, note: maps onto template }
from: { type: string, pattern: "Hypothesis#<slot>@v<version>", required: false, note: lineage, never rendered }
about: { type: Thing reference, required: false, note: the Thing whose fields fill the sections }