Next Stack (App Router + Prisma + TanStack Query)
Intent
Provide a consistent decision framework + implementation checklist for this stack, so changes stay:
- correct in server/client boundaries,
- consistent with UI & data patterns,
- testable and PR-ready.
When to use
Activate this skill when the task involves any of:
- Next.js App Router pages/layouts/route handlers/server actions
- Prisma-backed reads/writes
- client mutations, optimistic UI, live updates (TanStack Query)
- forms & validation (RHF + Zod)
- shadcn/ui + Tailwind components under
frontend/
Non-negotiables (stack rules)
- Server Components first
- Default to Server Components.
- Add
"use client" only when you need interactivity, local state, effects, or client-only libraries.
- Prisma is server-only
- Never import Prisma in Client Components.
- Ensure any Prisma usage runs in Node runtime (not Edge):
- For Route Handlers that might run on Edge, explicitly set:
export const runtime = "nodejs" (where applicable in your codebase conventions).
- Data fetching split
- Prefer server-side reads (RSC, route handlers, server actions) for static/deterministic reads.
- Use TanStack Query for:
- mutations,
- optimistic flows,
- client revalidation,
- “live-ish” / frequently changing UI state.
- React Query hygiene
- Stable, deterministic query keys (no unstable objects in keys).
- Precise invalidation (invalidate the smallest relevant scope).
- Forms & validation
- Use React Hook Form + Zod resolver.
- Maintain one Zod schema shared between client & server.
- Server must re-validate (do not trust client).
- Styling & UI
- Tailwind default.
- shadcn/ui lives under
frontend/components/ui/*.
- Preserve accessibility props/labels and semantic structure.
- Conventions
- ESLint (AirBnB-style) + Prettier.
- React component files in PascalCase (e.g.,
UserCard.tsx).
- Prefer named exports (unless Next.js route file conventions force defaults).
Workflow (how to execute tasks in this stack)
Step 1 — Clarify & make it verifiable
- Ask 1–3 clarifying questions if critical requirements are missing.
- Define acceptance criteria as verifiable checks:
- “what page shows what state”
- “what API returns what”
- “which tests prove it”
Step 2 — Decide server vs client boundary
Choose the minimum client surface area:
- If no interactivity: stay in RSC.
- If interaction/mutation: isolate
"use client" to the smallest component subtree.
Step 3 — Pick the data path
Reads
- Prefer RSC/server fetch.
- Be explicit about caching behavior for user-specific or frequently changing data:
- use
cache: "no-store" / revalidate strategy as appropriate to the app conventions.
Writes / mutations
- Implement server action or route handler as the mutation boundary.
- Client uses React Query
useMutation and invalidates exact keys.
Step 4 — Implement with shared schema
- Create/locate a shared
zod schema module (single source of truth).
- Client:
- RHF + zodResolver(schema)
- Server:
- schema.parse(...) (or safeParse with structured error return)
Step 5 — UI integration (shadcn + Tailwind)
- Use shadcn components for primitives; Tailwind for layout/spacing.
- Keep a11y intact: labels, aria attributes, keyboard focus, form errors.
Step 6 — Verification
Before finalizing:
- run lint + typecheck
- unit/component tests (Vitest + RTL) where applicable
- Playwright e2e for critical flows
(Use the repo’s package manager and scripts; inspect package.json / lockfiles and follow existing patterns.)
Step 7 — PR output expectations
PR should include:
- runnable code and relevant tests,
- a short rationale: what you changed, why it matches this stack,
- explicit trade-offs (e.g., “RSC read chosen over React Query because X”).
Anti-patterns (reject these)
- Prisma imported from any Client Component module graph
- Blanket
"use client" at high-level layouts/pages without necessity
- React Query used for deterministic static reads with no client interactivity need
- Unstable query keys (objects/functions/dates) causing cache misses
- Over-broad invalidation (invalidate everything) instead of precise keys
- Duplicate schemas (one for client, one for server)
Quick decision rules
- Start with RSC; promote to client only when you hit a real constraint.
- If Prisma is involved, ensure Node runtime and keep the boundary server-side.
- If you need optimistic UI or repeated client refresh, use React Query—but keep keys stable and invalidation precise.
1---2name: next-stack3description: Next.js App Router frontend stack workflow: Server Components-first, Prisma server-only (Node runtime), Tailwind + shadcn/ui, TanStack Query, React Hook Form + Zod, and conventions for work under frontend/. Use when implementing or refactoring UI, routes, data fetching, mutations, or forms in this stack.4---5
6# Next Stack (App Router + Prisma + TanStack Query)
7
8## Intent
9Provide a **consistent decision framework + implementation checklist** for this stack, so changes stay:
10- correct in server/client boundaries,
11- consistent with UI & data patterns,
12- testable and PR-ready.
13
14## When to use
15Activate this skill when the task involves any of:
16- Next.js App Router pages/layouts/route handlers/server actions
17- Prisma-backed reads/writes
18- client mutations, optimistic UI, live updates (TanStack Query)
19- forms & validation (RHF + Zod)
20- shadcn/ui + Tailwind components under `frontend/`
21
22## Non-negotiables (stack rules)
231) **Server Components first**
24- Default to Server Components.
25- Add `"use client"` only when you need interactivity, local state, effects, or client-only libraries.
26
272) **Prisma is server-only**
28- Never import Prisma in Client Components.
29- Ensure any Prisma usage runs in **Node runtime** (not Edge):
30 - For Route Handlers that might run on Edge, explicitly set:
31 - `export const runtime = "nodejs"` (where applicable in your codebase conventions).
32
333) **Data fetching split**
34- Prefer server-side reads (RSC, route handlers, server actions) for static/deterministic reads.
35- Use TanStack Query for:
36 - mutations,
37 - optimistic flows,
38 - client revalidation,
39 - “live-ish” / frequently changing UI state.
40
414) **React Query hygiene**
42- Stable, deterministic query keys (no unstable objects in keys).
43- Precise invalidation (invalidate the smallest relevant scope).
44
455) **Forms & validation**
46- Use **React Hook Form + Zod resolver**.
47- Maintain **one Zod schema** shared between client & server.
48- Server must re-validate (do not trust client).
49
506) **Styling & UI**
51- Tailwind default.
52- shadcn/ui lives under `frontend/components/ui/*`.
53- Preserve accessibility props/labels and semantic structure.
54
557) **Conventions**
56- ESLint (AirBnB-style) + Prettier.
57- React component files in PascalCase (e.g., `UserCard.tsx`).
58- Prefer **named exports** (unless Next.js route file conventions force defaults).
59
60## Workflow (how to execute tasks in this stack)
61### Step 1 — Clarify & make it verifiable
62- Ask 1–3 clarifying questions if critical requirements are missing.
63- Define acceptance criteria as verifiable checks:
64 - “what page shows what state”
65 - “what API returns what”
66 - “which tests prove it”
67
68### Step 2 — Decide server vs client boundary
69Choose the minimum client surface area:
70- If no interactivity: stay in RSC.
71- If interaction/mutation: isolate `"use client"` to the smallest component subtree.
72
73### Step 3 — Pick the data path
74**Reads**
75- Prefer RSC/server fetch.
76- Be explicit about caching behavior for user-specific or frequently changing data:
77 - use `cache: "no-store"` / revalidate strategy as appropriate to the app conventions.
78
79**Writes / mutations**
80- Implement server action or route handler as the mutation boundary.
81- Client uses React Query `useMutation` and invalidates exact keys.
82
83### Step 4 — Implement with shared schema
84- Create/locate a shared `zod` schema module (single source of truth).
85- Client:
86 - RHF + zodResolver(schema)
87- Server:
88 - schema.parse(...) (or safeParse with structured error return)
89
90### Step 5 — UI integration (shadcn + Tailwind)
91- Use shadcn components for primitives; Tailwind for layout/spacing.
92- Keep a11y intact: labels, aria attributes, keyboard focus, form errors.
93
94### Step 6 — Verification
95Before finalizing:
96- run lint + typecheck
97- unit/component tests (Vitest + RTL) where applicable
98- Playwright e2e for critical flows
99
100(Use the repo’s package manager and scripts; inspect `package.json` / lockfiles and follow existing patterns.)
101
102### Step 7 — PR output expectations
103PR should include:
104- runnable code and relevant tests,
105- a short rationale: what you changed, why it matches this stack,
106- explicit trade-offs (e.g., “RSC read chosen over React Query because X”).
107
108## Anti-patterns (reject these)
109- Prisma imported from any Client Component module graph
110- Blanket `"use client"` at high-level layouts/pages without necessity
111- React Query used for deterministic static reads with no client interactivity need
112- Unstable query keys (objects/functions/dates) causing cache misses
113- Over-broad invalidation (invalidate everything) instead of precise keys
114- Duplicate schemas (one for client, one for server)
115
116## Quick decision rules
117- Start with RSC; promote to client only when you hit a real constraint.
118- If Prisma is involved, ensure Node runtime and keep the boundary server-side.
119- If you need optimistic UI or repeated client refresh, use React Query—but keep keys stable and invalidation precise.