/saas — Full-Stack SaaS Builder
Auslöser: /saas [idee] oder einfach /saas (fragt nach der Idee)
Ausgabe: Ein vollständig bereitgestelltes, produktionsreifes SaaS unter einer Vercel-URL. Funktionierende Authentifizierung, echtes Backend, Live-Daten, schöne UI. Keine Demo. Kein Gerüst. Ein echtes Produkt.
PIPELINE ÜBERSICHT
AUFNAHME → RECHERCHE (parallel) → PLAN → KLÄRUNG → BAU → TEST → ÜBERPRÜFUNG → AUSLIEFERUNG
Jede Phase steuert die nächste. Keine Abkürzungen. Kein Überspringen.
PHASE 1 — AUFNAHME
Wenn der Benutzer /saas [idee] ausgeführt hat, extrahiere die Idee aus dem Befehl.
Wenn er /saas ohne Argument ausgeführt hat, frage:
Was ist die SaaS-Idee? Beschreibe sie in 1-3 Sätzen. Füge hinzu:
- Was sie tut
- Für wen sie ist
- Welches Problem sie löst
Speichern als IDEA. Bestätige sie in einem Satz, bevor du fortfährst.
PHASE 2 — PARALLELE RECHERCHE
Starte zwei Recherche-Stränge gleichzeitig mit dem Agent-Tool. Warte NICHT, bis einer beendet ist, bevor du den anderen startest.
Strang A — Marktinformationen
Erzeuge einen general-purpose-Agenten mit folgender Anweisung:
Recherchiere den SaaS-Markt für diese Idee: [IDEA]
Liefere einen strukturierten Bericht, der Folgendes abdeckt:
1. BESTEHENDE ANBIETER (5-8 Wettbewerber)
- Name, URL, Preismodelle, Positionierung
- Was sie gut machen, was ihnen fehlt
- Geschätztes ARR, falls verfügbar
2. MARKTGRÖSSE & NACHFRAGE
- Kategorie (CRM, Projektmanagement, Analysen, usw.)
- Marktgrößenschätzung
- Wachstumstrend (wachsend/stabil/rückläufig)
- Nachweis der Nachfrage (Reddit-Threads, ProductHunt-Upvotes, Stellenanzeigen)
3. PREISBENCHMARKS
- Freemium vs. nur kostenpflichtig vs. Testversion
- Typische Preisgestaltung ($/Benutzer/Monat, Pauschal, nutzungsabhängig)
- Welche Modelle gewinnen in dieser Kategorie
4. FUNKTIONSTABELLE
- Liste die 10 häufigsten Funktionen aller Wettbewerber auf
- Markiere, welche davon Grundvoraussetzung vs. Unterscheidungsmerkmal sind
5. WEISSER RAUM
- Was machen Wettbewerber NICHT?
- Worüber beschweren sich Benutzer? (Prüfe G2, Capterra, Reddit)
- Was ist die Nischenchance?
Liefere strukturiertes Markdown. Sei spezifisch. Kein unnötiger Inhalt.
Strang B — Technische Muster-Recherche
Starte einen zweiten general-purpose-Agenten:
Recherchiere die technischen Implementierungsmuster für diese Art von SaaS: [IDEA]
Liefere:
1. DATENMODELL-MUSTER
- Welche Tabellen/Entitäten benötigt diese App normalerweise?
- Wichtige Beziehungen und Einschränkungen
- Multi-Tenancy-Ansatz (zeilenbasiert mit org_id vs. getrennte Schemas)
2. AUTH-MUSTER
- Benötigt diese App Social Login? Magic Link? SSO?
- Nur auf Einladung vs. offene Registrierung?
- Rollenmuster (Admin/Mitglied/Betrachter typisch?)
3. ABRECHNUNGSMUSTER
- Pro-Sitzplatz, nutzungsabhängig oder pauschal?
- Kostenlose Tarifstrategie, die in diesem Bereich funktioniert?
4. INTEGRATIONSBEDARF
- Womit integrieren sich Apps in dieser Kategorie typischerweise?
- Webhooks, Zapier, API-Schlüssel?
5. TECHNISCHE RISIKEN
- Was ist in dieser Kategorie schwer zu bauen?
- Was machen Teams falsch?
- Leistungs-/Skalierungsüberlegungen
Liefere strukturiertes Markdown. Sei spezifisch.
Warte darauf, dass BEIDE Stränge abgeschlossen sind, bevor du fortfährst.
PHASE 3 — ARCHITEKTURPLAN
Erstelle unter Verwendung beider Rechercheergebnisse einen strukturierten Bauplan. Schreibe dies nach .saas-workspace/[projekt-slug]/PLAN.md.
Der Plan muss Folgendes enthalten:
3.1 Produktdefinition
## Produkt
Name: [von der Idee abgeleitet, kann geändert werden]
Slogan: [eine Zeile]
Kernwertversprechen: [ein Satz]
Zielbenutzer: [spezifische Persona]
## MVP-Funktionsumfang (was wir HEUTE bauen)
- [Funktion 1] — [warum sie im Umfang ist]
- [Funktion 2] — [warum sie im Umfang ist]
...
## Nicht im Umfang (v1)
- [Funktion] — [verschoben auf v2, weil...]
3.2 Datenmodell
Entwerfe das vollständige Postgres-Schema. Für jede Tabelle:
- Tabellenname, Zweck
- Alle Spalten mit Typen, Einschränkungen, Standardwerten
- Fremdschlüsselbeziehungen
- Erforderliche RLS-Richtlinien
- Indizes
Beginne mit diesen erforderlichen Tabellen:
-- Immer einschließen:
profiles (erweitert auth.users)
organizations (falls Multi-Tenant)
organization_members (falls Multi-Tenant)
subscriptions (falls Abrechnung)
Füge dann domänenspezifische Tabellen für das Produkt hinzu.
3.3 Routenplan
Landingpage: /
Auth: /login /signup /auth/callback
App-Shell: /app (erfordert Authentifizierung)
Kernfunktionen: /app/[funktion] (eine pro MVP-Funktion)
Einstellungen: /app/settings
API-Routen: /api/... (jede auflisten)
3.4 Tech-Stack-Bestätigung
Framework: Next.js 15 (App Router, TypeScript)
Datenbank: Supabase (Postgres + Auth + RLS)
Styling: Tailwind CSS v4 + shadcn/ui
E-Mail: Resend (transaktional)
Bereitstellung: Vercel
Zahlungen: Stripe (falls Abrechnung benötigt)
3.5 Bau-Reihenfolge
Liste die genaue Reihenfolge auf: Migrationen → Auth → API-Routen → App-Shell → Funktionen → Landingpage → E-Mail-Vorlagen → Tests.
PHASE 4 — KLÄRUNGSFRAGEN
Bevor eine einzige Zeile Code geschrieben wird, identifiziere Lücken. Verwende AskUserQuestion, um Folgendes zu fragen (maximal 4 Fragen pro Aufruf gruppieren):
Runde 1 — Produktumfang:
- Bestätige den Namen (präsentiere 3 von der Idee abgeleitete Optionen)
- Multi-Tenant (Teams/Org.) oder Einzelbenutzerkonten?
- Benötigt v1 Zahlungen/Abrechnung oder ist es während des Aufbaus kostenlos?
- Gibt es spezifische Funktionen aus der Recherche, die Muss- oder Nice-to-have sind?
Runde 2 — Design & Bereitstellung (nur fragen, wenn Antworten aus Runde 1 neue Fragen aufwerfen):
- Domain? (oder vorerst Vercel-Subdomain verwenden)
- Markenfarben / Präferenzen? (Standard: Rawgrowth dunkelgrünes System)
- E-Mail-Absenderadresse für Resend?
Integriere die Antworten in die PLAN.md, bevor du fortfährst.
PHASE 5 — BAU
Vorbereitende Einrichtung vor dem Bau
Lade diese Skills, bevor du Code schreibst:
frontend-theme— injiziert das vollständige Rawgrowth-Designsystemui-ux-pro-max— Designentscheidungen, Palette, Typografie- Rufe Magic MCP auf (
@21st-dev/magic) für alle komplexen Komponenten
Projektstandort: Erstelle unter ~/saas-projects/[projekt-slug]/
Gerüstbefehl:
cd ~/saas-projects
npx create-next-app@latest [projekt-slug] \
--typescript \
--tailwind \
--eslint \
--app \
--src-dir \
--import-alias "@/*" \
--no-git
cd [projekt-slug]
Abhängigkeiten installieren:
npm install @supabase/supabase-js @supabase/ssr \
resend \
@radix-ui/react-icons \
lucide-react \
class-variance-authority clsx tailwind-merge \
zod \
@hookform/resolvers react-hook-form
# shadcn/ui initialisieren
npx shadcn@latest init --defaults
# shadcn-Komponenten hinzufügen
npx shadcn@latest add button input label card \
dropdown-menu avatar badge separator toast \
dialog sheet tabs form
Tailwind v4-Konfiguration — wende frontend-theme-Tokens auf src/app/globals.css an.
5.1 Datenbank & Migrationen
Verwende den Skill add-migration für jede Migration.
Migration 1: Kernschema
-- RLS für alle benutzerseitigen Tabellen aktivieren
-- profiles: erweitert auth.users
CREATE TABLE profiles (
id UUID REFERENCES auth.users(id) ON DELETE CASCADE PRIMARY KEY,
email TEXT NOT NULL,
full_name TEXT,
avatar_url TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Benutzer können ihr eigenes Profil anzeigen"
ON profiles FOR SELECT USING (auth.uid() = id);
CREATE POLICY "Benutzer können ihr eigenes Profil aktualisieren"
ON profiles FOR UPDATE USING (auth.uid() = id);
-- Profil bei Registrierung automatisch erstellen
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO public.profiles (id, email, full_name, avatar_url)
VALUES (
NEW.id,
NEW.email,
NEW.raw_user_meta_data->>'full_name',
NEW.raw_user_meta_data->>'avatar_url'
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
Migration 2: Organisationen (falls Multi-Tenant)
CREATE TABLE organizations (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name TEXT NOT NULL,
slug TEXT UNIQUE NOT NULL,
owner_id UUID REFERENCES profiles(id) ON DELETE CASCADE NOT NULL,
plan TEXT DEFAULT 'free',
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE organization_members (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
org_id UUID REFERENCES organizations(id) ON DELETE CASCADE NOT NULL,
user_id UUID REFERENCES profiles(id) ON DELETE CASCADE NOT NULL,
role TEXT NOT NULL DEFAULT 'member' CHECK (role IN ('owner', 'admin', 'member')),
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(org_id, user_id)
);
ALTER TABLE organizations ENABLE ROW LEVEL SECURITY;
ALTER TABLE organization_members ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Mitglieder können ihre Organisation anzeigen"
ON organizations FOR SELECT
USING (id IN (
SELECT org_id FROM organization_members WHERE user_id = auth.uid()
));
CREATE POLICY "Mitglieder können Organisationsmitgliedschaft anzeigen"
ON organization_members FOR SELECT
USING (org_id IN (
SELECT org_id FROM organization_members WHERE user_id = auth.uid()
));
Migration 3+: Domänentabellen — erstelle produktspezifische Tabellen gemäß dem Datenmodell in PLAN.md. Wende RLS auf jede Tabelle an.
5.2 Supabase-Client-Einrichtung
src/lib/supabase/client.ts:
import { createBrowserClient } from '@supabase/ssr'
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
}
src/lib/supabase/server.ts:
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'
export async function createClient() {
const cookieStore = await cookies()
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() { return cookieStore.getAll() },
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options)
)
} catch {}
},
},
}
)
}
src/middleware.ts — schütze alle /app/* Routen, leite nicht authentifizierte Benutzer zu /login um.
5.3 Auth-Seiten
Baue /login und /signup als vollständige Seiten (keine Modale). Wende frontend-theme an:
- Dunkler Hintergrund (#060B08)
- Zentrierte Karte mit Rand (rgba(255,255,255,0.06))
- Grüne CTA-Buttons (#0CBF6A)
- E-Mail + Passwort-Felder (+ Social Login, falls konfiguriert)
- "Passwort vergessen"-Link
- Keine Emojis. Sauber, hochwertig, minimalistisch.
src/app/(auth)/login/page.tsx — Login-Formular mit Supabase Auth
src/app/(auth)/signup/page.tsx — Registrierungsformular mit E-Mail-Bestätigungsablauf
src/app/auth/callback/route.ts — OAuth/Magic-Link-Callback-Handler
E-Mail-Bestätigungsablauf:
- Bei Registrierung → Supabase sendet Bestätigungs-E-Mail (über Resend SMTP)
- Callback-Route tauscht Code gegen Sitzung aus
- Bei Erfolg Weiterleitung zu
/app/dashboard
5.4 App-Shell
src/app/(app)/layout.tsx — authentifiziertes Layout mit:
- Seitenleiste (auf mobilen Geräten einklappbar)
- Obere Navigation mit Benutzer-Avatar + Dropdown (Profil, Einstellungen, Abmelden)
- Breadcrumbs
- Toast-Benachrichtigungsausgabe
Seitenleistenelemente abgeleitet vom Routenplan in PLAN.md.
Verwende Magic MCP, um eine Seitenleisten-Komponente abzurufen: suche nach "dashboard sidebar dark" und passe sie an frontend-theme-Tokens an.
5.5 Kernfunktionsseiten
Für jede Funktion im MVP-Funktionsumfang (aus PLAN.md):
- Zuerst designen — frage Magic MCP nach relevanten Komponentenmustern
- Datenebene — Server-Komponenten rufen direkt von Supabase ab
- Mutationen — Server-Aktionen mit Zod-Validierung
- Fehlerzustände — jedes Formular hat Validierungsfehler, Ladezustände, leere Zustände
- Keine
any-Typen — generiere TypeScript-Typen aus dem Supabase-Schema
Muster für datenabrufende Server-Komponente:
import { createClient } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'
export default async function DashboardPage() {
const supabase = await createClient()
const { data: { user } } = await supabase.auth.getUser()
if (!user) {
redirect('/login')
}
const { data: profile } = await supabase
.from('profiles')
.select('*')
.eq('id', user.id)
.single()
return (
<div>
<h1>Willkommen, {profile?.full_name || 'Benutzer'}</h1>
</div>
)
}