Functionaliteit
Editor
Section titled “Editor”De editor is een fullscreen canvas (EditorLayout) zonder sidebar navigatie. Blocks worden verticaal gestapeld en inline bewerkt.
UI Layout
Section titled “UI Layout”┌──────────────────────────────────────────────────────┐│ Toolbar: [← Terug] [Titel] [Undo/Redo] [Publiceren] │├────────────────────┬─────────────────────────────────┤│ │ ││ Block Picker │ Canvas ││ (sidebar, │ (blocks verticaal) ││ toggle) │ ││ │ ┌─────────────────┐ ││ ─── OF ─── │ │ Geselecteerd │ ││ │ │ block (inline │ ││ Block Settings │ │ editing) │ ││ (sidebar, │ └─────────────────┘ ││ per block) │ ││ │ │├────────────────────┴─────────────────────────────────┤│ Status bar: [Block count] [Last saved] [Draft/Pub] │└──────────────────────────────────────────────────────┘De sidebar wisselt tussen twee modi:
- Block picker — lijst van beschikbare block types om toe te voegen
- Block settings — configuratie van het geselecteerde block (props, achtergrond, spacing)
Inline Editing
Section titled “Inline Editing”Tekst en content worden direct op de canvas bewerkt:
| Component | Gebruik | Interactie |
|---|---|---|
EditableText | Titels, subtitels, FAQ vragen | Single-click = inline edit, Enter = blur (single-line) of <br> (multiline) |
RichText (Tiptap) | Hero/text content, FAQ antwoorden | Hover = ring, 120ms = editor mount, bubble menu bij selectie, expand naar modal |
EditableButtonList | Buttons in alle blocks | Klik = ButtonEditModal, block-level style+kleur via Design tab |
Gedrag bij verlaten van een veld:
- Klik buiten op een ander block → veld blurt, block wordt NIET geselecteerd (eerste klik = alleen exit)
- Selectie-ring verdwijnt wanneer een inline editor gefocust is
- RichText stript lege paragrafen aan begin/eind bij blur
Brand Story (Verhaal tab)
Section titled “Brand Story (Verhaal tab)”De Merk pagina bevat een “Verhaal” tab waar gebruikers merkgegevens invullen die de AI versterken. Data wordt opgeslagen in brand_profiles.onboarding_data als JSONB (BrandStory interface).
5 card-secties:
- Over je bedrijf — Naam, slogan, beschrijving, branche, opgericht
- Doelgroep & positionering — Doelgroep, B2B/B2C, regio, differentiator, primaire + secundaire CTA
- Missie & waarden — Missie, visie, kernwaarden (tag-input, max 6)
- Tone of voice — Aanspreekvorm (je/u/jullie), 3 sliders (formeel, serieus, technisch), tone beschrijving, verboden woorden (tag-input, max 10)
- Contactgegevens — Email, telefoon, adres
Volledig veldoverzicht: zie Data Architectuur — brand_profiles.
AI Content Generatie (Proof of Concept)
Section titled “AI Content Generatie (Proof of Concept)”De editor toolbar bevat een AI-knop (sparkle icoon) die een modal opent voor het genereren van hero content. Beschikbaar in zowel de page editor als de pattern editor.
Twee modi:
- Hero varianten (
POST /ai/generate-hero) — genereert 3 varianten van titel + subtitel. Via AI Test knop in de editor toolbar. - Per-block generatie (
POST /ai/generate-block) — genereert content voor elk individueel block. Via ✨ knop in de block hover-toolbar.
Per-block generatie (primaire feature):
- ✨ Sparkle knop verschijnt bij hover over elk block in de editor
- Popover met tekstveld: beschrijf wat je wilt → Enter om te genereren
- Smart merge: AI wijzigt alleen content (teksten, labels, items). Styling (kleuren, achtergrond, spacing, button styles) blijft behouden
- Verfijnen vs vervangen: AI bepaalt automatisch of het de bestaande content aanpast (“maak de titel korter”) of volledig vervangt (“maak hier een FAQ over verzendkosten”)
- Block context: AI kent de layout-instellingen (kolombreedte, achtergrond type, aantal items) en past de tekst lengte hierop aan
- Bestaande content: Huidige teksten worden meegestuurd zodat de AI kan verfijnen in plaats van vervangen
Technisch:
- Model: Configureerbaar via
AI_MODELenv var (default: Claude Sonnet) - Context: Volledige brand story + mood preset + block instellingen + bestaande content
- Output: Anthropic
tool_usevoor gegarandeerd JSON + Zod output validatie per block type - Security: Prompt injection preventie, IDOR check, 25s timeout, rate limit 10 req/min
- Enrichment: Buttons krijgen automatisch id, color, colorToken. Features/FAQ items krijgen id.
Volledige technische beschrijving: zie AI Architectuur.
De volledige AI pagina-generatie is beschreven in AI Content Generatie.
Block Types
Section titled “Block Types”11 block types beschikbaar. Volledige schema’s en props in Block Types.
| Type | Icoon | Doel |
|---|---|---|
hero | layout-template | Header sectie met titel, subtitel, buttons |
features | grid-3x3 | Grid van features (1-3 kolommen) |
testimonials-grid | layout-grid | Grid van klantbeoordelingen (2 of 3 kol.) |
featured-testimonial | quote | Uitgelichte enkele testimonial |
testimonials-carousel | gallery-horizontal | Horizontale Embla carousel met testimonials |
cta | megaphone | Call-to-action sectie |
text | type | Rich text content (HTML) |
faq | help-circle | FAQ accordeon |
group | layers-2 | Container/wrapper voor geneste blocks |
columns | layout-grid | 2-koloms layout |
buttons | square | Button groep |
Block Selection & Manipulatie
Section titled “Block Selection & Manipulatie”- Klik op een block om te selecteren — opent block settings sidebar
- Multi-select via Ctrl/Cmd+klik — voor bulk operaties
- Drag & drop via @dnd-kit — herordenen binnen de pagina
- Dupliceren — kopieert block met nieuwe ID
- Verwijderen — met bevestiging als block children bevat
Rich Text Editing (Tiptap)
Section titled “Rich Text Editing (Tiptap)”Het hero block gebruikt een Tiptap WYSIWYG-editor (gebouwd op ProseMirror) voor titel en subtitel in plaats van plain text contentEditable. Andere blocks (CTA, Features, FAQ) gebruiken nog EditableText.
Bubble Menu — Zwevende toolbar bij tekst selectie op het canvas:
- Inline formatting: vet, cursief, onderstrepen, doorhalen, link
- Block type: paragraaf, H1, H2, H3, H4
- Text styles: Lead tekst, Accent, Klein (CSS class-based)
- Expand knop: opent de tekst in een uitklapbare modal voor gedetailleerd bewerken
Expand Modal — Uitklapbare editor via sidebar-knop of bubble menu:
- Single editor instance — dezelfde Tiptap editor verplaatst tussen canvas en modal (geen synchronisatie nodig)
- FixedToolbar in modal — statische toolbar boven editor (geen bubble menu in modal)
- ModalHeader met titel “Tekst bewerken” + sluitknop
- Deferred store writes — bewerkingen in modal worden pas naar store geschreven bij sluiten
- Static HTML tijdens animaties — canvas en modal tonen HTML snapshot terwijl open/close animaties spelen;
EditorContentmount/unmount buiten animatieframes - Frozen height — canvas behoudt hoogte wanneer editor naar modal verplaatst
Tekst Kleur Auto-detectie:
textColorMode: 'auto'berekent lichte of donkere tekst op basis van achtergrond- Kleuren:
isLightColor()analyse op hex kleur of gradient stops - Afbeelding/video: default naar lichte tekst; alleen donkere tekst bij lichte overlay met >30% opacity
- Brand color tokens: resolven naar werkelijke kleurwaarde voor nauwkeurige detectie
Architectuur:
- Tiptap history uitgeschakeld — Zustand store history (undo/redo) is de single source of truth
- rAF-debounced store updates bij typen (deferred via
requestAnimationFrame) - Echo prevention — per-editor write timestamps (
Map) voorkomen dat editors hun eigen store-updates teruglezen - state.page bail-out — Zustand subscription skipt pad-traversal als
state.pagereferentie ongewijzigd - Zustand selectors — individuele action selectors voorkomen onnodige re-renders
- Lazy-loaded via
React.lazy()→ apartvendor-editorVite chunk (~135KB gzipped) - Link bewerken via
LinkEditModal(zelfde UI pattern alsButtonEditModal) - Backwards compatibel: plain text wordt automatisch in
<p>tags gewrapped vianormalizeToHtml() - Publieke site rendert HTML direct via
set:html(geen sanitize op Cloudflare Workers — content is pre-sanitized in dashboard)
Undo/Redo
Section titled “Undo/Redo”- Max 50 snapshots in de history stack
- Debounce: 500ms window. Prop-wijzigingen (tekst typen, kleur kiezen, spacing aanpassen) worden samengevoegd tot 1 history entry
- Directe snapshot: Structurele wijzigingen (block toevoegen, verwijderen, verplaatsen, pattern detach) slaan onmiddellijk op — geen debounce
- Keyboard shortcuts: Ctrl/Cmd+Z (undo), Ctrl/Cmd+Shift+Z (redo)
- Bij bereiken van het limiet (50): oudste snapshots worden verwijderd
Autosave
Section titled “Autosave”Pagina’s worden niet automatisch opgeslagen. De gebruiker klikt expliciet op “Opslaan” (Ctrl/Cmd+S).
Dirty state detectie: Vergelijking tussen page (huidige state) en originalPage (snapshot bij laden). De “Opslaan” button is alleen actief bij wijzigingen.
Save flow:
Gebruiker klikt "Opslaan" → cleanBlocksForSave() stript inactieve background velden → PUT /pages/:id (Supabase RLS check) → Bij succes: originalPage = huidige page (dirty state reset) → Fire-and-forget cache purge → Toast: "Pagina opgeslagen"Achtergrond Systeem
Section titled “Achtergrond Systeem”Elk block kan een achtergrond hebben. Volledige TypeScript schema in Block Types — BackgroundConfig.
| Type | Beschrijving |
|---|---|
| Kleur | Enkele kleur (hex). Default: wit |
| Gradient | Lineair of radiaal. Meerdere stops met kleur + positie |
| Afbeelding | Uit media library. Focal point picker, overlay opacity |
| Video | Achtergrond video. Thumbnail + blur placeholder |
De kleur wordt altijd bewaard als fallback, ook bij gradient/image/video. textColorMode: 'auto' berekent automatisch lichte of donkere tekst op basis van de achtergrond (zie Rich Text Editing — Tekst Kleur Auto-detectie).
Color Picker: De achtergrond-tab bevat een volledige color picker met:
- Kleur / Gradient tabs — segmented control om te wisselen tussen solid kleur en gradient mode
- Saturation/hue picker — visuele kleurkiezer met drag-pointers (motion.div spring-animatie)
- Gradient stop editor — horizontale balk met draggable stops (2-5 stops, lineair of radiaal)
- Lineair/Radiaal toggle — gradient type met angle-input (lineair) of 9-positie selector (radiaal)
- Brand kleuren — merkkleuren als presets (solid mode: achtergrondkleur, gradient mode: actieve stop-kleur)
- Brand presets — merkgradients als volledige gradient presets (alleen in gradient mode)
- Active state — actieve brand kleur/preset krijgt een visuele ring-indicator (
border-selection) - Opacity/alpha slider alleen beschikbaar in gradient mode, niet bij solid kleuren
- Gradient defaults gebruiken brand primary + secondary kleuren (geen hardcoded waarden)
- ColorPicker is lazy-loaded (
React.lazy) — pas geladen bij openen van de achtergrond-tab
Brand color tokens: Achtergronden en buttons kunnen gekoppeld worden aan merkkleur tokens (primary, secondary, accent). De kleur resolves naar var(--brand-{token}) — bij wijziging van het kleurenschema updaten alle gekoppelde elementen automatisch mee.
Button Kleur Systeem
Section titled “Button Kleur Systeem”Buttons gebruiken colorToken in plaats van hardcoded hex kleuren. Dit koppelt buttons aan het brand kleurensysteem.
| Token type | Waarden | Gedrag |
|---|---|---|
| Basis | light, dark | Vaste lichte/donkere kleur |
| Auto | auto | Past aan op achtergrondkleur van het parent block |
| Brand | primary, secondary, accent | Brand kleur token via var(--brand-{token}) |
| Shades | primary-100, accent-700, etc. | Shade varianten van brand kleuren |
Migratie: Bestaande buttons met de oude hardcoded paarse kleur zijn via database migratie (058-059) gebackfilled naar colorToken: 'primary'. Het color veld (hex) is deprecated maar blijft als fallback.
Security: sanitizeColorToken() valideert input tegen een whitelist van toegestane tokens. CSS injection via kwaadaardige color waarden is hiermee geblokkeerd. Zie Data Architectuur — ButtonItem voor het schema.
Pattern Invoegen
Section titled “Pattern Invoegen”Patterns kunnen als container in een pagina worden ingevoegd:
Block picker → "Patterns" tab → Selecteer pattern → Group block aangemaakt met pattern blocks als children → _pattern_id, _pattern_name, _is_synced metadata → Bij synced (`is_synced: true` in patterns tabel): "Update all uses" propagatie beschikbaar → Detach: verbreekt koppeling, blocks blijvenAanmaken & Bewerken
Section titled “Aanmaken & Bewerken”- Nieuw:
/editor/new— lege pagina met default titel en gegenereerde slug - Bewerken:
/editor/:id— laadt bestaande pagina in editor - Lijst:
/pages— overzicht met titel, slug, status, block count, datum
Slug Management
Section titled “Slug Management”- Formaat:
^[a-z0-9]([a-z0-9-]{1,61}[a-z0-9])?$(max 63 tekens) - Reserved slugs: app, admin, www, api, staging, dashboard, login, register, etc.
- Validatie: Client-side (direct feedback) + API-side (dubbele check)
- Slug wijziging: Triggert cascade-hrefs — alle interne links op andere pagina’s worden automatisch bijgewerkt
Publicatie
Section titled “Publicatie”| Status | Zichtbaarheid | RLS |
|---|---|---|
draft | Alleen teamleden in dashboard | Team members (authenticated) |
published | Publiek via Astro site | Iedereen (geen auth nodig) |
Publiceren = status wijzigen naar published + cache purge. Depubliceren = terug naar draft.
| Veld | Beschrijving | Fallback |
|---|---|---|
meta_title | Paginatitel voor zoekmachines | title |
meta_description | Beschrijving in zoekresultaten | — |
og_image | Social media preview | Site-level og_image_url |
no_index | Verberg voor zoekmachines | block_search_engines (site-level) |
hide_header | Verberg header navigatie | false |
hide_footer | Verberg footer navigatie | false |
Media Library
Section titled “Media Library”Upload
Section titled “Upload”Bestand selecteren → Client berekent SHA-256 hash → Check duplicaat (GET /media/check-duplicate) → Duplicaat? → Hergebruik bestaand item (toast melding) → Nieuw? → Upload naar R2 → Blur placeholder genereren (20px LQIP) → Thumbnail genereren (400px WebP) → DB record aanmaken → Toast: "Bestand geüpload"Limieten: 10 MB per bestand (images/docs), 100 MB video’s. 500 MB totaal per site. Zie Bedrijfslogica — Quota’s.
Stock Foto’s
Section titled “Stock Foto’s”Ingebouwde zoekfunctie voor Unsplash en Pexels:
Media library → "Stock" tab → Zoekterm invoeren → Provider kiezen (Unsplash / Pexels) → 20 resultaten per pagina → Selecteer foto → Opgeslagen als externe media → Fotograaf attributie bewaardZie Unsplash & Pexels integratie voor API details.
Externe Media
Section titled “Externe Media”URL invoeren → SSRF check → HEAD probe (type, grootte) → DB record. Externe media wordt niet gekopieerd naar R2 — de originele URL wordt gebruikt.
Tags & Organisatie
Section titled “Tags & Organisatie”- Tags per site, case-insensitive (LOWER comparison)
- Bulk operaties: meerdere media items selecteren → tag toewijzen/verwijderen
- Filteren en zoeken op tags in media library
Reference Counting
Section titled “Reference Counting”count_media_references(media_id) telt hoeveel pagina’s en patterns een media item gebruiken. Dit wordt getoond in de media detail view en gebruikt als waarschuwing bij verwijdering.
Navigatie
Section titled “Navigatie”Menu Builder
Section titled “Menu Builder”- Twee menu types: header en footer (selecteerbaar in site settings)
- Menu’s zijn site-scoped (
site_idkolom) — elke site heeft eigen menu’s - Hierarchische structuur (parent-child tree)
- Drag & drop herordenen via positie-veld
Menu Items
Section titled “Menu Items”| Veld | Type | Beschrijving |
|---|---|---|
label | text | Weergavenaam in menu |
page_id | UUID | Interne link → pagina slug |
url | text | Externe URL (als geen page_id) |
parent_id | UUID | Parent item (voor submenu’s) |
position | integer | Volgorde |
Bij interne links wordt de URL automatisch afgeleid van de pagina slug.
Header Configuratie
Section titled “Header Configuratie”De header pagina (/menus/header) combineert drie configuratiesecties:
Navigatie type — twee layouts:
| Type | Layout |
|---|---|
logo-menu-button | Logo (links) — Menu (midden) — CTA Button (rechts) |
menu-logo-menu | Menu 1 (links) — Logo (midden) — Menu 2 (rechts) |
Menu & Button configuratie:
logo-menu-button: menu selectie + CTA button (tekst, URL, stijl, kleur viaButtonEditModal)menu-logo-menu: linker menu + rechter menu selectie
Header Design — visuele configuratie met live preview:
- Achtergrond: brand kleuren, blur effect, transparant bij hero
- Border & schaduw: aan/uit, kleur, subtiel/medium
- Positie: sticky/static/fixed, hoogte (compact/default/tall), verberg bij scrollen
- Typografie: menu items, logo tekst, CTA button (font-size, weight, letter-spacing)
- Logo selectie: kies uit logo varianten geupload bij Brand → Elementen
Live preview — sticky browser mockup naast de opties:
- Toont header + homepage blocks (above-the-fold)
- Reageert direct op wijzigingen (geen opslaan nodig)
- Klik om te vergroten naar full-width (Motion
layoutIdmorph) - Scroll gedrag zichtbaar: hide-on-scroll, transparant bij hero
Multi-logo (Brand → Elementen)
Section titled “Multi-logo (Brand → Elementen)”Logo’s worden beheerd op de Brand pagina onder het Elementen tab:
- Meerdere logo varianten: Primary, Wit, Donker, Icoon, of custom
- Opgeslagen als
logosJSONB array opbrand_profiles - In de header configuratie selecteer je welk logo wordt getoond (
selectedLogoId) - Backwards compat: eerste logo =
logo_url(legacy veld)
Team & Invites
Section titled “Team & Invites”Site-scoped Teams
Section titled “Site-scoped Teams”Team management is site-scoped: elk team is gekoppeld aan een specifieke site, niet aan een owner. Een gebruiker kan editor zijn op site A en viewer op site B. De team_members tabel gebruikt site_id als primaire scope — owner_id is verwijderd.
Bij het aanmaken van een nieuwe site voegt de add_owner_to_site_team() trigger de eigenaar automatisch toe als team member met role owner.
Ledenbeheer
Section titled “Ledenbeheer”- Overzicht:
/settings/users— lijst van teamleden met naam, email, rol, datum - Rol wijzigen: Owner/admin kan rollen aanpassen (dropdown)
- Verwijderen: Owner/admin kan leden verwijderen (met bevestiging)
- Verlaten: Non-owners kunnen zelf het team verlaten
Uitnodigingen
Section titled “Uitnodigingen”- Uitnodigen: Voornaam, achternaam, email, rol selecteren
- Validatie: Geen self-invite, geen duplicaat, alleen owner/admin
- Email: HTML template via Resend met magic link
- Status tracking: pending → accepted / declined / revoked / expired
- Resend: Uitnodiging opnieuw versturen als deze verlopen of niet ontvangen is
Rechtenmatrix
Section titled “Rechtenmatrix”Zie Bedrijfslogica — Rollen & Rechten voor de volledige matrix.
Merk & Stijl
Section titled “Merk & Stijl”Configureerbaar via /brand — de Styling Builder voor de visuele identiteit van een site.
| Tab | Beschrijving |
|---|---|
| Presets | 6 sfeer-presets als startpunt (Warm & Aards, Bold & Expressief, etc.) |
| Kleuren | 7 kleuren: primair, secundair, accent, neutraal, achtergrond + tekst donker/licht. Preset paletten + vrije kleurkiezer met inline WCAG contrast badge per kleur |
| Typografie | 12 font-combinaties + fijnafstelling: heading dikte/letterafstand/regelhoogte, body dikte/regelhoogte, typeschaal (compact/standaard/dramatisch) |
| Elementen | Hoekafronding (5 opties), schaduw (4 opties) |
| Export | CSS custom properties, W3C Design Tokens JSON, Tailwind v4 @theme — kopieer naar klembord of open in browser |
Live preview: Split layout met rechts een voorbeeldkaart die direct reageert op wijzigingen. Toont heading, body, buttons, card, links en kleurenpalet.
Design token features:
- 7 brand kleuren — Primary, secondary, accent, neutral, surface + textDark/textLight. Neutral en surface worden gebruikt voor semantische tokens (borders, muted text, surface backgrounds)
- WCAG contrast badges — Client-side contrast checking per kleur via
checkWcagContrast(). Badge toont ratio + pass/fail status, met suggestie voor accessible alternatieven - Semantic tokens — Automatisch afgeleide tokens (surface, border, on-primary, danger/success/warning/info) als CSS variabelen
- OKLCH shade scale — 10-staps kleurschaal (50-900) per brand kleur gegenereerd via OKLCH kleurruimte
- Dark mode — Automatische dark mode CSS via
@media (prefers-color-scheme: dark)met OKLCH-berekende overrides - Typography fijnafstelling — Heading weight (100-900), letter-spacing (-0.05em tot 0.05em), line-height (0.8-1.5). Body weight (300-700), line-height (1.2-2.0). Type scale selector (compact/standaard/dramatisch)
- Token versioning — Automatische snapshots bij elke wijziging + handmatige named snapshots met restore via versiegeschiedenis modal
- Export — 3 formaten: CSS Custom Properties, W3C Design Tokens JSON, Tailwind v4
@theme - Accessibility — WAI-ARIA tabs pattern, aria-labels op alle controls, live regions voor status updates, keyboard navigatie
Data: brand_profiles tabel (1 per site) met design_tokens JSONB en mood_preset referentie. token_versions tabel voor versiegeschiedenis (max 50 auto-snapshots).
Multi-site Support
Section titled “Multi-site Support”Gebruikers kunnen meerdere sites aanmaken en beheren (max 10 per owner).
Site Switcher
Section titled “Site Switcher”In het user dropdown menu staat een site switcher met favicon en sitenaam. Bij wisselen worden alle dashboard data (pages, menus, settings, domains) herladen voor de geselecteerde site.
Site Aanmaken
Section titled “Site Aanmaken”Via de “Nieuwe site” knop in de site switcher:
- Naam invoeren — slug wordt automatisch gegenereerd (lowercase, spaties → hyphens)
- Bootstrap maakt automatisch een
site_settingsenbrand_profilerecord aan - Quota check: max 10 actieve sites per owner (
check_site_quota()trigger)
Site Verwijderen
Section titled “Site Verwijderen”Soft delete met 14 dagen hersteltijd:
- Owner klikt “Verwijder site” in settings → bevestiging via modal
DELETE /sites/:idzetdeleted_attimestamp (soft delete)- Site verdwijnt uit de site switcher en dashboard
- Na 14 dagen:
hardDeleteExpiredSites()cron verwijdert definitief (R2 bestanden, CF custom domains, DB records)
Site Settings
Section titled “Site Settings”Settings zijn opgedeeld in 4 subpagina’s, elk met een eigen route en focus:
Mijn site (/settings)
Section titled “Mijn site (/settings)”| Instelling | Beschrijving |
|---|---|
| Site naam | Bewerkbare naam van de site, getoond in site switcher |
| Homepage | Welke pagina wordt getoond op het root-domein |
| Favicon | Browser tab icoon (upload via media library) |
| Apple Touch Icon | iOS home screen icoon |
| OG Image | Default social media preview voor alle pagina’s |
| Site taal | Content taal via <html lang=""> (default: nl) |
| Zoekengine blokkering | Zet noindex op alle pagina’s |
| Gevarenzone | Site verwijderen (soft delete met 14 dagen hersteltijd) |
SEO (/settings/seo)
Section titled “SEO (/settings/seo)”| Instelling | Beschrijving |
|---|---|
| Site naam | Weergavenaam in meta tags |
| Site titel | Titel in browser tab |
| Site beschrijving | Meta description (site-level fallback) |
| Social preview | OG image en social media instellingen (read-only, instelbaar bij Mijn site) |
Domeinnamen (/settings/domains)
Section titled “Domeinnamen (/settings/domains)”| Instelling | Beschrijving |
|---|---|
| Subdomein | {slug}.builtwithbeam.com — automatisch beschikbaar |
| Custom domains | Eigen domein koppelen via CF Pages Custom Domains API |
Gebruikers (/settings/users)
Section titled “Gebruikers (/settings/users)”| Instelling | Beschrijving |
|---|---|
| Teamleden | Overzicht met naam, email, rol, datum |
| Uitnodigingen | Nieuwe leden uitnodigen per email |
| Rollenbeheer | Owner/admin kan rollen wijzigen |
Publieke Site
Section titled “Publieke Site”Rendering
Section titled “Rendering”Astro 5.8 SSR op Cloudflare Pages. Elke pagina wordt server-side gerenderd bij elk bezoek (met edge caching).
Request flow:
Bezoeker → Cloudflare CDN (edge cache check) → Cache hit? → Serveer direct (< 50ms) → Cache miss? → CF Pages Worker → Host-based routing (custom domain → site lookup via LRU cache) → [...slug].astro (catch-all route) → Promise.all([getSiteData(), getPageBySlug()]) → Astro SSR → HTML response → Cache: s-maxage=300, stale-while-revalidate=600Performance
Section titled “Performance”| Feature | Implementatie |
|---|---|
| ~4 KB JavaScript | Astro islands — geen client-side framework |
| Inline CSS | ~18 KB (5.5 KB gzip) — geen render-blocking stylesheet |
| 103 Early Hints | Font + LCP hero image preloading |
| Speculation Rules | Prefetch on hover (eagerness: 'moderate') |
| View Transitions | Smooth navigatie via CSS API |
| LQIP blur-up | Base64 blur → real image cross-fade |
| Above-fold detectie | fetchpriority="high", eager loading, sync decoding |
| Responsive images | srcSet met 8 breedtes via CF Image Resizing |
- Meta tags (title, description, canonical URL)
- Open Graph tags (og:title, og:description, og:image)
- JSON-LD structured data
- Robots meta tag (per pagina of site-level)
- Sitemap (automatisch gegenereerd)
Security
Section titled “Security”Alle user-generated HTML content wordt gesanitized via isomorphic-dompurify (@beam/shared/sanitize). Zie Technische Stack — Security voor CSP headers en verdere hardening.