tribunal-kit 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/.agent/ARCHITECTURE.md +99 -99
  2. package/.agent/GEMINI.md +52 -52
  3. package/.agent/agents/accessibility-reviewer.md +187 -220
  4. package/.agent/agents/ai-code-reviewer.md +199 -233
  5. package/.agent/agents/backend-specialist.md +215 -238
  6. package/.agent/agents/code-archaeologist.md +161 -181
  7. package/.agent/agents/database-architect.md +184 -207
  8. package/.agent/agents/debugger.md +191 -218
  9. package/.agent/agents/dependency-reviewer.md +103 -136
  10. package/.agent/agents/devops-engineer.md +218 -238
  11. package/.agent/agents/documentation-writer.md +201 -221
  12. package/.agent/agents/explorer-agent.md +160 -180
  13. package/.agent/agents/frontend-reviewer.md +160 -194
  14. package/.agent/agents/frontend-specialist.md +248 -237
  15. package/.agent/agents/game-developer.md +48 -52
  16. package/.agent/agents/logic-reviewer.md +116 -149
  17. package/.agent/agents/mobile-developer.md +200 -223
  18. package/.agent/agents/mobile-reviewer.md +162 -195
  19. package/.agent/agents/orchestrator.md +181 -211
  20. package/.agent/agents/penetration-tester.md +157 -174
  21. package/.agent/agents/performance-optimizer.md +183 -203
  22. package/.agent/agents/performance-reviewer.md +178 -211
  23. package/.agent/agents/product-manager.md +142 -162
  24. package/.agent/agents/product-owner.md +6 -25
  25. package/.agent/agents/project-planner.md +142 -162
  26. package/.agent/agents/qa-automation-engineer.md +225 -242
  27. package/.agent/agents/security-auditor.md +174 -194
  28. package/.agent/agents/seo-specialist.md +193 -213
  29. package/.agent/agents/sql-reviewer.md +161 -194
  30. package/.agent/agents/supervisor-agent.md +184 -203
  31. package/.agent/agents/swarm-worker-contracts.md +17 -17
  32. package/.agent/agents/swarm-worker-registry.md +46 -46
  33. package/.agent/agents/test-coverage-reviewer.md +160 -193
  34. package/.agent/agents/test-engineer.md +0 -21
  35. package/.agent/agents/type-safety-reviewer.md +175 -208
  36. package/.agent/patterns/generator.md +9 -9
  37. package/.agent/patterns/inversion.md +12 -12
  38. package/.agent/patterns/pipeline.md +9 -9
  39. package/.agent/patterns/reviewer.md +13 -13
  40. package/.agent/patterns/tool-wrapper.md +9 -9
  41. package/.agent/rules/GEMINI.md +63 -63
  42. package/.agent/scripts/compress_skills.py +167 -0
  43. package/.agent/scripts/consolidate_skills.py +173 -0
  44. package/.agent/scripts/deep_compress.py +202 -0
  45. package/.agent/scripts/minify_context.py +80 -0
  46. package/.agent/scripts/security_scan.py +1 -1
  47. package/.agent/scripts/strip_tribunal.py +41 -0
  48. package/.agent/skills/agent-organizer/SKILL.md +92 -126
  49. package/.agent/skills/agentic-patterns/SKILL.md +0 -70
  50. package/.agent/skills/ai-prompt-injection-defense/SKILL.md +126 -160
  51. package/.agent/skills/api-patterns/SKILL.md +123 -215
  52. package/.agent/skills/api-security-auditor/SKILL.md +143 -177
  53. package/.agent/skills/app-builder/SKILL.md +326 -50
  54. package/.agent/skills/app-builder/templates/SKILL.md +13 -15
  55. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +16 -16
  56. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +22 -22
  57. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +18 -18
  58. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +20 -20
  59. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +17 -17
  60. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +18 -18
  61. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +21 -21
  62. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +19 -19
  63. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +26 -26
  64. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +26 -26
  65. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +19 -19
  66. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +18 -18
  67. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +20 -20
  68. package/.agent/skills/appflow-wireframe/SKILL.md +87 -121
  69. package/.agent/skills/architecture/SKILL.md +82 -252
  70. package/.agent/skills/authentication-best-practices/SKILL.md +139 -173
  71. package/.agent/skills/bash-linux/SKILL.md +120 -154
  72. package/.agent/skills/behavioral-modes/SKILL.md +8 -69
  73. package/.agent/skills/brainstorming/SKILL.md +428 -104
  74. package/.agent/skills/building-native-ui/SKILL.md +143 -174
  75. package/.agent/skills/clean-code/SKILL.md +323 -360
  76. package/.agent/skills/code-review-checklist/SKILL.md +0 -62
  77. package/.agent/skills/config-validator/SKILL.md +107 -141
  78. package/.agent/skills/csharp-developer/SKILL.md +468 -528
  79. package/.agent/skills/database-design/SKILL.md +104 -369
  80. package/.agent/skills/deployment-procedures/SKILL.md +111 -145
  81. package/.agent/skills/devops-engineer/SKILL.md +295 -332
  82. package/.agent/skills/devops-incident-responder/SKILL.md +79 -113
  83. package/.agent/skills/doc.md +5 -5
  84. package/.agent/skills/documentation-templates/SKILL.md +19 -63
  85. package/.agent/skills/edge-computing/SKILL.md +123 -157
  86. package/.agent/skills/extract-design-system/SKILL.md +100 -134
  87. package/.agent/skills/framer-motion-expert/SKILL.md +111 -855
  88. package/.agent/skills/frontend-design/SKILL.md +151 -499
  89. package/.agent/skills/game-design-expert/SKILL.md +71 -105
  90. package/.agent/skills/game-engineering-expert/SKILL.md +88 -122
  91. package/.agent/skills/geo-fundamentals/SKILL.md +89 -124
  92. package/.agent/skills/github-operations/SKILL.md +279 -314
  93. package/.agent/skills/gsap-expert/SKILL.md +119 -826
  94. package/.agent/skills/i18n-localization/SKILL.md +104 -138
  95. package/.agent/skills/intelligent-routing/SKILL.md +159 -127
  96. package/.agent/skills/lint-and-validate/SKILL.md +8 -52
  97. package/.agent/skills/llm-engineering/SKILL.md +344 -357
  98. package/.agent/skills/local-first/SKILL.md +120 -154
  99. package/.agent/skills/mcp-builder/SKILL.md +84 -118
  100. package/.agent/skills/mobile-design/SKILL.md +213 -219
  101. package/.agent/skills/motion-engineering/SKILL.md +184 -0
  102. package/.agent/skills/nextjs-react-expert/SKILL.md +99 -698
  103. package/.agent/skills/nodejs-best-practices/SKILL.md +498 -559
  104. package/.agent/skills/observability/SKILL.md +293 -330
  105. package/.agent/skills/parallel-agents/SKILL.md +88 -122
  106. package/.agent/skills/performance-profiling/SKILL.md +217 -254
  107. package/.agent/skills/plan-writing/SKILL.md +84 -118
  108. package/.agent/skills/platform-engineer/SKILL.md +89 -123
  109. package/.agent/skills/playwright-best-practices/SKILL.md +128 -162
  110. package/.agent/skills/powershell-windows/SKILL.md +112 -146
  111. package/.agent/skills/python-patterns/SKILL.md +7 -35
  112. package/.agent/skills/python-pro/SKILL.md +148 -754
  113. package/.agent/skills/react-specialist/SKILL.md +123 -827
  114. package/.agent/skills/readme-builder/SKILL.md +15 -85
  115. package/.agent/skills/realtime-patterns/SKILL.md +269 -304
  116. package/.agent/skills/red-team-tactics/SKILL.md +10 -51
  117. package/.agent/skills/rust-pro/SKILL.md +623 -701
  118. package/.agent/skills/seo-fundamentals/SKILL.md +120 -154
  119. package/.agent/skills/server-management/SKILL.md +156 -190
  120. package/.agent/skills/shadcn-ui-expert/SKILL.md +172 -206
  121. package/.agent/skills/skill-creator/SKILL.md +18 -58
  122. package/.agent/skills/sql-pro/SKILL.md +579 -633
  123. package/.agent/skills/supabase-postgres-best-practices/SKILL.md +28 -68
  124. package/.agent/skills/swiftui-expert/SKILL.md +142 -176
  125. package/.agent/skills/systematic-debugging/SKILL.md +84 -118
  126. package/.agent/skills/tailwind-patterns/SKILL.md +516 -576
  127. package/.agent/skills/tdd-workflow/SKILL.md +103 -137
  128. package/.agent/skills/test-result-analyzer/SKILL.md +33 -73
  129. package/.agent/skills/testing-patterns/SKILL.md +512 -573
  130. package/.agent/skills/trend-researcher/SKILL.md +30 -71
  131. package/.agent/skills/ui-ux-pro-max/SKILL.md +0 -41
  132. package/.agent/skills/ui-ux-researcher/SKILL.md +51 -91
  133. package/.agent/skills/vue-expert/SKILL.md +127 -866
  134. package/.agent/skills/vulnerability-scanner/SKILL.md +354 -269
  135. package/.agent/skills/web-accessibility-auditor/SKILL.md +159 -193
  136. package/.agent/skills/web-design-guidelines/SKILL.md +17 -61
  137. package/.agent/skills/webapp-testing/SKILL.md +111 -145
  138. package/.agent/skills/whimsy-injector/SKILL.md +58 -132
  139. package/.agent/skills/workflow-optimizer/SKILL.md +28 -68
  140. package/.agent/workflows/api-tester.md +151 -151
  141. package/.agent/workflows/audit.md +127 -138
  142. package/.agent/workflows/brainstorm.md +110 -110
  143. package/.agent/workflows/changelog.md +112 -112
  144. package/.agent/workflows/create.md +124 -124
  145. package/.agent/workflows/debug.md +165 -189
  146. package/.agent/workflows/deploy.md +180 -189
  147. package/.agent/workflows/enhance.md +128 -151
  148. package/.agent/workflows/fix.md +114 -135
  149. package/.agent/workflows/generate.md +12 -4
  150. package/.agent/workflows/migrate.md +160 -160
  151. package/.agent/workflows/orchestrate.md +168 -168
  152. package/.agent/workflows/performance-benchmarker.md +114 -123
  153. package/.agent/workflows/plan.md +173 -173
  154. package/.agent/workflows/preview.md +80 -80
  155. package/.agent/workflows/refactor.md +161 -183
  156. package/.agent/workflows/review-ai.md +101 -129
  157. package/.agent/workflows/review.md +116 -116
  158. package/.agent/workflows/session.md +94 -94
  159. package/.agent/workflows/status.md +79 -79
  160. package/.agent/workflows/strengthen-skills.md +138 -139
  161. package/.agent/workflows/swarm.md +179 -179
  162. package/.agent/workflows/test.md +189 -211
  163. package/.agent/workflows/tribunal-backend.md +93 -113
  164. package/.agent/workflows/tribunal-database.md +94 -115
  165. package/.agent/workflows/tribunal-frontend.md +95 -118
  166. package/.agent/workflows/tribunal-full.md +92 -133
  167. package/.agent/workflows/tribunal-mobile.md +94 -119
  168. package/.agent/workflows/tribunal-performance.md +109 -133
  169. package/.agent/workflows/ui-ux-pro-max.md +122 -143
  170. package/package.json +1 -1
  171. package/.agent/skills/api-patterns/api-style.md +0 -42
  172. package/.agent/skills/api-patterns/auth.md +0 -24
  173. package/.agent/skills/api-patterns/documentation.md +0 -26
  174. package/.agent/skills/api-patterns/graphql.md +0 -41
  175. package/.agent/skills/api-patterns/rate-limiting.md +0 -31
  176. package/.agent/skills/api-patterns/response.md +0 -37
  177. package/.agent/skills/api-patterns/rest.md +0 -40
  178. package/.agent/skills/api-patterns/security-testing.md +0 -122
  179. package/.agent/skills/api-patterns/trpc.md +0 -41
  180. package/.agent/skills/api-patterns/versioning.md +0 -22
  181. package/.agent/skills/app-builder/agent-coordination.md +0 -71
  182. package/.agent/skills/app-builder/feature-building.md +0 -53
  183. package/.agent/skills/app-builder/project-detection.md +0 -34
  184. package/.agent/skills/app-builder/scaffolding.md +0 -118
  185. package/.agent/skills/app-builder/tech-stack.md +0 -40
  186. package/.agent/skills/architecture/context-discovery.md +0 -43
  187. package/.agent/skills/architecture/examples.md +0 -94
  188. package/.agent/skills/architecture/pattern-selection.md +0 -68
  189. package/.agent/skills/architecture/patterns-reference.md +0 -50
  190. package/.agent/skills/architecture/trade-off-analysis.md +0 -77
  191. package/.agent/skills/brainstorming/dynamic-questioning.md +0 -360
  192. package/.agent/skills/database-design/database-selection.md +0 -43
  193. package/.agent/skills/database-design/indexing.md +0 -39
  194. package/.agent/skills/database-design/migrations.md +0 -48
  195. package/.agent/skills/database-design/optimization.md +0 -36
  196. package/.agent/skills/database-design/orm-selection.md +0 -30
  197. package/.agent/skills/database-design/schema-design.md +0 -56
  198. package/.agent/skills/frontend-design/animation-guide.md +0 -331
  199. package/.agent/skills/frontend-design/color-system.md +0 -329
  200. package/.agent/skills/frontend-design/decision-trees.md +0 -418
  201. package/.agent/skills/frontend-design/motion-graphics.md +0 -306
  202. package/.agent/skills/frontend-design/typography-system.md +0 -363
  203. package/.agent/skills/frontend-design/ux-psychology.md +0 -1116
  204. package/.agent/skills/frontend-design/visual-effects.md +0 -383
  205. package/.agent/skills/intelligent-routing/router-manifest.md +0 -65
  206. package/.agent/skills/mobile-design/decision-trees.md +0 -516
  207. package/.agent/skills/mobile-design/mobile-backend.md +0 -491
  208. package/.agent/skills/mobile-design/mobile-color-system.md +0 -420
  209. package/.agent/skills/mobile-design/mobile-debugging.md +0 -122
  210. package/.agent/skills/mobile-design/mobile-design-thinking.md +0 -357
  211. package/.agent/skills/mobile-design/mobile-navigation.md +0 -458
  212. package/.agent/skills/mobile-design/mobile-performance.md +0 -767
  213. package/.agent/skills/mobile-design/mobile-testing.md +0 -356
  214. package/.agent/skills/mobile-design/mobile-typography.md +0 -433
  215. package/.agent/skills/mobile-design/platform-android.md +0 -666
  216. package/.agent/skills/mobile-design/platform-ios.md +0 -561
  217. package/.agent/skills/mobile-design/touch-psychology.md +0 -537
  218. package/.agent/skills/nextjs-react-expert/1-async-eliminating-waterfalls.md +0 -312
  219. package/.agent/skills/nextjs-react-expert/2-bundle-bundle-size-optimization.md +0 -240
  220. package/.agent/skills/nextjs-react-expert/3-server-server-side-performance.md +0 -490
  221. package/.agent/skills/nextjs-react-expert/4-client-client-side-data-fetching.md +0 -264
  222. package/.agent/skills/nextjs-react-expert/5-rerender-re-render-optimization.md +0 -581
  223. package/.agent/skills/nextjs-react-expert/6-rendering-rendering-performance.md +0 -432
  224. package/.agent/skills/nextjs-react-expert/7-js-javascript-performance.md +0 -684
  225. package/.agent/skills/nextjs-react-expert/8-advanced-advanced-patterns.md +0 -150
  226. package/.agent/skills/vulnerability-scanner/checklists.md +0 -121
@@ -1,783 +1,184 @@
1
1
  ---
2
2
  name: nextjs-react-expert
3
- description: Next.js 15+ App Router mastery. Server Components, Server Actions, Streaming SSR, Partial Prerendering (PPR), route handlers, middleware, caching/revalidation, generateMetadata, parallel routes, intercepting routes, and AI streaming UI. Use when building Next.js applications, optimizing performance, eliminating waterfalls, or implementing App Router patterns.
3
+ description: Next.js 15+ App Router mastery. Server Components, Server Actions, PPR, caching, metadata, middleware, parallel/intercepting routes. Use when building Next.js apps or optimizing Next.js performance.
4
4
  allowed-tools: Read, Write, Edit, Glob, Grep
5
- version: 2.0.0
6
- last-updated: 2026-03-30
7
- applies-to-model: gemini-2.5-pro, claude-3-7-sonnet
5
+ version: 3.1.0
6
+ last-updated: 2026-04-06
7
+ applies-to-model: gemini-3-1-pro, claude-3-7-sonnet
8
8
  ---
9
9
 
10
- # Next.js 15+ App Router — Pro-Max Patterns
10
+ # Next.js 15+ App Router — Dense Reference
11
11
 
12
- > The fastest code is code that doesn't run on the client.
13
- > The second fastest is code that runs on the edge and streams the result.
14
- > If you're using `getServerSideProps`, `getStaticProps`, or the Pages Router you're writing legacy.
12
+ ## Hallucination Traps (Read First)
13
+ - `pages/api/` or `_app.tsx` App Router only: `app/api/route.ts`, `app/layout.tsx`
14
+ - `getServerSideProps` `async function Page()` fetches directly
15
+ - ❌ `next/router` → ✅ `next/navigation` (`useRouter`, `usePathname`, `useSearchParams`)
16
+ - ❌ Server Action without `"use server"` → ✅ Required at top of file or top of function
17
+ - ❌ Fetch is cached by default → ✅ **Next.js 15 changed this**: `fetch()` is UNCACHED by default
18
+ - ❌ `cookies()` at top of page → ✅ Opts entire route into dynamic rendering, breaking PPR. Wrap inside `<Suspense>`
19
+ - ❌ Passing functions as props Server → Client → ✅ Illegal. Use Server Actions instead.
20
+ - ❌ Plain `Response` in route handler → ✅ Use `NextResponse.json()`
15
21
 
16
22
  ---
17
23
 
18
- ## Paradigm Shifts (Next.js 14 → 15+)
24
+ ## App Router Conventions
19
25
 
20
- | Legacy (Pages Router / Next 14) | Modern (App Router / Next 15+) |
21
- |---|---|
22
- | `getServerSideProps` / `getStaticProps` | **Server Components** fetch directly |
23
- | Manual `useMemo()` / `useCallback()` | **React Compiler** handles memoization |
24
- | Client-side form handling | **Server Actions** native mutations |
25
- | Loading spinners on client | **Streaming UI** + `<Suspense>` boundaries |
26
- | Static *or* Dynamic pages | **Partial Prerendering (PPR)** — both in one route |
27
- | `next/router` (`useRouter`) | `next/navigation` (`useRouter`, `usePathname`, `useSearchParams`) |
28
-
29
- ---
30
-
31
- ## App Router File Conventions
32
-
33
- ```
26
+ ```text
34
27
  app/
35
- ├── layout.tsx ← Root layout (wraps ALL routes)
36
- ├── page.tsx Home page (/)
37
- ├── loading.tsx Automatic <Suspense> fallback for the route
38
- ├── error.tsx ← Error boundary for the route
39
- ├── not-found.tsx ← 404 page
40
- ├── global-error.tsx ← Root error boundary (wraps layout)
41
-
42
- ├── dashboard/
43
- │ ├── layout.tsx Dashboard layout (persists across sub-routes)
44
- │ ├── page.tsx ← /dashboard
45
- │ ├── loading.tsx ← Dashboard loading state
46
- │ ├── error.tsx ← Dashboard error boundary
47
- │ │
48
- │ ├── settings/
49
- │ │ └── page.tsx ← /dashboard/settings
50
- │ │
51
- │ └── [userId]/ ← Dynamic segment
52
- │ └── page.tsx ← /dashboard/abc123
53
-
54
- ├── api/
55
- │ └── users/
56
- │ └── route.ts ← API Route Handler (GET, POST, etc.)
57
-
58
- ├── @modal/ ← Parallel route (named slot)
59
- │ └── login/
60
- │ └── page.tsx ← Rendered in parallel with main content
61
-
62
- └── (marketing)/ ← Route group (no URL impact — for layout organization)
63
- ├── layout.tsx ← Layout ONLY for marketing pages
64
- ├── about/
65
- │ └── page.tsx ← /about (NOT /marketing/about)
66
- └── pricing/
67
- └── page.tsx ← /pricing
68
- ```
69
-
70
- ```tsx
71
- // ❌ HALLUCINATION TRAP: These Pages Router files DO NOT EXIST in App Router
72
- // _app.tsx → use app/layout.tsx
73
- // _document.tsx → use app/layout.tsx with <html> and <body>
74
- // pages/api/ → use app/api/route.ts
75
- // getServerSideProps → fetch directly in Server Components
76
- // getStaticProps → fetch at build time or use generateStaticParams
28
+ ├── layout.tsx ← Root shell (HTML/BODY)
29
+ ├── page.tsx Route UI
30
+ ├── loading.tsx Auto-suspense fallback
31
+ ├── error.tsx ← Error boundary (Must be "use client")
32
+ ├── not-found.tsx ← 404 UI
33
+ ├── global-error.tsx ← Root error boundary
34
+ ├── api/users/route.ts ← API Handler (GET, POST)
35
+ ├── @modal/login/page.tsx ← Parallel Route (renders in same layout)
36
+ └── (auth)/login/page.tsx Route Group (doesn't affect URL)
77
37
  ```
78
38
 
79
39
  ---
80
40
 
81
41
  ## Server vs Client Components
82
42
 
83
- ### The Decision
84
-
85
- ```
86
- Default: Server Component (Zero JS sent to client)
87
- Switch to Client ('use client') ONLY when:
88
- ✓ Uses browser APIs (window, localStorage, navigator, IntersectionObserver)
89
- ✓ Needs DOM event handlers (onClick, onChange, onSubmit)
90
- ✓ Needs state/effects (useState, useEffect, useRef for DOM)
91
- ✓ Needs Framer Motion, GSAP, or client-side animation libraries
92
-
93
- Everything else stays on the server.
94
- ```
95
-
96
- ### The Interleaving Pattern
43
+ - **Server Components (Default)**: Zero JS. Direct DB access. Secure env vars.
44
+ - **Client Components (`"use client"`)**: Lifecycle (`useEffect`), State (`useState`), Browser APIs (`window`), Event listeners (`onClick`).
97
45
 
98
46
  ```tsx
99
- // ✅ CORRECT: Keep the shell on the server, pass server content INTO client
100
- // app/dashboard/page.tsx (Server Component)
101
- import { ClientSidebar } from "./ClientSidebar";
102
- import { ServerStats } from "./ServerStats"; // fetches DB directly
103
-
104
- export default async function DashboardPage() {
105
- const stats = await getStats(); // no API call needed — direct DB
106
-
47
+ // ✅ INTERLEAVING PATTERN: Pass Server Component as children to Client Component
48
+ export default function Page() {
107
49
  return (
108
- <div className="flex">
109
- <ClientSidebar> {/* client: has onClick, state */}
110
- <ServerStats data={stats} /> {/* server: zero JS, renders HTML */}
111
- </ClientSidebar>
112
- </div>
50
+ <ClientSidebar> {/* "use client" */}
51
+ <ServerStats /> {/* Server: zero JS bundle, fetches DB */}
52
+ </ClientSidebar>
113
53
  );
114
54
  }
115
-
116
- // ❌ WRONG: Making the entire page "use client" because one button needs onClick
117
- // This ships ALL the JS to the client — defeats the purpose of RSC
118
- ```
119
-
120
- ### Serialization Boundary
121
-
122
- ```tsx
123
- // Only serializable data can cross the server→client boundary
124
- // ✅ Can pass: strings, numbers, booleans, arrays, plain objects, Date, Map, Set
125
- // ❌ Cannot pass: functions, class instances, DOM nodes, Symbols
126
-
127
- // ❌ BAD: Passing a function from server to client
128
- <ClientButton onClick={() => deleteItem(id)} /> // functions aren't serializable
129
-
130
- // ✅ GOOD: Use a Server Action instead
131
- <ClientButton deleteAction={deleteItemAction} itemId={id} />
132
-
133
- // In ClientButton:
134
- "use client";
135
- function ClientButton({ deleteAction, itemId }) {
136
- return <button onClick={() => deleteAction(itemId)}>Delete</button>;
137
- }
138
55
  ```
139
56
 
140
57
  ---
141
58
 
142
- ## Server Actions
59
+ ## Server Actions (Mutations)
143
60
 
144
61
  ```tsx
145
- // Server Actions are async functions that run on the server
146
- // They can be called from client or server components
147
-
148
- // ✅ Inline Server Action (defined in a Server Component)
149
- export default function Page() {
150
- async function createUser(formData: FormData) {
151
- "use server"; // marks this function as a Server Action
152
-
153
- const name = formData.get("name") as string;
154
- const email = formData.get("email") as string;
155
-
156
- await db.user.create({ data: { name, email } });
157
- revalidatePath("/users"); // bust cache for /users
158
- redirect("/users"); // redirect after mutation
159
- }
160
-
161
- return (
162
- <form action={createUser}>
163
- <input name="name" required />
164
- <input name="email" type="email" required />
165
- <button type="submit">Create</button>
166
- </form>
167
- );
168
- }
169
- ```
170
-
171
- ### Separate Action File
172
-
173
- ```tsx
174
- // app/actions/user.ts
175
- "use server";
176
-
62
+ "use server"
177
63
  import { revalidatePath } from "next/cache";
178
- import { redirect } from "next/navigation";
179
64
  import { z } from "zod";
180
65
 
181
- const UserSchema = z.object({
182
- name: z.string().min(2),
183
- email: z.string().email(),
184
- });
66
+ const Schema = z.object({ name: z.string().min(2) });
185
67
 
186
68
  export async function createUser(prevState: any, formData: FormData) {
187
- const parsed = UserSchema.safeParse({
188
- name: formData.get("name"),
189
- email: formData.get("email"),
190
- });
191
-
192
- if (!parsed.success) {
193
- return { errors: parsed.error.flatten().fieldErrors };
194
- }
195
-
196
- try {
197
- await db.user.create({ data: parsed.data });
198
- } catch (e) {
199
- return { errors: { _form: ["Failed to create user"] } };
200
- }
201
-
202
- revalidatePath("/users");
203
- redirect("/users");
69
+ // TRAP: ALWAYS validate formData. Never trust client input.
70
+ const parsed = Schema.safeParse({ name: formData.get("name") });
71
+ if (!parsed.success) return { errors: parsed.error.flatten().fieldErrors };
72
+
73
+ await db.user.create({ data: parsed.data });
74
+ revalidatePath("/users"); // Clears cache so next render shows new user
75
+ return { success: true };
204
76
  }
205
-
206
- // ❌ HALLUCINATION TRAP: Server Actions MUST be in a file with "use server"
207
- // at the top, OR defined inline with "use server" inside the function body.
208
- // They CANNOT be imported from a regular module.
209
-
210
- // ❌ HALLUCINATION TRAP: Always validate input in Server Actions.
211
- // FormData comes from the client — it's user input. Never trust it.
212
77
  ```
213
78
 
214
- ---
215
-
216
- ## Data Fetching & Caching
217
-
218
- ### Fetching in Server Components
219
-
79
+ Client usage (React 19):
220
80
  ```tsx
221
- // Server Components can fetch data directly — no useEffect, no API route
222
- export default async function UsersPage() {
223
- const users = await db.user.findMany(); // direct DB call
224
- // OR
225
- const res = await fetch("https://api.example.com/users", {
226
- next: { revalidate: 3600 }, // ISR: revalidate every hour
227
- });
228
- const users = await res.json();
229
-
230
- return <UserList users={users} />;
81
+ "use client"
82
+ import { useActionState } from "react";
83
+ import { createUser } from "./actions";
84
+
85
+ export function UserForm() {
86
+ const [state, formAction, isPending] = useActionState(createUser, null);
87
+ return (
88
+ <form action={formAction}>
89
+ <input name="name" />
90
+ <button disabled={isPending}>Submit</button>
91
+ {state?.errors?.name && <p>{state.errors.name}</p>}
92
+ </form>
93
+ )
231
94
  }
232
95
  ```
233
96
 
234
- ### Caching Strategies
235
-
236
- ```tsx
237
- // 1. Static (cached forever until revalidated)
238
- const data = await fetch(url); // default: cached
239
-
240
- // 2. ISR (Incremental Static Regeneration)
241
- const data = await fetch(url, {
242
- next: { revalidate: 60 }, // revalidate every 60 seconds
243
- });
244
-
245
- // 3. Dynamic (never cached)
246
- const data = await fetch(url, { cache: "no-store" });
247
-
248
- // 4. On-demand revalidation (Server Actions / Webhooks)
249
- import { revalidatePath, revalidateTag } from "next/cache";
250
-
251
- // Revalidate a specific path
252
- revalidatePath("/dashboard");
253
-
254
- // Revalidate by tag
255
- const data = await fetch(url, { next: { tags: ["users"] } });
256
- // Later, in a Server Action:
257
- revalidateTag("users"); // busts all fetches tagged "users"
258
-
259
- // ❌ HALLUCINATION TRAP: Next.js 15 changed the default caching behavior
260
- // In Next.js 14: fetch was cached by default
261
- // In Next.js 15: fetch is NOT cached by default (dynamic by default)
262
- // You must explicitly opt into caching with next.revalidate or cache: "force-cache"
263
- ```
97
+ ---
264
98
 
265
- ### `unstable_cache` for Non-Fetch Data
99
+ ## Data Fetching & Caching (Next.js 15)
266
100
 
267
101
  ```tsx
268
- import { unstable_cache } from "next/cache";
102
+ // Next.js 15 caching defaults
103
+ const dynamic = await fetch(url); // 15 default: NO CACHE
104
+ const static = await fetch(url, { cache: "force-cache" }); // Static
105
+ const isr = await fetch(url, { next: { revalidate: 3600 } }); // Revalidate every hour
106
+ const tagged = await fetch(url, { next: { tags: ["user-1"] } }); // On-demand via revalidateTag()
269
107
 
270
- // Cache database queries that don't use fetch()
108
+ // DB calls without fetch
109
+ import { unstable_cache } from "next/cache";
271
110
  const getCachedUser = unstable_cache(
272
- async (userId: string) => {
273
- return await db.user.findUnique({ where: { id: userId } });
274
- },
275
- ["user-by-id"], // cache key parts
276
- {
277
- revalidate: 3600, // 1 hour
278
- tags: ["user"], // for on-demand revalidation
279
- }
111
+ async (id) => db.user.findUnique({ where: { id } }),
112
+ ["user-cache-key"],
113
+ { revalidate: 60, tags: ["users"] }
280
114
  );
281
-
282
- // Usage:
283
- const user = await getCachedUser("abc123");
284
- ```
285
-
286
- ---
287
-
288
- ## Waterfall Elimination
289
-
290
- ### The Problem
291
-
292
- ```tsx
293
- // ❌ CRITICAL WATERFALL: Each await blocks the next
294
- async function Dashboard() {
295
- const user = await getUser(); // 200ms
296
- const posts = await getPosts(); // 200ms (waits for user)
297
- const analytics = await getAnalytics(); // 200ms (waits for posts)
298
- // Total: 600ms sequential
299
- }
300
115
  ```
301
116
 
302
- ### Fix 1: Parallel Fetching
303
-
117
+ ### Waterfall Elimination
304
118
  ```tsx
305
- // ✅ All three start simultaneously
306
- async function Dashboard() {
307
- const [user, posts, analytics] = await Promise.all([
308
- getUser(),
309
- getPosts(),
310
- getAnalytics(),
311
- ]);
312
- // Total: ~200ms (time of slowest call)
313
- }
314
- ```
315
-
316
- ### Fix 2: Streaming with Suspense (Pro-Max)
119
+ // ✅ Parallel Fetching:
120
+ const [user, posts] = await Promise.all([getUser(), getPosts()]);
317
121
 
318
- ```tsx
319
- // 🚀 Show fast content immediately, stream slow content later
320
- export default function Dashboard() {
122
+ // ✅ Streaming (PPR-compatible):
123
+ export default function Page() {
321
124
  return (
322
125
  <main>
323
- <FastHeader /> {/* renders instantly — static */}
324
-
325
- <Suspense fallback={<StatsSkeleton />}>
326
- <SlowStatsPanel /> {/* streams when DB resolves */}
327
- </Suspense>
328
-
329
- <Suspense fallback={<ChartSkeleton />}>
330
- <VerySlowChart /> {/* streams when API resolves */}
126
+ <FastNav />
127
+ {/* Page shell loads instantly, SlowChart streams in when ready */}
128
+ <Suspense fallback={<Skeleton />}>
129
+ <SlowChart />
331
130
  </Suspense>
332
131
  </main>
333
132
  );
334
133
  }
335
-
336
- // Each Suspense boundary independently streams its content
337
- // The user sees the page progressively — not a blank screen
338
134
  ```
339
135
 
340
136
  ---
341
137
 
342
138
  ## Partial Prerendering (PPR)
343
139
 
140
+ PPR static-generates the route shell and streams dynamic parts.
344
141
  ```tsx
345
142
  // next.config.ts
346
- export default {
347
- experimental: {
348
- ppr: true, // Enable Partial Prerendering
349
- },
350
- };
143
+ export default { experimental: { ppr: true } };
351
144
 
352
- // PPR = Static shell (edge-cached) + Dynamic holes (streamed)
353
- // The static parts are served from CDN at edge speed
354
- // Dynamic parts stream in from the server
145
+ // Any component reading cookies/headers inside a Suspense boundary becomes a dynamic hole
146
+ import { cookies } from "next/headers";
355
147
 
356
- export default function ProductPage({ params }: { params: { id: string } }) {
357
- return (
358
- <main>
359
- {/* 🟢 STATIC — pre-rendered at build time, served from CDN */}
360
- <Header />
361
- <ProductDetails id={params.id} />
148
+ async function Cart() {
149
+ const c = await cookies(); // Next.js 15 cookies are async!
150
+ const cartId = c.get("cartId");
151
+ }
362
152
 
363
- {/* 🔴 DYNAMIC — streamed on request (requires cookies/headers) */}
153
+ export default function Page() {
154
+ return (
155
+ <div>
156
+ <StaticHeader /> {/* Cached at build time on CDN */}
364
157
  <Suspense fallback={<CartSkeleton />}>
365
- <PersonalizedCart /> {/* reads cookies() dynamic */}
158
+ <Cart /> {/* Dynamic, streamed at request time */}
366
159
  </Suspense>
367
-
368
- <Suspense fallback={<ReviewsSkeleton />}>
369
- <LiveReviews /> {/* real-time data — dynamic */}
370
- </Suspense>
371
- </main>
372
- );
373
- }
374
-
375
- // ❌ HALLUCINATION TRAP: Using cookies(), headers(), or searchParams at the
376
- // top level of a component tree forces the ENTIRE route to be dynamic.
377
- // Isolate dynamic data inside Suspense boundaries for PPR to work.
378
- ```
379
-
380
- ---
381
-
382
- ## Metadata & SEO
383
-
384
- ### `generateMetadata` (Dynamic)
385
-
386
- ```tsx
387
- import { Metadata } from "next";
388
-
389
- // Static metadata
390
- export const metadata: Metadata = {
391
- title: "My App",
392
- description: "The best app ever",
393
- openGraph: { title: "My App", description: "...", images: ["/og.png"] },
394
- };
395
-
396
- // Dynamic metadata (based on params/data)
397
- export async function generateMetadata({
398
- params,
399
- }: {
400
- params: { slug: string };
401
- }): Promise<Metadata> {
402
- const post = await getPost(params.slug);
403
-
404
- return {
405
- title: post.title,
406
- description: post.excerpt,
407
- openGraph: {
408
- title: post.title,
409
- description: post.excerpt,
410
- images: [post.coverImage],
411
- },
412
- twitter: {
413
- card: "summary_large_image",
414
- title: post.title,
415
- },
416
- alternates: {
417
- canonical: `https://example.com/blog/${params.slug}`,
418
- },
419
- };
420
- }
421
-
422
- // ❌ HALLUCINATION TRAP: generateMetadata is an async function exported
423
- // from page.tsx or layout.tsx — NOT a React component.
424
- // It runs on the server during rendering.
425
- ```
426
-
427
- ### `generateStaticParams` (Static Generation)
428
-
429
- ```tsx
430
- // Pre-generate pages at build time (SSG)
431
- export async function generateStaticParams() {
432
- const posts = await getAllPosts();
433
-
434
- return posts.map((post) => ({
435
- slug: post.slug, // matches [slug] dynamic segment
436
- }));
437
- }
438
-
439
- // Combined with dynamicParams:
440
- export const dynamicParams = false; // 404 for unknown slugs
441
- // OR
442
- export const dynamicParams = true; // generate on-demand (default)
443
- ```
444
-
445
- ---
446
-
447
- ## Route Handlers (API Routes)
448
-
449
- ```tsx
450
- // app/api/users/route.ts
451
- import { NextRequest, NextResponse } from "next/server";
452
-
453
- export async function GET(request: NextRequest) {
454
- const searchParams = request.nextUrl.searchParams;
455
- const page = searchParams.get("page") ?? "1";
456
-
457
- const users = await db.user.findMany({
458
- skip: (parseInt(page) - 1) * 20,
459
- take: 20,
460
- });
461
-
462
- return NextResponse.json(users);
463
- }
464
-
465
- export async function POST(request: NextRequest) {
466
- const body = await request.json();
467
-
468
- // Always validate input
469
- const parsed = UserSchema.safeParse(body);
470
- if (!parsed.success) {
471
- return NextResponse.json(
472
- { error: parsed.error.flatten() },
473
- { status: 400 }
474
- );
475
- }
476
-
477
- const user = await db.user.create({ data: parsed.data });
478
- return NextResponse.json(user, { status: 201 });
479
- }
480
-
481
- // Dynamic route: app/api/users/[id]/route.ts
482
- export async function GET(
483
- request: NextRequest,
484
- { params }: { params: { id: string } }
485
- ) {
486
- const user = await db.user.findUnique({ where: { id: params.id } });
487
- if (!user) {
488
- return NextResponse.json({ error: "Not found" }, { status: 404 });
489
- }
490
- return NextResponse.json(user);
160
+ </div>
161
+ )
491
162
  }
492
-
493
- // ❌ HALLUCINATION TRAP: Route handlers use named exports (GET, POST, PUT, DELETE)
494
- // NOT default export. NOT export function handler().
495
- // ❌ HALLUCINATION TRAP: Route handlers are in route.ts, NOT in page.tsx
496
- // A directory cannot have both page.tsx and route.ts
497
163
  ```
498
164
 
499
165
  ---
500
166
 
501
167
  ## Middleware
502
168
 
503
- ```tsx
504
- // middleware.ts (in project ROOT, not inside app/)
169
+ ```typescript
170
+ // middleware.ts (Root of project)
505
171
  import { NextResponse } from "next/server";
506
172
  import type { NextRequest } from "next/server";
507
173
 
508
- export function middleware(request: NextRequest) {
509
- const token = request.cookies.get("session")?.value;
510
- const { pathname } = request.nextUrl;
511
-
512
- // Redirect unauthenticated users
513
- if (pathname.startsWith("/dashboard") && !token) {
514
- return NextResponse.redirect(new URL("/login", request.url));
174
+ export function middleware(req: NextRequest) {
175
+ const token = req.cookies.get("auth-token");
176
+ if (!token && req.nextUrl.pathname.startsWith("/dashboard")) {
177
+ return NextResponse.redirect(new URL("/login", req.url));
515
178
  }
516
-
517
- // Add custom headers
518
- const response = NextResponse.next();
519
- response.headers.set("x-pathname", pathname);
520
-
521
- return response;
522
179
  }
523
180
 
524
- // Matcher: only run middleware on specific routes
525
181
  export const config = {
526
- matcher: [
527
- "/dashboard/:path*",
528
- "/api/:path*",
529
- // Skip static files and Next.js internals
530
- "/((?!_next/static|_next/image|favicon.ico).*)",
531
- ],
182
+ matcher: ["/dashboard/:path*"], // Strict matcher is critical for performance
532
183
  };
533
-
534
- // ❌ HALLUCINATION TRAP: middleware.ts must be at the project ROOT
535
- // (same level as app/ directory), NOT inside app/
536
- // ❌ HALLUCINATION TRAP: Middleware runs on the Edge Runtime
537
- // You CANNOT use Node.js APIs (fs, crypto.createHash, etc.)
538
- // Use Web APIs (crypto.subtle, fetch, Response, Headers)
539
- ```
540
-
541
- ---
542
-
543
- ## Parallel & Intercepting Routes
544
-
545
- ### Parallel Routes (Named Slots)
546
-
547
- ```
548
- app/
549
- ├── layout.tsx
550
- ├── page.tsx
551
- ├── @analytics/
552
- │ └── page.tsx ← Rendered in parallel with main page
553
- └── @notifications/
554
- └── page.tsx ← Also rendered in parallel
555
- ```
556
-
557
- ```tsx
558
- // app/layout.tsx
559
- export default function Layout({
560
- children,
561
- analytics,
562
- notifications,
563
- }: {
564
- children: React.ReactNode;
565
- analytics: React.ReactNode;
566
- notifications: React.ReactNode;
567
- }) {
568
- return (
569
- <div>
570
- <main>{children}</main>
571
- <aside>{analytics}</aside>
572
- <div>{notifications}</div>
573
- </div>
574
- );
575
- }
576
- ```
577
-
578
- ### Intercepting Routes (Modal Pattern)
579
-
580
- ```
581
- app/
582
- ├── feed/
583
- │ └── page.tsx ← /feed (shows feed)
584
- ├── photo/[id]/
585
- │ └── page.tsx ← /photo/123 (full photo page)
586
- └── @modal/
587
- └── (..)photo/[id]/
588
- └── page.tsx ← Intercepts /photo/123 when navigating from /feed
589
- Shows as modal overlay instead of full page
590
- ```
591
-
592
184
  ```
593
- Intercepting conventions:
594
- (.) — same level
595
- (..) — one level up
596
- (..)(..) — two levels up
597
- (...) — from root
598
- ```
599
-
600
- ---
601
-
602
- ## AI & Streaming UI
603
-
604
- ```tsx
605
- import { openai } from "@ai-sdk/openai";
606
- import { streamText } from "ai";
607
-
608
- // app/api/chat/route.ts
609
- export async function POST(req: NextRequest) {
610
- const { messages } = await req.json();
611
-
612
- const result = streamText({
613
- model: openai("gpt-4o"),
614
- messages,
615
- });
616
-
617
- return result.toDataStreamResponse();
618
- }
619
-
620
- // Client component:
621
- "use client";
622
- import { useChat } from "@ai-sdk/react";
623
-
624
- function ChatUI() {
625
- const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat();
626
-
627
- return (
628
- <div>
629
- {messages.map((m) => (
630
- <div key={m.id} className={m.role === "user" ? "user" : "ai"}>
631
- {m.content}
632
- </div>
633
- ))}
634
- <form onSubmit={handleSubmit}>
635
- <input value={input} onChange={handleInputChange} />
636
- <button disabled={isLoading}>Send</button>
637
- </form>
638
- </div>
639
- );
640
- }
641
-
642
- // ❌ HALLUCINATION TRAP: Import from "@ai-sdk/react", NOT "ai/react"
643
- // The package was restructured in Vercel AI SDK 4+
644
- ```
645
-
646
- ---
647
-
648
- ## Bundle Optimization
649
-
650
- ```tsx
651
- // 1. Push "use client" as FAR DOWN as possible
652
- // ❌ BAD: "use client" on layout.tsx (ships entire layout as JS)
653
- // ✅ GOOD: "use client" only on the interactive widget component
654
-
655
- // 2. Dynamic imports for heavy client deps
656
- import dynamic from "next/dynamic";
657
-
658
- const HeavyChart = dynamic(() => import("./HeavyChart"), {
659
- ssr: false, // skip server rendering
660
- loading: () => <ChartSkeleton />,
661
- });
662
-
663
- // 3. next/image for automatic optimization
664
- import Image from "next/image";
665
-
666
- <Image
667
- src="/hero.jpg"
668
- alt="Hero image"
669
- width={1200}
670
- height={630}
671
- priority // preload for LCP images
672
- placeholder="blur"
673
- blurDataURL={blurUrl}
674
- />
675
-
676
- // 4. next/font for zero-layout-shift fonts
677
- import { Inter } from "next/font/google";
678
-
679
- const inter = Inter({
680
- subsets: ["latin"],
681
- display: "swap",
682
- variable: "--font-inter",
683
- });
684
-
685
- // In layout.tsx:
686
- <html className={inter.variable}>
687
- <body>{children}</body>
688
- </html>
689
-
690
- // ❌ HALLUCINATION TRAP: next/font automatically self-hosts fonts
691
- // Do NOT add Google Fonts <link> tags in <head> — they cause CLS
692
- ```
693
-
694
- ---
695
-
696
- ## Key Anti-Patterns
697
-
698
- | Pattern | Problem | Fix |
699
- |---|---|---|
700
- | `getServerSideProps` in App Router | Pages Router API — doesn't exist | Fetch directly in Server Components |
701
- | `"use client"` on layout/page | Ships massive JS bundle | Push `"use client"` to leaf components |
702
- | `useEffect(() => fetch(...))` | Client waterfall, no cache, CLS | Server Component or React Query |
703
- | Sequential `await` calls | Network waterfall | `Promise.all()` or `<Suspense>` |
704
- | `cookies()`/`headers()` at top level | Disables PPR for entire route | Isolate inside `<Suspense>` boundaries |
705
- | `next/router` (Pages Router) | Wrong import | Use `next/navigation` |
706
- | Missing `loading.tsx` | Blank screen during navigation | Add loading.tsx or Suspense |
707
- | Raw `<img>` and `<a>` tags | No optimization | Use `next/image` and `next/link` |
708
-
709
- ---
710
-
711
- ## Output Format
712
-
713
- When this skill produces or reviews code, structure your output as follows:
714
-
715
- ```
716
- ━━━ Next.js Expert Report ━━━━━━━━━━━━━━━━━━━━━━━━
717
- Skill: Next.js React Expert
718
- Next.js Ver: 15+
719
- Scope: [N files · N routes]
720
- ─────────────────────────────────────────────────
721
- ✅ Passed: [checks that passed, or "All clean"]
722
- ⚠️ Warnings: [non-blocking issues, or "None"]
723
- ❌ Blocked: [blocking issues requiring fix, or "None"]
724
- ─────────────────────────────────────────────────
725
- VBC status: PENDING → VERIFIED
726
- Evidence: [test output / lint pass / compile success]
727
- ```
728
-
729
- **VBC (Verification-Before-Completion) is mandatory.**
730
- Do not mark status as VERIFIED until concrete terminal evidence is provided.
731
-
732
- ---
733
-
734
- ## 🤖 LLM-Specific Traps
735
-
736
- AI coding assistants often fall into specific bad habits when generating Next.js code. These are strictly forbidden:
737
-
738
- 1. **Pages Router in App Router:** Never generate `getServerSideProps`, `getStaticProps`, `getInitialProps`, `_app.tsx`, `_document.tsx`, or `pages/api/` in an App Router project.
739
- 2. **`"use client"` Everywhere:** Marking layouts, pages, or entire feature modules as client components defeats RSC. Push the `"use client"` boundary as deep as possible.
740
- 3. **`next/router` Import:** The Pages Router `useRouter` is `next/router`. App Router uses `next/navigation`. Using the wrong one causes runtime errors.
741
- 4. **Missing Input Validation in Server Actions:** Server Actions receive raw `FormData` from the client. Always validate with Zod or similar before touching the database.
742
- 5. **`useEffect` for Data Fetching:** Server Components can fetch directly. Client components should use React Query or SWR. `useEffect` fetch has no caching, no deduplication, no error boundaries.
743
- 6. **Forgetting Next.js 15 Cache Changes:** In Next.js 15, `fetch()` is NOT cached by default (changed from 14). You must explicitly opt into caching.
744
- 7. **Google Fonts `<link>` Tags:** Never add external font `<link>` tags. Use `next/font` for zero-CLS, self-hosted fonts.
745
- 8. **Route Handler Default Exports:** Route handlers use named exports (`GET`, `POST`, `DELETE`), not `export default function handler`.
746
- 9. **Middleware Inside `app/`:** `middleware.ts` must be at the project root, not inside the `app/` directory.
747
- 10. **`"ai/react"` Import Path:** The Vercel AI SDK restructured its exports. Use `@ai-sdk/react` for hooks and `ai` for core.
748
-
749
- ---
750
-
751
- ## 🏛️ Tribunal Integration (Anti-Hallucination)
752
-
753
- **Slash command: `/tribunal-frontend`**
754
- **Active reviewers: `logic` · `security` · `frontend` · `type-safety`**
755
-
756
- ### ❌ Forbidden AI Tropes
757
-
758
- 1. **Blind Assumptions:** Never make an assumption without documenting it clearly with `// VERIFY: [reason]`.
759
- 2. **Silent Degradation:** Catching and suppressing errors without logging or displaying error boundaries.
760
- 3. **Context Amnesia:** Forgetting whether the project uses Pages Router or App Router.
761
- 4. **Generic Design:** Do not default to black/white Vercel aesthetics unless instructed.
762
-
763
- ### ✅ Pre-Flight Self-Audit
764
-
765
- Review these questions before confirming output:
766
- ```
767
- ✅ Did I maximize Server Component usage and isolate "use client"?
768
- ✅ Are there sequential awaits creating a waterfall? Did I use Promise.all or Suspense?
769
- ✅ Did I validate all Server Action inputs with Zod?
770
- ✅ Did I use next/image and next/link (not raw <img> and <a>)?
771
- ✅ Did I implement loading.tsx and error.tsx for route segments?
772
- ✅ Did I use next/font (not external font <link> tags)?
773
- ✅ Did I use next/navigation (not next/router)?
774
- ✅ Are dynamic data reads (cookies, headers) inside Suspense for PPR?
775
- ✅ Did I add generateMetadata for SEO?
776
- ✅ Is middleware.ts at the project root (not inside app/)?
777
- ```
778
-
779
- ### 🛑 Verification-Before-Completion (VBC) Protocol
780
-
781
- **CRITICAL:** You must follow a strict "evidence-based closeout" state machine.
782
- - ❌ **Forbidden:** Assuming a Next.js route "works" because the dev server shows no errors.
783
- - ✅ **Required:** You are explicitly forbidden from completing your task without providing **concrete evidence** (successful `next build`, passing tests, or equivalent proof) that the code compiles and runs correctly.