refactor: rebuild template — Tailwind v4, Docker self-hosting, passkey auth

Toolchain fixes (all previously broken):
- npm run lint: next lint was removed in Next 16 -> eslint with flat config
- .eslintrc.json was ignored by ESLint 9 -> eslint.config.mjs
- npm test / test:e2e exited 1 with no tests -> passWithNoTests
- Vitest scanned tests/ and would have run Playwright specs -> scoped to src/
- Playwright targeted Mobile Safari while docs installed only chromium
- reuseExistingServer silently tested a foreign server on :3000 -> E2E_PORT
- 11 high-severity vulns -> npm audit fix
- deny rule Read(**/.env*) also blocked .env.example -> precise patterns

Stack changes:
- Tailwind v3 -> v4 (CSS-first, no tailwind.config.ts, tw-animate-css)
- shadcn regenerated for v4; 33 components -> 6 core, bundled radix-ui
- Supabase removed entirely; data layer is now chosen per project
- Vercel removed; Docker Compose self-hosting with scripts/update.sh
- Better Auth + passkey plugin as the binding auth standard
- ThemeProvider and Sonner mounted; dark mode and toasts now actually work

Workflow system:
- Sub-agents wired: /frontend, /backend, /qa delegate to .claude/agents
- Checklists folded into their SKILL.md; one file per skill
- Rules rewritten: DB-agnostic backend, passkey security, v4 frontend
- Spec language settled as German, skill instructions English
This commit is contained in:
Florian Wilde
2026-08-09 00:48:50 +02:00
parent a8b196e92b
commit b0c4e9e9b9
101 changed files with 3651 additions and 7695 deletions
+46 -23
View File
@@ -1,32 +1,55 @@
---
paths:
- "src/app/api/**"
- "src/lib/supabase*"
- "supabase/**"
- "src/lib/**"
- "src/server/**"
- "drizzle/**"
- "prisma/**"
---
# Backend Development Rules
# Backend Rules
## Database (Supabase)
- ALWAYS enable Row Level Security on every table
- Create RLS policies for SELECT, INSERT, UPDATE, DELETE
- Add indexes on columns used in WHERE, ORDER BY, and JOIN clauses
- Use foreign keys with ON DELETE CASCADE where appropriate
- Never skip RLS - security first
## No preselected data layer
## API Routes
- Validate all inputs using Zod schemas before processing
- Always check authentication: verify user session exists
- Return meaningful error messages with appropriate HTTP status codes
- Use `.limit()` on all list queries
This template ships **no** database, ORM or BaaS. `/architecture` picks one per
project and records the choice in the spec's Technical Decisions table. Until that
decision exists, do not install an ORM or write schema code.
## Query Patterns
- Use Supabase joins instead of N+1 query loops
- Use `unstable_cache` from Next.js for rarely-changing data
- Always handle errors from Supabase responses
Whatever is chosen must be self-hostable inside the Docker Compose stack —
the deployment target is a plain server, not a managed platform.
## Security
- Never hardcode secrets in source code
- Use environment variables for all credentials
- Validate and sanitize all user input
- Use parameterized queries (Supabase handles this)
## Route Handlers
- Validate every request body with a Zod schema before touching it. Reuse the
schema the form already uses; never trust client-side validation alone.
- Check authentication before doing any work — see `.claude/rules/security.md`
- Return correct status codes: 400 validation, 401 unauthenticated,
403 unauthorized, 404 missing, 409 conflict, 500 unexpected
- Error responses carry a message safe to show a user. Log the detail server-side;
never leak stack traces, SQL or internal IDs to the client.
## Data Access
- **Scope every query by the current user.** Ownership is checked in the query
itself (`where userId = session.user.id`), not after fetching. A filter applied
in application code after a broad read is a data leak waiting for a bug.
- Index columns used in WHERE, ORDER BY and JOIN
- Foreign keys with an explicit ON DELETE behaviour
- Always paginate or `.limit()` list queries — no unbounded reads
- Use joins instead of looping queries (N+1)
- Only parameterized queries. Never build SQL through string concatenation.
- Handle the error branch of every database call
## Migrations
- Schema changes go through checked-in migration files, never manual edits on a
running database
- Migrations must be reversible or explicitly documented as one-way
- The deployment step runs pending migrations before the new container serves
traffic — see `docs/DEPLOYMENT.md`
## Secrets
- Read configuration from `process.env`, never hardcode it
- Every new variable goes into `.env.example` with a dummy value in the same commit
- `NEXT_PUBLIC_` only for values that are safe in a browser bundle