Formele beslissingen met context, overwegingen en gevolgen. Volledige documenten in docs/beslissingen/.
| # | Beslissing | Status | Detail |
|---|
| ADR-001 | Vercel naar Cloudflare | Besloten | Lees meer |
| ADR-002 | Next.js naar Vite SPA | Besloten | Lees meer |
| ADR-003 | Server Actions naar Hono API | Besloten | Lees meer |
| ADR-004 | CF for SaaS naar CF Pages Custom Domains | Besloten | Lees meer |
| ADR-005 | ESLint 10 Flat Config | Besloten | Lees meer |
| ADR-006 | Layered Context Architecture | Besloten | Lees meer |
| ADR-008 | KV Cache voor Publieke Site (ISR) | Besloten | Lees meer |
| ADR-009 | Embla Carousel als standaard carousel-engine | Besloten | Lees meer |
| # | Vraag | Nodig voor | Impact |
|---|
| OQ-1 | Onboarding app: aparte Vite app of route binnen dashboard? | Vision Fase 1 | Architectuur + deploy |
| OQ-2 | Supabase: gedeeld of apart project voor onboarding? | Vision Fase 1 | Database + auth |
| OQ-3 | AI model: Claude (voorkeur) of configureerbaar? | Vision Fase 3 | API kosten + vendor lock |
| OQ-4 | Style Packs: hardcoded seed data of admin-interface? | Vision Fase 4 | Data management |
| OQ-5 | Addon public site rendering: middleware of file-based routing? | Vision Fase 4 | Astro architectuur |
| OQ-6 | Stockfoto’s in Asset Packs: API bij activatie of vooraf R2 cache? | Vision Fase 7 | Storage kosten |
| OQ-7 | Achievements: beam_events tabel of CF Queue? | Vision Fase 5 | Infra keuze |
| OQ-8 | Directory screenshots: Puppeteer of CF Browser Rendering API? | Vision Fase 6 | Vendor + kosten |
| OQ-9 | Pricing: per addon, per vertical pack, of flat-rate per tier? | Voor launch | Business model |
| OQ-10 | GDPR: welke data is exporteerbaar/verwijderbaar? | Voor launch | Juridisch |
| # | Item | Status | Detail |
|---|
| 1 | Error monitoring (Sentry) | Voltooid | |
| 2 | E2E tests (Playwright) | Voltooid | |
| 3 | Staging environment | Open | |
| 4 | Pages PUT mass assignment fix | Open | Zod schema toevoegen aan apps/api/src/routes/pages.ts — blokkeert overschrijven van user_id, site_id, created_at. Zie [Security Audit #3] |
| 5 | Unbounded queries — .limit() toevoegen | Open | getPages(), getMenus(), getMenusWithCounts(), updateLinkedButtonHrefs(), patterns usage endpoint. Max 500 rijen |
| # | Item | Status / Aanpak |
|---|
| 6 | Database backup verificatie | Maandelijkse restore-test naar staging |
| 7 | Database backup documentatie | Open — Documenteer Supabase backup config, PITR status, R2 lifecycle rules in docs/ |
| 7b | Disaster recovery procedures | Open — Documenteer RTO/RPO, recovery stappen, rollback procedures |
| 8 | Analytics (Plausible/PostHog) | Privacy-first events: page views, editor sessions, media uploads |
| 9 | Rate limiting | Voltooid |
| 10 | Structured logging | Voltooid |
| 11 | Blur placeholders | Voltooid |
| 12 | Env var fail-fast validatie | Open — Voeg check toe in apps/dashboard/src/lib/supabase.ts voor ontbrekende VITE_* vars |
| 13 | Session expiry redirect | Open — Handle SIGNED_OUT event in auth-context.tsx met redirect naar /login |
| 14 | FOUT (Flash of Unstyled Text) | Open — Font preload werkt niet op subdomein-sites. Check <link rel="preload"> in public site [...slug].astro |
| # | Item | Aanpak |
|---|
| 15 | Brand Export tab | Design tokens exporteren als CSS custom properties, Tailwind v4 theme, en W3C Design Tokens JSON |
| 16 | Page version history | page_versions tabel, max 10 per pagina, restore UI |
| 17 | Collaborative editing lock | Supabase Realtime presence: “X bewerkt deze pagina” |
| 18 | Billing (Stripe) | Plan tiers, quota enforcement, webhooks |
| 19 | GDPR compliance | Data export, account deletion cascade, privacy policy, cookie consent |
| 20 | API documentatie | @hono/zod-openapi of handmatige OpenAPI YAML |
| 21 | Site restore (undo soft-delete) | UI voor het herstellen van verwijderde sites binnen 14-dagen grace period |
| 22 | getSession() → getUser() migratie | Project-breed: vervang getSession() door getUser() in security-kritieke flows (6+ bestanden). RLS vangt het server-side op, maar client-side is niet geverifieerd |
| 23 | Patterns tab met presets | Patterns-tab in de block picker/editor uitbreiden met preset-varianten per block type (bv. Reviews Grid / Featured / Carousel, Pricing 3-tier / 2-tier highlight, Hero center / left / split). Presets hergebruiken de BlockPickerEntry.preset infrastructuur uit blocks.ts en tonen thumbnail + beschrijving per variant. Eén block-type, meerdere start-configuraties. Later uitbreidbaar met categorieën (Marketing / Social proof / Media / Conversion) |
Roadmap voor het opschalen van Beam naar 500+ sites. Elke fase wordt getriggerd door groei, niet door planning.
| Fase | Trigger | Upgrade | Effort | Impact |
|---|
| S1 | Nu (< 50 sites) | KV voor site config + ISR pattern — CF KV als edge cache voor site config, brand tokens en gerenderde page data. Elimineert DB calls voor public site reads | 2-3 dagen | TTFB ~100ms → ~1-5ms, DB load -95% |
| S2 | ~50 sites | Billing (Stripe) — Plan tiers, quota enforcement via Stripe webhooks, metered billing | 2-3 weken | Revenue, quota enforcement |
| S3 | ~100 sites | CF KV site-level cache tags — Purge per site i.p.v. globaal. Fijnmazige invalidatie | 1-2 dagen | Snellere purge, minder cache misses |
| S4 | ~200 sites | Durable Objects voor quota + rate limiting — Gedeelde state tussen Workers isolates. Exacte counters per site/user voor storage, pages, team size | 1-2 weken | Exacte billing metering, geen race conditions |
| S5 | ~200 sites | Neon Postgres migratie — Serverless Postgres met HTTP driver, read replica voor public site, database branching voor staging | 2-3 weken | Connection pooling, read replica latency, gratis staging |
| S6 | ~300 sites | PartyKit realtime — Edge-native realtime (vervangt Supabase Realtime). Per-page rooms, presence, block-level locking | 2-3 weken | Collaborative editing, edge latency |
| S7 | ~500 sites | CF Queues voor async taken — Media processing, bulk export, email campagnes, webhook delivery. Dead letter queue + retry | 1-2 weken | Lagere API response times, betere reliability |
| S8 | ~500 sites | Image pre-generation pipeline — Upload → Queue → genereer 8 srcSet variants (AVIF + WebP) → R2. Geen on-the-fly resize meer | 1-2 weken | Lagere CF Image Resizing kosten, snellere delivery |
Geschatte infra-kosten bij 500 sites: ~€210/mo (CF Workers $25, R2 $4, KV $5, DO $10, Queues $5, Neon $69, Supabase Auth $25, PartyKit $20, Resend $20, Sentry $26)
Principe: Upgrade pas wanneer de groei het rechtvaardigt. De huidige stack draagt 100+ sites zonder wijzigingen.
| # | Item |
|---|
| 22b | Proactieve monitoring/alerting |
| 23 | Multi-language dashboard (i18n) |
| 24 | Analytics dashboard (bezoekerstatistieken per klant-site) |
| 25 | React Native mobile app |
| 26 | sessionStorage als auth storage adapter (i.p.v. localStorage, veiliger bij XSS) |
| 27 | Background color upgrade — mesh/grain optie |
| 28 | Visual regression tests voor blocks — Playwright screenshots op key block × variant combinaties (cardStyle × quoteMark × background type). Automatisch vergeleken in CI. |
| 29 | Import van Trustpilot/Google reviews — automatisch testimonials importeren via externe review-API. Mapping naar TestimonialItem schema in API Worker. |
| 30 | compactLabelField override voor repeater compact-labels — betere UX voor review-repeaters: toon auteursnaam als compact-label i.p.v. generiek “Item 1”. |
| 31 | Testimonials-block — brand-token voor rating-kleur — review-card.css hardcodet #f59e0b voor sterren. Vervangen door var(--brand-accent, #f59e0b) zodra een dedicated brand-accent token bestaat of per user-preference instelbaar is. |
| 32 | Testimonials-block — dark mode card styling — .review-card--card.review-card--dark gebruikt #ffffff. Support voor prefers-color-scheme: dark toevoegen zodra dark-mode-first sites in scope komen. |
| 33 | Testimonials-block — defaultTestimonial() helper hergebruiken — apps/dashboard/src/lib/blocks.ts bevat bijna-duplicate inline defaults voor featured-testimonial en testimonials-grid. Consolideren naar één helper zodat nieuwe defaults één plek hebben. |
| 34 | Testimonials-block — escape verbetering title-escape tools — escapeHtml() in packages/shared/src/testimonials/classes.ts inlinen in een algemene shared-helper als meer Astro-blocks dynamische heading tags krijgen. |
| 35 | Testimonials-block — BlockRegistry interface drift — apps/dashboard/src/lib/types.ts BlockRegistry mist benoemde keys voor testimonials-grid, featured-testimonial, testimonials-carousel, faq, columns. Index-signature vangt het, maar benoemde keys geven IDE-hints. |
| 36 | Testimonials-block — E2E pageIds array opruimen — e2e/blocks-testimonials.spec.ts heeft een pageIds accumulator die niet gebruikt wordt in de cleanup. Verwijderen of koppelen aan ID-based delete. |
| 37 | Testimonials-block — quote-mark font-family — .review-quote-mark--classic gebruikt Georgia, serif. Overwegen om brand-font te gebruiken zodra een typography-token voor display-type bestaat. |
| 38 | Testimonials-block — Embla resize-transition — Grid-carousel herinit nu correct bij mobile→desktop. Bij desktop→mobile opnieuw wordt de observer opnieuw ge-armed maar dit kan strakker: één centrale media-query-watcher per block zodat we niet steeds IO opzetten. Nu acceptabel. |