Skip to content

AI Block Schema

Bronbestand: packages/shared/src/ai/block-schema.ts Gebruikt door: apps/api/src/routes/ai.ts (system prompt) + Zod output validatie

Het AI Block Schema beschrijft elk block type op een manier die de AI helpt om:

  1. Het juiste block te kiezen voor een pagina-onderdeel
  2. Content te genereren die past bij het block-formaat
  3. Paginastructuur te bepalen (welke blocks in welke volgorde)

De AI genereert alleen content — styling (spacing, background, corners, textColorMode) wordt automatisch toegepast via enrichBlocksWithDefaults().


7 block types zijn beschikbaar voor AI-generatie. group is uitgesloten — dat is een editor-container die niet door AI wordt aangemaakt.

BlockPositieMax/paginaPast bijTone
herofirst1features, text, columnsImpactvol, beknopt
featuresany2hero, ctaScanbaar, bullet-achtig
ctalast2hero, features, faqUrgent, actiegericht
textany3hero, columns, ctaVerhalend, informatief
faqany1cta, textBehulpzaam, helder
columnsany2hero, ctaMix tekst + visueel
buttonsany2text, columnsKort, actiegericht

De AI gebruikt deze patronen als richtlijn (niet als verplichting):

Pagina-typeStructuur
Dienstenhero → features → text → cta
Over onshero → columns → features → cta
Landinghero → features → faq → cta
Contacthero → columns → faq
Brandhero → text (missie) → text (visie) → features (waarden) → cta
Simpelhero → text → cta

Beschrijving: Header sectie met paginatitel, ondertitel en call-to-action buttons.

Wanneer gebruiken: Altijd als eerste block op een pagina. Bevat de hoofdboodschap en primaire CTA.

Wanneer NIET gebruiken: Niet als 2e/3e block. Niet voor tussentekst of secundaire secties.

MetadataWaarde
Positiefirst (altijd bovenaan)
Max per pagina1
Past bijfeatures, text, columns
AlternatiefVoor alleen tekst zonder buttons: gebruik text block

Content velden:

VeldTypeRichtlijnVerplicht
layoutcenter | leftTekstuitlijningdefault: center
title.textstring3-8 woorden, krachtig en duidelijkJa
title.tagh1Alleen h1 in herodefault: h1
title.sizexldefault: xl
subtitle.textstring1-2 zinnen, max 25 woordenJa
buttons.items[].labelstring2-4 woorden, actiegerichtJa
buttons.items[].hrefstringURL of #default: #
buttons.items[].stylesolid | outlineEerste button solid, tweede outlinedefault: solid

Voorbeeld output:

{
"type": "hero",
"props": {
"layout": "center",
"title": { "text": "Uw tuin, ons vakmanschap", "tag": "h1", "size": "xl" },
"subtitle": { "text": "Al 25 jaar creëren wij groene oases in de regio Utrecht." },
"buttons": { "items": [
{ "label": "Gratis adviesgesprek", "href": "#contact", "style": "solid" },
{ "label": "Bekijk projecten", "href": "#projecten", "style": "outline" }
]}
}
}

Verbeterpunten:

  • Afbeelding/video achtergrond: hero kan een background image/video hebben maar de AI genereert dit nog niet (vereist media library koppeling)
  • Brand CTA’s: als de BrandStory een primaryCta bevat, zou de AI die automatisch als eerste button label moeten gebruiken

Beschrijving: Grid van features, diensten of voordelen met iconen.

Wanneer gebruiken: Om meerdere gelijkwaardige items te tonen: diensten, voordelen, kenmerken, teamleden.

Wanneer NIET gebruiken: Niet voor lange tekst. Niet als er maar 1 item is — gebruik dan text block.

MetadataWaarde
Positieany
Max per pagina2
Past bijhero, cta
AlternatiefVoor gedetailleerde tekst per onderwerp: meerdere text blocks

Content velden:

VeldTypeRichtlijnVerplicht
columns2 | 3 | 4Aantal kolommendefault: 3
title.textstring2-6 woordenJa
subtitle.textstring1 zin, optioneelNee
features.items[].iconstringLucide icon naamdefault: star
features.items[].titlestring1-4 woordenJa
features.items[].descriptionstring1-2 zinnen, max 20 woordenJa

Beschikbare iconen: zap, shield, heart, star, clock, users, check, sparkles, leaf, pencil-ruler, phone, mail, map-pin, award, target, lightbulb (en alle andere Lucide iconen)

Voorbeeld output:

{
"type": "features",
"props": {
"columns": "3",
"title": { "text": "Wat wij voor u doen", "tag": "h2", "size": "lg" },
"subtitle": { "text": "Drie specialisaties, één doel." },
"features": { "items": [
{ "icon": "leaf", "title": "Tuinonderhoud", "description": "Seizoensgebonden onderhoud zodat uw tuin er het hele jaar verzorgd uitziet." },
{ "icon": "pencil-ruler", "title": "Tuinontwerp", "description": "Een doordacht ontwerp dat past bij uw woning en budget." },
{ "icon": "award", "title": "Aanleg", "description": "Van bestrating tot beplanting — uw droomtuin van A tot Z." }
]}
}
}

Verbeterpunten:

  • Icon matching: AI kiest nu uit een beperkte set iconen. Zou alle ~1500 Lucide iconen moeten kennen
  • Columns automatisch: AI zou columns moeten baseren op het aantal items (2 items → 2, 3 → 3, 4+ → 4)
  • Afbeeldingen per feature: features hebben nu alleen iconen, geen afbeeldingen (toekomstige block-uitbreiding)

Beschrijving: Call-to-action sectie die bezoekers aanzet tot actie.

Wanneer gebruiken: Als afsluiter van een pagina of sectie. Na informatie (features, text, faq) om de bezoeker te converteren.

Wanneer NIET gebruiken: Niet als openingsblock. Niet direct na een andere CTA.

MetadataWaarde
Positielast (afsluiter)
Max per pagina2
Past bijhero, features, faq
AlternatiefVoor alleen buttons: gebruik buttons block

Content velden:

VeldTypeRichtlijnVerplicht
layoutcenter | side-by-sidedefault: center
title.textstring4-10 woorden, vraag of uitnodigingJa
subtitle.textstring1 zin, verlaag de drempelJa
buttons.items[].labelstring2-4 woorden, actiegerichtJa

Verbeterpunten:

  • Brand CTA koppeling: primaryCta en secondaryCta uit BrandStory automatisch als button labels
  • Achtergrondkleur: CTA gebruikt nu de default button kleur als achtergrond, AI kan dit niet beïnvloeden

Beschrijving: Vrije tekst sectie met rich HTML content.

Wanneer gebruiken: Voor langere tekst: werkwijze, over ons, missie, toelichting, verhaal.

Wanneer NIET gebruiken: Niet voor opsommingen (gebruik features). Niet voor Q&A (gebruik faq).

MetadataWaarde
Positieany
Max per pagina3
Past bijhero, columns, cta
AlternatiefVoor tekst naast afbeelding: gebruik columns block

Content velden:

VeldTypeRichtlijnVerplicht
maxWidthprose | md | lg | fullTekstbreedtedefault: prose
alignmentleft | centerdefault: left
content.htmlHTML string<h2>, <h3>, <p>, <ul>, <li>, <strong>, <em>. Geen <h1>.Ja

Verbeterpunten:

  • HTML sanitization: AI-gegenereerde HTML wordt nog niet door DOMPurify gehaald voor insert
  • Heading hiërarchie: AI moet weten welke headings al op de pagina zijn (h1 in hero → h2 in text)

Beschrijving: Veelgestelde vragen in accordion-formaat.

Wanneer gebruiken: Om bezoekersvragen te beantwoorden en bezwaren weg te nemen.

Wanneer NIET gebruiken: Niet als er minder dan 3 vragen zijn.

MetadataWaarde
Positieany
Max per pagina1
Past bijcta, text
AlternatiefVoor een lijstje punten: gebruik features block

Content velden:

VeldTypeRichtlijnVerplicht
title.textstring2-5 woordenJa
items.items[].questionstringDirecte vraag vanuit klantperspectiefJa
items.items[].answerHTML string1-3 zinnen als <p>, concreetJa

Verbeterpunten:

  • Branche-specifieke vragen: AI zou typische vragen per branche moeten kennen (kapper → “Moet ik een afspraak maken?”)
  • SEO structured data: FAQ blocks zouden automatisch FAQPage schema.org markup moeten genereren

Beschrijving: Twee kolommen layout met tekst en/of afbeelding.

Wanneer gebruiken: Om tekst naast een afbeelding te tonen, of twee content-blokken naast elkaar.

Wanneer NIET gebruiken: Niet als beide kolommen alleen tekst bevatten.

MetadataWaarde
Positieany
Max per pagina2
Past bijhero, cta
AlternatiefVoor alleen tekst: text block. Voor 3+ items: features block

Content velden:

VeldTypeRichtlijnVerplicht
left.typetext | imageType linkerkolomdefault: text
left.text.htmlHTML stringMax 2-3 alinea’s met <h2> kopAls type=text
right.typetext | imageType rechterkolomdefault: image
right.image.altstringBeschrijvende alt-tekstAls type=image

Verbeterpunten:

  • Afbeelding selectie: AI kan nu geen afbeeldingen uit de media library koppelen — genereert lege url
  • Grid layout: AI kan de kolomverhoudingen niet beïnvloeden (default 50/50)
  • Meer dan 2 kolommen: huidige block ondersteunt alleen 2 kolommen

Beschrijving: Standalone buttons zonder omringende tekst.

Wanneer gebruiken: Voor navigatie-links midden op de pagina, los van hero of CTA.

Wanneer NIET gebruiken: Niet als de CTA al buttons heeft.

MetadataWaarde
Positieany
Max per pagina2
Past bijtext, columns
AlternatiefVoor tekst + buttons: gebruik cta block

Content velden:

VeldTypeRichtlijnVerplicht
alignmentleft | center | rightdefault: center
buttons.items[].labelstring2-4 woorden, actiegerichtJa

AI output wordt gevalideerd via een Zod discriminated union per block type:

import { aiBlockSchema, aiGeneratePageSchema } from '@beam/shared/ai'
// Valideer een enkel block
const result = aiBlockSchema.safeParse(block)
// Valideer een volledige pagina-response
const pageResult = aiGeneratePageSchema.safeParse(response)

Bij validatiefouten: 1x retry met foutmelding als feedback aan Claude. Na 2e fout: 502 naar client.


Na validatie voegt enrichBlocksWithDefaults() automatisch toe:

  • id (via crypto.randomUUID())
  • spacing (default: { top: 'medium', bottom: 'medium' })
  • background (default: { type: 'color', color: '#ffffff' })
  • corners (default: { top: false, bottom: false })
  • textColorMode (default: 'auto')
  • color + colorToken: 'primary' op buttons
  • Unieke id’s op geneste items (features, FAQ items, buttons)

  • Media library koppeling — AI kan nu geen afbeeldingen selecteren. Vereist: media items met AI-beschrijvingen, matching algoritme
  • Brand CTA automatischprimaryCta en secondaryCta uit BrandStory als default button labels
  • Full page generatie — Huidige PoC genereert alleen hero varianten. Block schema + Zod is klaar voor full page
  • Per-block regeneratie — ✨ knop per block in editor, hergebruikt zelfde AI service
  • Content kwaliteitscheck — Lorem ipsum detectie, cliché check, heading hiërarchie, lege strings
  • HTML sanitization — DOMPurify op AI-gegenereerde HTML voor text/faq blocks
  • Lucide icon set — Volledige icon-set beschikbaar maken voor features block
  • Columns grid layout — AI kolomverhoudingen laten bepalen
  • SEO structured data — FAQ → FAQPage schema.org, breadcrumbs
  • Conversatie modus — Chat-interface voor stapsgewijze pagina-opbouw