Product Plan Spezifikation
Version 0.1.0 — Februar 2026
Product Plan beschreibt, wie ein Produkt implementiert wird. Er ist die Implementierungsblaupause fuer product.lock.json.
Lock definiert WAS (was gebaut werden soll). Plan definiert WIE (wie es gebaut wird).
Plan ist fuer KI zum Lesen gedacht. Menschen koennen ihn ueberspringen, aber wenn etwas schiefgeht, koennen Menschen ihn verstehen.
Die vollstaendige Lock-Spezifikation findest du in der Product Lock Spezifikation.
Inhaltsverzeichnis
- Beziehung zwischen den Dateien
- Designprinzipien
- Format
- Erforderliche Abschnitte
- Optionale Abschnitte
- Konventionen
- Lock vs Plan
1. Beziehung zwischen den Dateien
product.lock.json → WAS das Produkt ist (Mensch genehmigt)
product.plan.md → WIE es gebaut wird (KI folgt)
codebase → Das eigentliche Produkt (KI-Reviewer verifiziert gegen Lock)
| Du hast | Du kannst |
|---|---|
| Nur Lock | KI baut Produkt, trifft eigene Implementierungsentscheidungen |
| Lock + Plan | KI baut exakt dasselbe Produkt mit derselben Architektur |
| Lock + Plan + Codebasis | KI-Reviewer verifiziert, dass alles uebereinstimmt |
| Nur Plan | KI kann bauen, hat aber keine Produktgrenze zur Verifizierung |
2. Designprinzipien
- Vom Lock abgeleitet — Plan MUSS alles implementieren, was das Lock definiert, ohne Auslassungen und ohne Konflikte
- Reproduzierbar — Verschiedene KI-Agenten, die denselben Plan lesen, SOLLTEN strukturell identische Codebasen erzeugen
- Klartext — Markdown-Format, nicht komprimiert, nicht kodiert, nicht verschluesselt
- Vollstaendig — Plan enthaelt alle Implementierungsentscheidungen, die das Lock nicht abdeckt; eine KI mit diesem Plan kann direkt Code schreiben
- Stack-spezifisch — Dasselbe Lock kann mehrere Plans haben (TypeScript-Version, Python-Version, Go-Version)
3. Format
Die Datei MUSS product.plan.md heissen und im Projektstammverzeichnis neben product.lock.json platziert werden.
# Product Plan: {name} v{version}
> Lock: product.lock.json
> Stack: {einzeilige Stack-Zusammenfassung}
> Generated: {date}
## Stack
| Layer | Choice |
|-------|--------|
| Language | TypeScript 5.x |
| Runtime | Node.js 20 |
| Framework | Next.js 15 (App Router) |
| Database | PostgreSQL 16 |
| ORM | Prisma 6 |
| Auth | Supabase Auth (magic link) |
| Validation | Zod |
| State | TanStack Query + Zustand |
| Styling | Tailwind CSS 4 + shadcn/ui |
| Deploy | Vercel |
## Schemas
{Vollstaendige Entitaetsschemata mit Typen, Einschraenkungen, Relationen.}
## Endpoints
{Jeden Feature-API-Vertrag.}
## Implementation Steps
{Geordnete Schritte zum Aufbau von Null.}
4. Erforderliche Abschnitte
Jeder Plan MUSS die folgenden Abschnitte enthalten.
4.1 Stack
Technologiewahl auf jeder Ebene des Produkts.
## Stack
| Layer | Choice |
|-------|--------|
| Language | TypeScript 5.x |
| Runtime | Node.js 20 |
| Framework | Next.js 15 (App Router) |
| Database | PostgreSQL 16 |
| ORM | Prisma 6 |
| Auth | Supabase Auth (magic link) |
| Validation | Zod |
| State | TanStack Query + Zustand |
| Styling | Tailwind CSS 4 + shadcn/ui |
| Deploy | Vercel |
4.2 Schemas
Vollstaendige Entitaetsdefinitionen mit Typen, Einschraenkungen, Relationen und Indizes. Dies ist das, was die Entitaeten des Locks im Code werden.
## Schemas
### User
| Field | Type | Constraints |
|-------|------|-------------|
| id | uuid | PK, default gen_random_uuid() |
| email | varchar(255) | UNIQUE, NOT NULL |
| name | varchar(100) | NOT NULL |
| avatarUrl | text | nullable |
| role | enum(Admin,Member,Guest) | NOT NULL, default 'Member' |
| createdAt | timestamptz | NOT NULL, default now() |
Relations: has many Message, has many Conversation (via membership)
### Message
| Field | Type | Constraints |
|-------|------|-------------|
| id | uuid | PK |
| content | text | NOT NULL |
| senderId | uuid | FK → User.id, NOT NULL |
| conversationId | uuid | FK → Conversation.id, NOT NULL |
| createdAt | timestamptz | NOT NULL, default now() |
Relations: belongs to User (sender), belongs to Conversation
Index: (conversationId, createdAt)
Der Plan MUSS ALLE Felder enthalten, nicht nur die im Lock spezifizierten. Das Lock hat ["id", "name", "email"] → der Plan fuegt Typen, Einschraenkungen, Standardwerte, Relationen, Indizes hinzu. Der Plan KANN Felder hinzufuegen, die das Lock nicht erwaehnt (z.B. createdAt, updatedAt).
4.3 Endpoints
API-Endpunkte, die jedes Feature implementieren. Jedes Feature im Lock MUSS auf mindestens einen Endpunkt (oder Hintergrundjob) abgebildet werden.
## Endpoints
### Messages
#### sendMessage
- `POST /api/messages`
- Auth: Member, Admin
- Body: `{ content: string, conversationId: string }`
- Response: `201 { message: Message }`
- Side effects: broadcast to conversation subscribers
- Validation: content 1-5000 chars, conversationId must exist
#### deleteMessage
- `DELETE /api/messages/:id`
- Auth: Admin only (or message owner)
- Response: `204`
Jeder Endpunkt MUSS enthalten:
- HTTP-Methode und Pfad
- Auth-Anforderungen
- Request-Body / Query-Parameter
- Response-Form und Statuscode
- Validierungsregeln
- Seiteneffekte (falls vorhanden)
4.4 Implementation Steps
Geordnete Schritte zum Aufbau von Null. Eine KI, die diesen Schritten folgt, erzeugt das vollstaendige Produkt.
## Implementation Steps
1. Initialize Next.js 15 project with TypeScript
2. Install dependencies: prisma, @supabase/supabase-js, zod, tailwindcss
3. Configure Prisma schema with all entities
4. Run prisma migrate to create database
5. Set up Supabase Auth with magic link
6. Create auth middleware
7. Implement API routes: messages, conversations, groups
8. Implement background jobs: fetchNews, enrichNews
9. Create UI pages: login, dashboard, conversations, settings
10. Configure RLS policies
11. Test all features against lock
12. Generate product.lock.json and verify
Regeln:
- Nummeriert, geordnet
- Jeder Schritt SOLLTE unabhaengig verifizierbar sein
- Granularitaet: jeder Schritt ≈ eine Arbeitssitzung fuer KI
5. Optionale Abschnitte
Diese Abschnitte einbeziehen, wenn das Produkt sie erfordert.
5.1 Architecture
Wenn nicht-triviale Patterns verwendet werden (Microservices, Event Sourcing, CQRS usw.).
## Architecture
REST API with Next.js Route Handlers. Supabase handles auth, database, storage, and real-time subscriptions. Single deployment on Vercel.
- API: Next.js Route Handlers (REST)
- Auth: Supabase middleware, RLS on database
- Real-time: Supabase Realtime subscriptions
- File storage: Supabase Storage
5.2 File Structure
Wenn das Projektlayout nicht standardmaessig ist oder Erklaerung braucht.
## File Structure
├── prisma/schema.prisma
├── src/
│ ├── app/
│ │ ├── (auth)/login/
│ │ ├── (dashboard)/
│ │ └── api/
│ ├── components/
│ │ ├── ui/ ← shadcn primitives
│ │ └── features/ ← domain components
│ ├── lib/
│ │ ├── db.ts
│ │ ├── auth.ts
│ │ └── validations/
│ ├── hooks/
│ └── types/
└── package.json
5.3 Auth & Permissions
Wenn das Lock actors oder permissions hat.
## Auth & Permissions
- Auth method: Supabase magic link (email OTP)
- Session: JWT stored in httpOnly cookie
- Middleware: `src/lib/auth.ts` extracts user + role
- Route protection: middleware checks role before handler
| Actor | Implementation |
|-------|---------------|
| Admin | role='admin' in users table, full access |
| Member | role='member', default for new signups |
| Guest | no auth, public routes only |
RLS policies:
- messages: SELECT for conversation members, INSERT for Member/Admin
- conversations: SELECT for members, INSERT for Member/Admin
5.4 Background Jobs
Wenn das Lock System-Stories hat (autonome Verhaltensweisen).
## Background Jobs
### fetchNews
- Trigger: cron every 30 minutes
- Process: fetch from RSS feeds → parse → store as NewsArticle
- Error handling: retry 3x, log failures
### enrichNewsWithAi
- Trigger: after new NewsArticle created
- Process: call local LLM → generate summary, impact, signal → update article
- Rate limit: 10 req/min to LLM
5.5 Third-party Services
Wenn externe Dienste verwendet werden.
## Third-party Services
| Service | Purpose | Config |
|---------|---------|--------|
| Supabase | Auth + DB + Storage + Realtime | SUPABASE_URL, SUPABASE_ANON_KEY |
| OpenAI / Local LLM | AI enrichment | OPENAI_API_KEY or OLLAMA_URL |
| Resend | Transactional email | RESEND_API_KEY |
5.6 Environment Variables
Wenn externe Konfiguration benoetigt wird.
## Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| DATABASE_URL | Yes | PostgreSQL connection string |
| SUPABASE_URL | Yes | Supabase project URL |
| SUPABASE_ANON_KEY | Yes | Supabase anonymous key |
| OPENAI_API_KEY | No | OpenAI API key (if not using local LLM) |
5.7 Denied Items Implementation
Wenn das Lock ein denied-Feld hat.
## Denied Items Implementation
- videoCall: no WebRTC, no video-related dependencies, no video UI
- voiceCall: no audio streaming, no voice-related dependencies
- Reaction: no reaction model, no reaction endpoints, no emoji picker on messages
6. Konventionen
6.1 Benennung
Der Plan verwendet Konventionen der Zielsprache, nicht Lock-Konventionen.
| Lock sagt | TypeScript-Plan | Python-Plan | Go-Plan |
|---|---|---|---|
sendMessage (camelCase) |
sendMessage |
send_message |
SendMessage |
User (PascalCase) |
User |
User (Klasse) / users (Tabelle) |
User |
6.2 Schemas
- ALLE Felder einschliessen, nicht nur die im Lock spezifizierten
- Lock hat
["id", "name", "email"]→ Plan fuegt Typen, Einschraenkungen, Standardwerte, Relationen, Indizes hinzu - Plan KANN Felder hinzufuegen, die das Lock nicht erwaehnt (z.B.
createdAt,updatedAt) — das Lock beschraenkt nur, was es spezifiziert
6.3 Endpoints
- Jedes Feature im Lock MUSS auf mindestens einen Endpunkt (oder Hintergrundjob) abgebildet werden
- Request-/Response-Formen einschliessen
- Auth-Anforderungen einschliessen
- Validierungsregeln einschliessen
- Seiteneffekte einschliessen
6.4 Implementation Steps
- Nummeriert, geordnet
- Jeder Schritt SOLLTE unabhaengig verifizierbar sein (“nach Schritt 5 sollte Auth funktionieren”)
- Granularitaet: jeder Schritt ≈ eine Arbeitssitzung fuer KI
7. Lock vs Plan
| Aspekt | Lock | Plan |
|---|---|---|
| Zielgruppe | Mensch (genehmigen/ablehnen) | KI (implementieren) |
| Inhalt | Produktgrenze (WAS) | Implementierungsblaupause (WIE) |
| Format | JSON (deterministisch) | Markdown (lesbar) |
| Stack | Nicht erwaehnt | Vollstaendig spezifiziert |
| Entitaetsfelder | Nur Namen | Namen + Typen + Einschraenkungen + Relationen |
| Features | Faehigkeitsnamen | Vollstaendige API-Vertraege |
| Stories | Natuerlichsprachliche Ablaeufe | Auf Endpunkte + Hintergrundjobs abgebildet |
| Permissions | Rollen-Feature-Matrix | Auth-Middleware + RLS-Policies |
| Portabilitaet | Sprachunabhaengig | Stack-spezifisch |
Diese Spezifikation ist Teil der Product Lock Spezifikation.