Semantic frontend compiler · Playbook
Semantic blueprint schema
The blueprint is reviewed project data. It intentionally contains semantic content rather than raw captured HTML or arbitrary class names.
{
"schemaVersion": 3,
"approval": {
"status": "approved",
"scope": "release",
"productionEligible": true,
"reviewedBy": "Migration reviewer",
"reviewedAt": "2026-08-29T00:00:00Z",
"sourceDigest": "64-character SHA-256 digest of the frozen extraction",
"sourceEvidence": "builder-inventory.json"
},
"site": {
"name": "Example Practice",
"lang": "en",
"canonicalBase": "https://www.example.com"
},
"tokens": {
"color": "#18332d",
"accent": "#a46f38",
"paper": "#ffffff",
"ink": "#171a18",
"maxWidth": 1180
},
"navigation": [
{ "label": "Home", "href": "/" },
{
"label": "Services",
"href": "/services/",
"children": [{ "label": "Service one", "href": "/services/one/" }]
}
],
"footer": {
"groups": [
{
"heading": "Practice",
"links": [{ "label": "Contact", "href": "/contact/" }]
}
],
"legal": "Example Practice"
},
"features": {
"mobileActions": [
{ "label": "Contact", "href": "tel:+12025550100" },
{ "label": "Book", "href": "/contact/" },
{ "label": "Find us", "href": "https://maps.example.com/" }
],
"consent": {
"message": "Choose whether optional map content may load.",
"acceptLabel": "Accept",
"rejectLabel": "Reject",
"privacyHref": "/privacy/"
},
"accessibility": { "label": "Display preferences" },
"search": { "label": "Search", "placeholder": "Search services" }
},
"assets": [
{ "source": "approved/hero.webp", "output": "assets/media/hero.webp" }
],
"redirects": [
{ "from": "/old-contact/", "to": "/contact/", "status": 301 },
{ "from": "/collections/*", "to": "https://shop.example.com/collections/:splat", "status": 302 }
],
"routes": [
{
"path": "/",
"template": "landing",
"title": "Example Practice",
"description": "A specific description of the page.",
"h1": "A clear page heading",
"intro": "Optional introductory copy.",
"hero": {
"variant": "immersive",
"image": "/assets/media/hero.webp",
"tone": "dark",
"align": "left",
"objectPosition": "50% 40%"
},
"sections": [
{
"type": "prose",
"heading": "About",
"paragraphs": ["Approved paragraph text."]
},
{
"type": "image",
"src": "/assets/media/hero.webp",
"alt": "Descriptive alternative text",
"width": 1600,
"height": 1000,
"srcset": [
{ "src": "/assets/media/hero-480.webp", "width": 480 },
{ "src": "/assets/media/hero.webp", "width": 1600 }
],
"sizes": "(max-width: 760px) 100vw, 50vw",
"priority": true
},
{
"type": "cta",
"heading": "Ready to talk?",
"body": "Contact the practice for details.",
"label": "Contact the practice",
"href": "/contact/"
},
{
"type": "form",
"heading": "Request a consultation",
"endpoint": "/api/submit",
"submitLabel": "Send request",
"successMessage": "Your request was received.",
"fields": [
{ "name": "name", "label": "Full name", "type": "text", "required": true },
{ "name": "email", "label": "Email", "type": "email", "required": true },
{ "name": "message", "label": "How can we help?", "type": "textarea" }
]
}
]
}
]
}
Section types
prose: optionalheading, requiredparagraphs[].list: optionalheading, requireditems[], optionalordered.image:src,alt,width,height, optional responsivesrcset[](src+width),sizes,priority, andcaption; usedecorative: trueonly when the image conveys no information.priorityemits eager loading and high fetch priority and should be limited to the route’s likely LCP image. Gallery items support the same responsive fields.cards: optionalheading,items[]withtitle,body, optional pairedhref+label, and optional reviewedimagereferencing an asset-manifest output path.gallery: optionalheading, imageitems[]; compiles to owned accessible lightbox controls.faq: optionalheading,items[]withquestionandanswer; compiles to native details.video: optionalheading, requiredsrcandtitle, optionalposter; compiles to native video, never an empty overlay anchor.cta: requiredheading,body,label, andhref.form: requiredheading,endpoint,submitLabel,successMessage, andfields[]. Supported field types aretext,email,tel,date,number,select,radio,textarea,checkbox, andfile; selects and radio groups need explicit options. File fields may declareacceptandmultiple. A field can declareshowWhen: { "field": "otherName", "equals": "value" }for first-party conditional behavior, and the form can declareajax: truefor an accessible inline status. The compiler emits owned semantic markup, while Klinklang owns the Worker endpoint, private R2 upload handling, protection, notification and delivery proof.embed: requiredheading,src, andtitle; optionalconsentCategorydelays the iframe until the user accepts optional content.reviews: optionalheadingand 0–5rating; requireditems[]withquote,author, and optionalsource. Only reviewed, real review data belongs here.quote: requiredquoteandattribution.
Schema v2 global features
mobileActions: zero to three labeled safe links rendered as a mobile-only app-style action bar.consent: reviewed message, accept/reject labels, and optional privacy-policy link. It gatesembedsections that declareconsentCategory.accessibility: a label for first-party text-size and contrast preferences. This supplements, never replaces, direct WCAG conformance.search: a label and optional placeholder. The compiler emits a small route metadata index and an owned search dialog with no CMS endpoint.
Schema v3 presentation
site.brandmay declare the approved image logo using the same requiredsrc,alt,width, andheightfields as other images. Use the real reviewed asset; text substitution is not a presentation-preserving fallback.- A route may declare
hero.variantasimmersive,editorial, orsplit, plus a reviewed asset output path inhero.image. hero.toneislightordark;hero.alignisleft,center, orright; andhero.objectPositionaccepts a safe CSS object-position value.hero.headingPresentationisvisibleby default orvisually-hiddenwhen the approved source keeps its required H1 out of the visual hero. The H1 remains in semantic HTML either way.- Hero and card images are references to entries already declared in
assets[]. The compiler does not infer a hero from builder DOM or allow arbitrary classes/styles. - Presentation is review data, not production approval. A technical-staging blueprint remains non-indexable and non-production even when its presentation review passes.
- Navigation links are styled contextually without forced underlines; content links retain a clear affordance and every interactive element retains a visible keyboard focus indicator.
Schemas 1 and 2 remain accepted for existing blueprints; features requires schema 2+ and reviewed
hero/card presentation requires schema 3.
Asset source paths resolve below --asset-root; output paths must remain below assets/. The
compiler copies bytes without transforming them. Run Shrinkita and the Klinklang media manifest/R2
lane before selecting approved derivatives for the blueprint.
Every route needs at least one reviewed semantic section. A generated scaffold remains deliberately
invalid while approval.status is draft; changing it to approved also requires the reviewer,
UTC timestamp, frozen-source digest, and the evidence record used for review. Schema v2 additionally
requires approval.scope. A technical-staging blueprint must set productionEligible: false and
reference technicalReviewEvidence; Gurdurr adds noindex,follow to every emitted route. A release
blueprint may be production eligible but still remains subject to the migration skill’s content,
clinical, legal and deployment gates. The emitted manifest binds the exact blueprint bytes, source
digest, approval scope and production eligibility to the separate candidate.
The error document uses "path": "/404/" plus "notFound": true. It compiles to root 404.html
with noindex,follow, no canonical, and no sitemap entry.