---
applyTo: "app/**/actions.ts,actions/**/*.ts,app/**/route.ts"
description: Rules for Next.js server mutations
---

# Server Actions and route handlers

- Files with actions start with `"use server"`. Export only async functions.
- Every action follows the same order:
  1. Parse input with a zod schema (`schema.safeParse(Object.fromEntries(formData))`).
  2. Get the session; return an unauthorized result if missing.
  3. Check the user may act on the target record (ownership or role).
  4. Perform the mutation through `lib/server/*`.
  5. Revalidate (`updateTag`/`revalidateTag`/`revalidatePath`) and/or `redirect()`.
- Return a typed result (`{ ok: true, data } | { ok: false, errors }`) for forms used with `useActionState`. Don't throw for validation errors.
- `redirect()` throws by design; call it outside `try/catch`.
- Never accept prices, roles, or user ids from the client as truth.
- Route handlers (`route.ts`) export `GET`/`POST` etc., return `Response.json(...)` with explicit status codes, and verify webhook signatures using the raw body (`await req.text()`).
- Rate-limit public mutations (login, signup, contact forms).
- Log errors server-side with context; return generic messages to the client.
