Files
code-vorlage/.claude/rules/backend.md
T
Florian Wilde b0c4e9e9b9 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
2026-08-09 00:48:50 +02:00

56 lines
2.1 KiB
Markdown

---
paths:
- "src/app/api/**"
- "src/lib/**"
- "src/server/**"
- "drizzle/**"
- "prisma/**"
---
# Backend Rules
## No preselected data layer
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.
Whatever is chosen must be self-hostable inside the Docker Compose stack —
the deployment target is a plain server, not a managed platform.
## 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