Alpha: Ships on npm at 7.0.0-alpha.07.0.0-alpha.0
JSON
The record is its own JSON rendering: served beside each page, with the page schema and one schema per Section type beside it.
A Page record needs no converter to become JSON: it is JSON. This site serves every record beside its render, byte for byte. An agent reads the exact input of the page a person sees.
What mdxui renders
Harbor's contact page as a person reads it, and as an agent reads it: open the Record tab.
{
"$schema": "https://next.mdxui.dev/schema.json",
"theme": "quaypoint",
"template": "contact",
"title": "Contact · Harbor tides",
"description": "Ask a harbor master for a berth, a plan or an integration.",
"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": "cta-form",
"head": { "eyebrow": "Contact", "title": "Talk to the harbor.", "lede": "A harbor master answers within one working day." },
"action": "/contact/sent",
"fields": [
{ "name": "name", "type": "text", "label": "Name" },
{ "name": "email", "type": "email", "label": "Email", "placeholder": "you@example.com" },
{
"name": "topic",
"type": "select",
"label": "About",
"options": ["A new berth", "A plan", "An integration"]
},
{ "name": "message", "type": "textarea", "label": "Message" }
],
"submit": "Send",
"note": "The form posts with no script."
}
},
{
"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."]
}
}
]
}
Where this site serves it
| Address | Holds |
|---|---|
/pages/home.json | The landing's record |
/pages/harbor/contact.json | One worked page's record; every worked page has one at /pages/<site>/<path>.json |
/schema.json | PageSchema as JSON Schema, for an editor or an agent |
/schema/sections/hero.json | One Section type's schema; there is one for each of the 27 |
/components/variant/hero/split.json | One section record, as a Section type page's Record tab shows it |
Validate it
JSON Schema carries the shape and the bounds. PageSchema carries them and the refinements JSON Schema cannot say, such as a head that needs a title or a lede, so validate with it:
import { PageSchema } from '@mdxui/site';
const record = await (await fetch('https://next.mdxui.dev/pages/harbor/contact.json')).json();
const result = PageSchema.safeParse(record);
if (!result.success) for (const issue of result.error.issues) console.log(issue.path.join('.'), issue.message);Each issue names the path and the bound; Refusals gives the fix for each.