SaaS Boilerplate mit Claude Code: Vollständiger Stack in einem Tag 2026

Die meisten SaaS-Ideen scheitern nicht am Produkt — sondern am Setup-Aufwand: Authentication, Billing, Multi-Tenancy, Onboarding-Flow. Claude Code reduziert diese Boilerplate-Arbeit von Wochen auf einen Tag.

Der SaaS-Stack den Claude Code in einem Tag aufbaut

  • Next.js 15 App RouterServer Components, Server Actions, Streaming
  • AuthenticationNextAuth v5 / Better Auth — Google, GitHub, Magic Link
  • DatenbankPostgreSQL + Prisma ORM mit Migrations
  • BillingStripe Subscriptions, Webhooks, Customer Portal
  • EmailResend + React Email: Onboarding, Password Reset, Invoices
  • Multi-TenancyOrganization/Workspace-Modell mit Role-Based Access
  • DashboardAnalytics-Seite mit Usage-Tracking
  • DeploymentVercel (Frontend) + Supabase/Neon (DB) + Upstash (Redis)
Der 1-Tag-Plan: Morgens Auth + DB-Schema. Mittags Stripe Billing + Webhooks. Nachmittags Dashboard + Email. Abends Deployment + Go-Live. Claude Code macht jeden Block in 30-60 Minuten statt 2-3 Tagen.

Schritt 1: Datenbank-Schema mit Multi-Tenancy

Multi-TenancyOrganization-basiertes Datenmodell

# Prompt: "Erstelle ein Prisma-Schema für eine Multi-Tenant SaaS-App: # User kann mehreren Organizations gehören # Organizations haben Plans (free/pro/enterprise) # Row-Level-Security: User sieht nur eigene Org-Daten" # schema.prisma — Claude Code generiert: model User { id String @id @default(cuid()) email String @unique name String? createdAt DateTime @default(now()) memberships OrgMembership[] sessions Session[] } model Organization { id String @id @default(cuid()) name String slug String @unique // für URLs: /org/acme plan Plan @default(FREE) stripeId String? @unique trialEndsAt DateTime? members OrgMembership[] projects Project[] } model OrgMembership { id String @id @default(cuid()) role Role @default(MEMBER) // OWNER | ADMIN | MEMBER userId String orgId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade) @@unique([userId, orgId]) } enum Plan { FREE PRO ENTERPRISE } enum Role { OWNER ADMIN MEMBER }

Schritt 2: Stripe Subscription Billing

StripeSubscription + Webhook-Handler

# Checkout Session erstellen export async function createCheckoutSession(orgId, priceId) { const org = await db.organization.findUnique({ where: { id: orgId } }); // Stripe Customer anlegen oder laden let customerId = org.stripeId; if (!customerId) { const customer = await stripe.customers.create({ email: org.ownerEmail, metadata: { orgId } }); customerId = customer.id; await db.organization.update({ where: { id: orgId }, data: { stripeId: customerId } }); } const session = await stripe.checkout.sessions.create({ customer: customerId, mode: 'subscription', line_items: [{ price: priceId, quantity: 1 }], success_url: `${APP_URL}/dashboard?upgraded=true`, cancel_url: `${APP_URL}/pricing`, metadata: { orgId } }); return session.url; }
# Webhook-Handler: Plan aktualisieren export async function POST(req) { const body = await req.text(); const sig = req.headers.get('stripe-signature'); const event = stripe.webhooks.constructEvent( body, sig, process.env.STRIPE_WEBHOOK_SECRET ); switch (event.type) { case 'customer.subscription.updated': case 'customer.subscription.created': { const sub = event.data.object; const orgId = sub.metadata.orgId; const plan = getPlanFromPriceId(sub.items.data[0].price.id); await db.organization.update({ where: { id: orgId }, data: { plan, stripeSubscriptionId: sub.id } }); break; } case 'customer.subscription.deleted': { const orgId = event.data.object.metadata.orgId; await db.organization.update({ where: { id: orgId }, data: { plan: 'FREE' } }); } } return Response.json({ received: true }); }

Schritt 3: Feature Gates für Plan-Limits

Feature GatesPlan-Limits durchsetzen

# lib/features.ts const PLAN_LIMITS = { FREE: { projects: 3, teamMembers: 1, apiCalls: 100 }, PRO: { projects: 20, teamMembers: 10, apiCalls: 10000 }, ENTERPRISE: { projects: Infinity, teamMembers: Infinity, apiCalls: Infinity } }; export async function checkFeatureLimit(orgId, feature) { const org = await db.organization.findUnique({ where: { id: orgId }, include: { _count: { select: { projects: true, members: true } } } }); const limit = PLAN_LIMITS[org.plan][feature]; const current = org._count[feature]; if (current >= limit) { throw new Error(`Plan limit reached: ${feature} (${current}/${limit}). Upgrade to PRO.`); } } # In Server Action nutzen: export async function createProject(formData) { await checkFeatureLimit(session.orgId, 'projects'); // wirft wenn Limit erreicht await db.project.create({ ... }); }

Deployment-Checkliste

  • PostgreSQL-Verbindung mit Connection Pooling (Supabase/Neon)
  • Stripe Webhooks in Production registriert + getestet
  • Environment-Variablen in Vercel gesetzt (kein .env in Git!)
  • CRON: Trial-Reminder-Emails 3 Tage vor Ablauf
  • Error Monitoring: Sentry für kritische Pfade (Auth, Billing)
  • Rate Limiting auf /api Routen (Upstash Redis)
  • DSGVO: Privacy Policy, Imprint, Cookie-Consent
  • Stripe Customer Portal aktiviert (Self-Service Upgrades/Downgrades)
Trial-to-Paid Rate: Das wichtigste Metric. Claude Code hilft dir Onboarding-Flows zu optimieren — beschreibe wo User abspringen und lass dir A/B-Test-Varianten generieren.

SaaS Boilerplate im Kurs

Im Claude Code Mastery Kurs bauen wir live eine vollständige SaaS-App: Authentication, Stripe Billing, Multi-Tenancy, Dashboard, Email-Onboarding — von 0 bis zum ersten zahlenden Kunden. Mit allem was du brauchst um schnell zu shippen.

14 Tage kostenlos testen →