SAMENVATTING

We hebben in 18 maanden ruim 30 headless-projecten geïmplementeerd bij Social Animal. Ongeveer een derde van onze recente inname is reddingswerk van designer-geleide builds die demo's hebben opgeleverd maar in productie kapot gingen. Michael Nervegna's gids "Claude Code for Designers" op Substack is echt goed voor prototyping -- maar het stopt voor Row Level Security, auth token refresh, database abstraction choices, deploy rollback, Content Security Policy en admin authentication. Dit artikel behandelt deze hiaten. Als je naar productie gaat, heb je ze nodig.

Inhoudsopgave

Wat Is Claude Code en Waarom Gebruiken Designers Het?

Claude Code is het terminal-gebaseerde coderingstool van Anthropic dat begin 2025 is gestart. Het wordt uitgevoerd als @anthropic-ai/claude-code en vereist Claude Pro ($20/maand) of Team ($30/seat/maand) met API-toegang. Je schrijft, bewerkt en debugt code via natuurlijke taal in je terminal.

Designers gebruiken het omdat het de kloof dicht tussen "ik heb dit in Figma ontworpen" en "dit is een werkende Next.js-app". In tegenstelling tot v0 of Bolt werkt Claude Code op je werkelijke bestandssysteem. Het leest je projectstructuur, wijzigt bestanden, voert je dev-server uit en herhaalt op basis van foutuitvoer. Voor iemand die componenthiërarchie begrijpt maar niet alle TypeScript generics uit het hoofd wil leren, is dat echt nuttig.

Nervegna positioneert het als een tool waarmee designers "in systemen" kunnen denken in plaats van syntaxis. We zijn het ermee eens. Waar we afwijken is wat er gebeurt nadat de eerste npm run dev succesvol is.

Wat Doet de Gids van Nervegna Goed?

Nervegna doet drie dingen goed die de meeste AI-coderingstutorials missen.

Ten eerste: projectcontext. Hij raadt aan om Claude Code een CLAUDE.md-bestand te geven met je projectconventies, tech stack en design tokens. We hebben gezien dat Claude Code Tailwind-utilities tegen een project genereerde dat CSS Modules gebruikte omdat niemand het de conventies had verteld. Voordat je code schrijft, context vaststellen is de juiste aanpak.

Ten tweede: de iteratieve lus. Prompt, output beoordelen, koers corrigeren, herhalen. Hij behandelt Claude Code niet als een "beschrijf en verzend" knop. Hij behandelt het als een paringpartner die toezicht nodig heeft. Dat is het juiste mentale model.

Ten derde: klein beginnen. Bouw één component of pagina voordat je volledige applicatie scaffolding probeert. We hebben designers gezien die "bouw me een volledige SaaS dashboard met auth, facturering en admin" in één bericht promptten. Het resultaat is altijd een puinhoop. De incrementele aanpak van Nervegna vermijdt dit.

Waar de gids van Nervegna designers goed van dienst is, is de 0-naar-prototype fase. Het probleem is dat prototypes productiecode worden, en dat is waar de hiaten ertoe doen.

Waar Valt de Gids Te Kort?

De stuk van Nervegna levert voor de prototyping fase. Het behandelt geen zorgen die urgent worden als je een echte database, echte gebruikers en echte deployment-infrastructuur aansluit.

Wat ontbreekt:

  1. Row Level Security (RLS) -- Supabase-projecten gegenereerd door Claude Code hebben bijna nooit juiste RLS-beleid
  2. Auth handoff -- de kloof tussen Supabase Auth in ontwikkeling en productieflows met token refresh, sessionbeheer en redirect handling
  3. Database abstraction decisions -- wanneer je rechtstreeks de Supabase-client gebruikt versus Prisma of Drizzle ORM
  4. Deploy rollback strategie -- wat er gebeurt wanneer een Claude Code commit productie kapot maakt
  5. Content Security Policy -- vooral voor Next.js Image met proxied/externe assets
  6. Admin authentication -- wanneer je rol-gebaseerde toegang nodig hebt buiten simpele user auth

Laten we elk punt behandelen.

Row Level Security Gotcha's Die Claude Niet Zal Opvangen

Row Level Security is Supabase's mechanisme om ervoor te zorgen dat databasequery's alleen rijen retourneren die de aanvragende gebruiker mag zien. Wanneer je een tabel in Supabase maakt, is RLS standaard uitgeschakeld. Elke geverifieerde gebruiker -- of in sommige configuraties, elk anoniem verzoek -- kan elke rij lezen.

Wanneer Claude Code een Supabase-project scaffoldt, maakt het tabellen en schrijft het client-side queries. Het voegt soms RLS-beleid toe als je erom vraagt. Maar het gegenereerde beleid is vaak op subtiele manieren verkeerd.

Veelvoorkomende RLS-fouten in AI-gegenereerde code

Fout Wat Gebeurt Hoe Op Te Lossen
Helemaal geen RLS ingeschakeld Elke geverifieerde gebruiker leest alle gegevens ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
Beleid gebruikt auth.uid() maar tabel heeft geen user_id kolom Beleid compileert maar komt overeen met nul rijen, blokkeert alle toegang Voeg user_id UUID REFERENCES auth.users(id) toe en vul het in
SELECT-beleid bestaat maar geen INSERT/UPDATE/DELETE-beleid Gebruikers kunnen lezen maar niet hun eigen gegevens schrijven Maak aparte beleidregels voor elke bewerking
Beleid gebruikt auth.role() = 'authenticated' alleen Elke ingelogde gebruiker kan alle rijen zien, niet alleen de hunne Voeg voorwaarde auth.uid() = user_id toe
Service role key gebruikt in client-side code RLS wordt volledig omzeild Stel nooit SUPABASE_SERVICE_ROLE_KEY bloot in client bundles

We hebben die laatste -- service role key in client code -- dit jaar in drie aparte door designers gemaakte projecten gezien. Claude Code zal soms de service role key gebruiken omdat het "werkt" en geen permissiefouten gooit. Die key omzeilt alle RLS. Het hoort in server-side code (API routes, server actions, edge functions). Nooit in een use client component.

Nervegna behandelt RLS niet in zijn gids, wat begrijpelijk is. Maar als je zijn workflow volgt en met Supabase verbindt, controleer elke tabel handmatig. Voer dit in de Supabase SQL-editor in:

SELECT schemaname, tablename, rowsecurity
FROM pg_tables
WHERE schemaname = 'public';

Als rowsecurity voor enige tabel met gebruikersgegevens false is, stop en repareer het voor implementatie.

Auth Handoff: De Kloof Tussen Prototype en Productie

Auth is het meest voorkomende foutpunt in door designers gemaakte builds. Niet omdat de initiële setup verkeerd is -- Supabase Auth is gemakkelijk te scaffolden -- maar omdat productie-auth edge cases betreft die niet bovenkomen tijdens lokale ontwikkeling.

De gids van Nervegna concentreert zich op het lokaal aan het werk krijgen. Dit breekt af wanneer je implementeert:

Token Refresh-fouten

Supabase Auth-tokens verlopen standaard na 3600 seconden (1 uur). De Supabase-client handelt refresh automatisch af -- in theorie. In de praktijk, als je Next.js middleware of server components op elk verzoek een nieuwe Supabase-client aanmaken zonder de bestaande sessie door te geven, krijg je intermitterende 401-fouten na het eerste uur.

Met Next.js App Router heb je @supabase/ssr nodig (versie 0.5.x vanaf februari 2025) en juist cookie handling in middleware. Claude Code genereert vaak het oudere @supabase/auth-helpers-nextjs-pakket, wat verouderd is. Controleer je package.json.

Redirect URI-niet-overeenkomsten

OAuth-providers (Google, GitHub) vereisen exacte redirect URI's. Claude Code configureert deze voor localhost:3000. Wanneer je naar Vercel of Netlify implementeert, moet je je productie-URL en preview deployment URL's toevoegen aan zowel de OAuth-provider-console als Supabase's Auth-instellingen onder "Redirect URL's." Dit duurt 5 minuten maar blokkeert 100% van OAuth-logins als je het mist.

Het sessie-synchronisatieprobleem

In Next.js 14+ heb je server components, client components, middleware, API routes en server actions -- allemaal mogelijk behoefte aan de huidige gebruikerssessie. De Supabase-client moet in elke context anders worden aangemaakt. Claude Code maakt vaak één enkele createClient() utility en gebruikt het overal, wat hydration mismatch en verouderde sessies veroorzaakt.

Je hebt minimaal drie client creation functies nodig:

  • createBrowserClient() voor client components
  • createServerClient() voor server components en server actions
  • createMiddlewareClient() voor middleware

Dit is gedocumenteerd in Supabase's SSR-gids maar Claude Code genereert het niet consistent correct.

Supabase vs Prisma: Wat Zou Claude Code Voor Moeten Genereren?

Nervegna behandelt deze beslissing niet, en het maakt meer uit dan de meeste designers beseffen.

Supabase client (@supabase/supabase-js) query's de database via Supabase's PostgREST API. Het is handig, vereist geen schema definition bestanden en werkt rechtstreeks met RLS. Maar het geeft je geen type safety buiten wat Supabase genereert, en het koppelt je applicatie strak aan Supabase's infrastructuur.

Prisma ORM (momenteel v6.x) maakt rechtstreeks verbinding met PostgreSQL. Het geeft je een schema bestand (schema.prisma), gegenereerde TypeScript types, migraties en database-agnostische query's. Maar het respecteert RLS-beleid niet (het maakt verbinding als een geprivilegieerde gebruiker) en vereist een build stap om de client te genereren.

Drizzle ORM (v0.36.x) is een lichter alternatief met SQL-achtige syntaxis en betere edge runtime ondersteuning.

Beslissingsmatrix

Factor Supabase Client Prisma Drizzle
RLS ondersteuning Native Moet in app laag implementeren Moet in app laag implementeren
Type safety Gegenereerd via CLI Gegenereerd uit schema Schema-as-code
Edge runtime compatibel Ja Beperkt (Prisma Accelerate vereist) Ja
Leerproces voor designers Laag Gemiddeld Gemiddeld
Vendor lock-in Hoog (Supabase) Laag Laag
Claude Code generatie kwaliteit Goed Goed Inconsistent

Onze aanbeveling: als je een prototype bouwt of altijd op Supabase draait, gebruik de Supabase-client. Als je van Supabase af moet of strikte schema-driven development wilt, gebruik Drizzle. We zijn voor nieuwe projecten van Prisma overgestapt vanwege edge runtime beperkingen, hoewel Prisma Accelerate ($0 voor 60K queries/maand, daarna $49/maand) dit heeft verbeterd.

Vertel Claude Code je beslissing expliciet in je CLAUDE.md bestand. Als je het niet doet, zal het benaderingen mengen -- soms query via Supabase-client, soms via een ORM -- en je eindigt met twee verschillende data access patronen in hetzelfde project.

Deploy Rollback: Wat Gebeurt Er Als Je AI-Gegenereerde Code Kapot Gaat

De gids van Nervegna loopt door features stap voor stap te bouwen. Het behandelt niet wat er gebeurt wanneer een Claude Code sessie een commit genereert die lokale dev passeert maar in productie breekt.

Dit gebeurt vaker dan je verwacht. Claude Code kan 15 bestanden in één promptrespons wijzigen. Als je dat als één unit commit en implementeert, betekent rollback alle 15 wijzigingen terugdraaien -- zelfs als 13 prima waren.

Een Praktische Rollback-strategie

1. Commit na elke logische wijziging, niet na elke Claude Code sessie. Als Claude auth, UI en databaseschema in één sessie wijzigt, maak drie aparte commits.

2. Gebruik Vercel's instant rollback. Als je op Vercel implementeert, is elke implementatie immutable. Je kunt naar elke vorige implementatie in minder dan 10 seconden terugkeren vanuit het dashboard. Netlify biedt hetzelfde.

3. Voer nooit databasemigraties direct vanuit Claude Code uit. Als Claude een migratie bestand genereert, controleer het handmatig voor je npx supabase db push of npx prisma migrate deploy uitvoert. Een verwijderde kolom is niet iets wat je met een git revert ongedaan kunt maken.

4. Tag known-good staten. Voordat je een Claude Code sessie start die kritieke paden aanraakt (auth, betalingen, data modellen), maak een git tag: git tag pre-auth-refactor. Als het fout gaat, krijg je je terug met git reset --hard pre-auth-refactor.

5. Preview deployments zijn verplicht, niet optioneel. Vercel en Netlify maken beide preview deployments voor elke PR. Merge niet naar main zonder door de preview te klikken. Claude Code kan code genereren die lokaal werkt maar in productie faalt vanwege ontbrekende omgevingsvariabelen, edge runtime incompatibiliteiten of CSP-schendingen.

Content Security Policy Voor Proxied Assets

Dit is niche maar het bijt hard wanneer je een door designer gemaakte site implementeert.

Next.js's <Image> component proxiet externe afbeeldingen standaard via /_next/image. Dit is geweldig voor optimalisatie. Maar als je een Content Security Policy header hebt (en dat zou je moeten hebben), moet je expliciet de domeinen toestaan waaruit je afbeeldingen komen.

Claude Code zal next.config.js met remotePatterns instellen voor afbeeldingsoptimalisatie maar voegt geen CSP headers toe. Wanneer je achter Vercel's beveiligingsheaders implementeert of je eigen headers toevoegt via middleware, breken externe afbeeldingen stil -- ze laden lokaal (waar CSP vaak soepel is) maar falen in productie.

Dit is het minimum dat je in je middleware of next.config.js headers nodig hebt:

// middleware.ts
const cspHeader = `
  default-src 'self';
  script-src 'self' 'unsafe-eval' 'unsafe-inline';
  style-src 'self' 'unsafe-inline';
  img-src 'self' blob: data: https://your-supabase-project.supabase.co https://your-cdn.com;
  font-src 'self';
  connect-src 'self' https://your-supabase-project.supabase.co;
  frame-ancestors 'none';
`;

Vervang 'unsafe-eval' en 'unsafe-inline' met nonces voor production hardening. Het punt is: als Claude Code afbeeldingen van Unsplash, Supabase Storage of een externe CDN importeert, en je voegt die domeinen niet toe aan je CSP img-src directive, krijg je kapotte afbeeldingen in productie zonder console fouten in development.

Wanneer Heb Je Daadwerkelijk Admin Auth Nodig?

De gids van Nervegna behandelt basis user authentication. Veel door designer gemaakte projecten hebben een admin interface nodig -- een manier voor de site eigenaar of content team om gegevens te beheren zonder de database aan te raken.

De vraag is: wanneer heb je custom admin auth nodig als apart onderwerp versus gewoon Supabase's dashboard gebruiken?

Je HEBT GEEN Custom Admin Auth Nodig Wanneer:

  • Je bent de enige persoon die content beheert
  • Je client is comfortabel met Supabase's Table Editor
  • Het project heeft minder dan 3 content types
  • Updates gebeuren minder dan eenmaal per week

Je HEBT NODIG Custom Admin Auth Wanneer:

  • Niet-technische teamleden moeten content beheren
  • Je hebt approval workflows of draft/publish staten nodig
  • Het project heeft rol-gebaseerde toegang (editor vs. admin vs. viewer)
  • Je beheert user-generated content dat moderatie vereist

Als je admin auth nodig hebt, is de eenvoudigste aanpak een role kolom op je profiles tabel (wat auth.users weerspiegelt) met een enum: 'user' | 'editor' | 'admin'. Voeg vervolgens RLS-beleid toe dat deze rol controleert:

CREATE POLICY "Admins can do anything"
ON public.posts
FOR ALL
USING (
  EXISTS (
    SELECT 1 FROM public.profiles
    WHERE profiles.id = auth.uid()
    AND profiles.role = 'admin'
  )
);

Claude Code kan dit genereren als je het specifiek prompt. Zonder de prompt zal het standaard naar simpele auth.uid() = user_id beleid gaan dat geen admin-toegang in aanmerking neemt. Je eindigt met een admin die de content van andere gebruikers niet kan zien.

De workflow van Nervegna van vereisten definiëren in een CLAUDE.md bestand zou dit opvangen -- als je rol-gebaseerde toegang in je vereisten meeneemt. Voeg het aan het bestand toe voor je begint te bouwen.

Voor Je Naar Prod Gaat: De Checklist

Dit is wat we gebruiken bij Social Animal voor implementatie van projecten gebouwd of aanzienlijk bijgestaan door AI-coderingstools.

Database & Beveiliging

  • RLS is ingeschakeld op elke tabel in public schema
  • RLS-beleid bestaat voor SELECT, INSERT, UPDATE en DELETE op elke tabel
  • SUPABASE_SERVICE_ROLE_KEY wordt alleen gebruikt in server-side code (grep je codebase: grep -r "SERVICE_ROLE" --include="*.ts" --include="*.tsx")
  • Geen Supabase-client is aangemaakt met de service role key in bestand met 'use client'
  • Databasemigraties zijn handmatig beoordeeld
  • Foreign key constraints bestaan waar verwacht
  • Indexen bestaan op kolommen gebruikt in WHERE-componenten en RLS-beleid

Authentication

  • @supabase/ssr wordt gebruikt (niet verouderde @supabase/auth-helpers-nextjs)
  • Aparte client creation functies bestaan voor browser, server en middleware contexten
  • OAuth redirect URI's zijn geconfigureerd voor productiedomain EN preview deployment domeinen
  • Token refresh is getest (stel expiratie tijdelijk kort in en controleer sessies blijven bestaan)
  • Beveiligde routes leiden door naar login wanneer sessie afwezig is
  • Logout wist alle cookies en server-side sessie staat

Admin & Rollen

  • Als admin functies bestaan, gebeuren rol controles op RLS niveau (niet alleen UI-level verberging)
  • Admin routes zijn beveiligd door middleware, niet alleen voorwaardelijke rendering
  • Standaardrol voor nieuwe gebruikers is de minst geprivilegieerde rol

Implementatie & Rollback

  • Omgevingsvariabelen zijn ingesteld in implementatie platform
  • Een known-good git tag bestaat van voor de laatste grote AI-bijgestane wijzigingen
  • Preview deployment is getest door kern flows door te klikken
  • Vercel/Netlify instant rollback is begrepen en gedocumenteerd voor het team
  • Databaseback-ups zijn ingeschakeld (Supabase Pro plan bevat dagelijkse back-ups voor $25/maand)

Content Security & Assets

  • CSP headers bevatten alle externe afbeeldings domeinen in img-src
  • CSP headers bevatten Supabase project URL in connect-src
  • next.config.js remotePatterns overeenkomt met CSP img-src domeinen
  • Fonts zijn zelf-gehost of hun CDN staat in font-src
  • Geen gemengde content (HTTP resources op HTTPS pagina's)

Code Kwaliteit

  • TypeScript strict mode is ingeschakeld ("strict": true in tsconfig.json)
  • Geen @ts-ignore of any types die Claude Code toevoegde om fouten te onderdrukken
  • npm run build slaagt zonder waarschuwingen (niet alleen npm run dev)
  • Error boundaries bestaan voor client components die gegevens ophalen
  • Loading en error staten bestaan voor async operaties

Performance

  • Afbeeldingen gebruiken Next.js <Image> component met width en height of fill
  • Geen client-side data fetching voor gegevens die in server components opgehaald konden worden
  • Bundle grootte is gecontroleerd (npx next@latest build toont route grootte)
  • Lighthouse score is boven 90 voor Performance (voer uit op preview deployment, niet localhost)

Deze checklist is niet uitputtend. Het is het minimum voor een project dat Supabase, Next.js en AI-gegenereerde code aanraakt.

Veelgestelde Vragen

Is Claude Code goed genoeg voor designers om productie-apps te bouwen? Claude Code is uitstekend voor het genereren van werkende code uit design intent. Maar production readiness vereist beveiligings-, auth- en infrastructuurkennis die het tool niet unprompted biedt. Combineer het met een checklist en code review van iemand met backend ervaring.

Werkt de gids van Nervegna voor projecten buiten prototypes? De workflow van Nervegna -- context-first prompting, incrementeel bouwen, iteratieve review -- schaalt goed. De kloof zit in production zorgen zoals RLS, auth edge cases en deployment strategie. Zijn aanpak is gezond; het vereist aanvulling voor alles user-facing.

Moet ik Supabase of Prisma gebruiken met Claude Code? Gebruik Supabase's client library als je RLS enforcement op databaseniveau wilt en je bent toegewijd aan Supabase platform. Gebruik Drizzle ORM als je database portabiliteit en edge runtime compatibiliteit wilt. We zijn voor nieuwe projecten van Prisma afgestapt vanwege edge beperkingen.

Hoe voorkom ik dat Claude Code de Supabase service role key in client code gebruikt? Voeg een expliciete regel toe aan je CLAUDE.md bestand: "Gebruik nooit SUPABASE_SERVICE_ROLE_KEY in client components. Gebruik het alleen in server actions, API routes of middleware." Claude Code respecteert project-level instructies wanneer ze duidelijk zijn gesteld.

Wat is de goedkoopste manier om een Claude Code gegenereerde Next.js app te implementeren? Vercel's gratis Hobby plan ondersteunt één productie implementatie per project. Supabase's gratis tier bevat 2 projecten met 500MB database en 1GB file storage. Totale kosten: $0/maand voor laag-traffic sites. Verwacht naar Vercel Pro ($20/maand) en Supabase Pro ($25/maand) te gaan zodra je echte gebruikers hebt.

Hoe vaak genereert Claude Code code met beveiligingsproblemen? In onze ervaring produceert ongeveer 40% van Claude Code sessies met database operaties code met minstens één RLS gat. Het is niet kwaadaardig -- het tool optimaliseert voor "werkende" code, en RLS schendingen produceren geen fouten. Ze stellen gegevens gewoon stil bloot. Controleer altijd handmatig.