Skip to content

Supabase

Supabase is de primaire backend: authenticatie, PostgreSQL database, realtime subscriptions en object storage. Beam gebruikt drie Supabase clients met verschillende rechten.

ClientLocatieKeyRechten
DashboardBrowserAnon key + user JWTRLS enforced
API WorkerServerService role keyRLS bypass (admin)
Public SiteServerAnon keyRead-only
  • Flow: PKCE (Proof Key for Code Exchange) — geen implicit grant.
  • Token verificatie: Altijd via supabase.auth.getUser(), nooit getSession().
  • Magic links: Gebruikt voor team uitnodigingen. Supabase genereert de link, Resend verstuurt de email.
  • Email verificatie: Verplicht bij registratie.

PKCE voorkomt authorization code interception attacks. Bij implicit grant worden tokens via de URL fragment teruggestuurd, wat kwetsbaar is voor XSS. PKCE gebruikt een code verifier/challenge flow die server-side wordt gevalideerd.

  • Engine: PostgreSQL (Supabase-managed)
  • Migraties: 43+ Supabase migraties in supabase/migrations/
  • RLS: Row Level Security op alle tabellen — zie Data & Architectuur voor policies
  • Performance pattern: (SELECT auth.uid()) wordt door PostgreSQL gecached per statement, voorkomt herhaalde auth lookups

12 SQL helper functies voor team isolation, quota enforcement en data cleanup. Volledige lijst met beschrijvingen in Data & Architectuur — SQL Helper Functies.

Kernfuncties:

  • get_team_owner_id() — cached team owner lookup, kern van alle RLS policies
  • bootstrap_new_user() — auto-create team + site bij sign-up
  • check_media_quota() — enforce 500 MB limiet per site

Twee sync-mechanismen:

Instant sync tussen browser tabs van dezelfde gebruiker. Geen server roundtrip.

Tab A: delete media → broadcastMediaDeleted(id)
Tab B: useMediaRealtimeSync() ← luistert → markDeletedMedia(id)

Live sync tussen verschillende gebruikers via PostgreSQL postgres_changes events.

User A: save pattern → Supabase UPDATE event
User B: usePatternRealtimeSync() ← luistert → replacePatternBlocks()

Hooks:

  • useMediaRealtimeSync() — Luistert naar DELETE op media. Vervangt verwijderde achtergronden met witte kleur + _deleted_media flag. Deduplicatie via processedRef Set (10s cleanup).
  • usePatternRealtimeSync() — Luistert naar UPDATE op patterns. Vervangt pattern container children.
BucketZichtbaarheidDoelLimiet
avatarsPubliekProfielfoto’s
mediaPubliekLegacy (R2 is primair)10 MB
pattern-previewsPubliekPattern thumbnails
VariabeleWaarType
VITE_SUPABASE_URLDashboardBuild-time
VITE_SUPABASE_ANON_KEYDashboardBuild-time
SUPABASE_URLAPIVar
SUPABASE_ANON_KEYAPISecret
SUPABASE_SERVICE_ROLE_KEYAPISecret
PUBLIC_SUPABASE_URLPublic SiteBuild-time
PUBLIC_SUPABASE_ANON_KEYPublic SiteBuild-time
LimietWaarde
Database connectiesSupabase-managed (pooling)
Realtime concurrent connections200 (free tier)
Storage upload max10 MB per bestand
Auth rate limit30 signups/hour (Supabase default)
ProbleemOorzaakOplossing
”JWT expired” errorsToken niet ververstsupabase.auth.getUser() forceert refresh
RLS blokkeert queryMissende policy of verkeerde owner chainCheck get_team_owner_id() output
Realtime events missenChannel niet gesubscribed of quota bereiktCheck Supabase dashboard voor active connections
”duplicate key” op insertRace condition bij concurrent insertsGebruik ON CONFLICT of client-side dedup