toolkit

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: optional heading, required paragraphs[].
  • list: optional heading, required items[], optional ordered.
  • image: src, alt, width, height, optional responsive srcset[] (src + width), sizes, priority, and caption; use decorative: true only when the image conveys no information. priority emits 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: optional heading, items[] with title, body, optional paired href + label, and optional reviewed image referencing an asset-manifest output path.
  • gallery: optional heading, image items[]; compiles to owned accessible lightbox controls.
  • faq: optional heading, items[] with question and answer; compiles to native details.
  • video: optional heading, required src and title, optional poster; compiles to native video, never an empty overlay anchor.
  • cta: required heading, body, label, and href.
  • form: required heading, endpoint, submitLabel, successMessage, and fields[]. Supported field types are text, email, tel, date, number, select, radio, textarea, checkbox, and file; selects and radio groups need explicit options. File fields may declare accept and multiple. A field can declare showWhen: { "field": "otherName", "equals": "value" } for first-party conditional behavior, and the form can declare ajax: true for 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: required heading, src, and title; optional consentCategory delays the iframe until the user accepts optional content.
  • reviews: optional heading and 0–5 rating; required items[] with quote, author, and optional source. Only reviewed, real review data belongs here.
  • quote: required quote and attribution.

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 gates embed sections that declare consentCategory.
  • 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.brand may declare the approved image logo using the same required src, alt, width, and height fields as other images. Use the real reviewed asset; text substitution is not a presentation-preserving fallback.
  • A route may declare hero.variant as immersive, editorial, or split, plus a reviewed asset output path in hero.image.
  • hero.tone is light or dark; hero.align is left, center, or right; and hero.objectPosition accepts a safe CSS object-position value.
  • hero.headingPresentation is visible by default or visually-hidden when 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.