@kood/claude-code 0.3.6 → 0.3.8

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 (120) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +1 -1
  3. package/templates/.claude/agents/code-reviewer.md +124 -124
  4. package/templates/.claude/agents/dependency-manager.md +85 -85
  5. package/templates/.claude/agents/deployment-validator.md +56 -56
  6. package/templates/.claude/agents/git-operator.md +64 -64
  7. package/templates/.claude/agents/implementation-executor.md +95 -95
  8. package/templates/.claude/agents/ko-to-en-translator.md +74 -0
  9. package/templates/.claude/agents/lint-fixer.md +78 -78
  10. package/templates/.claude/agents/refactor-advisor.md +122 -122
  11. package/templates/.claude/commands/agent-creator.md +185 -185
  12. package/templates/.claude/commands/bug-fix.md +193 -193
  13. package/templates/.claude/commands/command-creator.md +54 -54
  14. package/templates/.claude/commands/docs-creator.md +57 -57
  15. package/templates/.claude/commands/docs-refactor.md +26 -26
  16. package/templates/.claude/commands/execute.md +12 -12
  17. package/templates/.claude/commands/git-all.md +32 -32
  18. package/templates/.claude/commands/git-session.md +42 -42
  19. package/templates/.claude/commands/git.md +34 -34
  20. package/templates/.claude/commands/lint-fix.md +138 -138
  21. package/templates/.claude/commands/lint-init.md +61 -61
  22. package/templates/.claude/commands/plan.md +260 -260
  23. package/templates/.claude/commands/prd.md +24 -24
  24. package/templates/.claude/commands/pre-deploy.md +109 -109
  25. package/templates/.claude/commands/refactor.md +147 -147
  26. package/templates/.claude/commands/version-update.md +17 -17
  27. package/templates/hono/CLAUDE.md +27 -27
  28. package/templates/hono/docs/architecture.md +24 -24
  29. package/templates/hono/docs/deployment/cloudflare.md +18 -18
  30. package/templates/hono/docs/deployment/docker.md +13 -13
  31. package/templates/hono/docs/deployment/index.md +19 -19
  32. package/templates/hono/docs/deployment/railway.md +32 -32
  33. package/templates/hono/docs/deployment/vercel.md +29 -29
  34. package/templates/hono/docs/guides/conventions.md +57 -57
  35. package/templates/hono/docs/guides/env-setup.md +47 -47
  36. package/templates/hono/docs/guides/getting-started.md +27 -27
  37. package/templates/hono/docs/library/hono/error-handling.md +11 -11
  38. package/templates/hono/docs/library/hono/index.md +4 -4
  39. package/templates/hono/docs/library/hono/middleware.md +18 -18
  40. package/templates/hono/docs/library/hono/rpc.md +7 -7
  41. package/templates/hono/docs/library/hono/validation.md +6 -6
  42. package/templates/hono/docs/library/prisma/cloudflare-d1.md +29 -29
  43. package/templates/hono/docs/library/prisma/config.md +16 -16
  44. package/templates/hono/docs/library/prisma/index.md +32 -32
  45. package/templates/hono/docs/library/t3-env/index.md +22 -22
  46. package/templates/hono/docs/library/zod/index.md +31 -31
  47. package/templates/nextjs/CLAUDE.md +228 -0
  48. package/templates/nextjs/docs/design.md +558 -0
  49. package/templates/nextjs/docs/guides/conventions.md +343 -0
  50. package/templates/nextjs/docs/guides/getting-started.md +367 -0
  51. package/templates/nextjs/docs/guides/routes.md +342 -0
  52. package/templates/nextjs/docs/library/better-auth/index.md +541 -0
  53. package/templates/nextjs/docs/library/nextjs/app-router.md +269 -0
  54. package/templates/nextjs/docs/library/nextjs/caching.md +351 -0
  55. package/templates/nextjs/docs/library/nextjs/index.md +291 -0
  56. package/templates/nextjs/docs/library/nextjs/middleware.md +391 -0
  57. package/templates/nextjs/docs/library/nextjs/route-handlers.md +382 -0
  58. package/templates/nextjs/docs/library/nextjs/server-actions.md +366 -0
  59. package/templates/nextjs/docs/library/prisma/cloudflare-d1.md +76 -0
  60. package/templates/nextjs/docs/library/prisma/config.md +77 -0
  61. package/templates/nextjs/docs/library/prisma/crud.md +90 -0
  62. package/templates/nextjs/docs/library/prisma/index.md +73 -0
  63. package/templates/nextjs/docs/library/prisma/relations.md +69 -0
  64. package/templates/nextjs/docs/library/prisma/schema.md +98 -0
  65. package/templates/nextjs/docs/library/prisma/setup.md +49 -0
  66. package/templates/nextjs/docs/library/prisma/transactions.md +50 -0
  67. package/templates/nextjs/docs/library/tanstack-query/index.md +66 -0
  68. package/templates/nextjs/docs/library/tanstack-query/invalidation.md +54 -0
  69. package/templates/nextjs/docs/library/tanstack-query/optimistic-updates.md +77 -0
  70. package/templates/nextjs/docs/library/tanstack-query/use-mutation.md +63 -0
  71. package/templates/nextjs/docs/library/tanstack-query/use-query.md +70 -0
  72. package/templates/nextjs/docs/library/zod/complex-types.md +61 -0
  73. package/templates/nextjs/docs/library/zod/index.md +56 -0
  74. package/templates/nextjs/docs/library/zod/transforms.md +51 -0
  75. package/templates/nextjs/docs/library/zod/validation.md +70 -0
  76. package/templates/npx/CLAUDE.md +37 -37
  77. package/templates/npx/docs/library/commander/index.md +12 -12
  78. package/templates/npx/docs/library/fs-extra/index.md +9 -9
  79. package/templates/npx/docs/library/prompts/index.md +3 -3
  80. package/templates/npx/docs/references/patterns.md +12 -12
  81. package/templates/tanstack-start/CLAUDE.md +53 -49
  82. package/templates/tanstack-start/docs/architecture.md +128 -128
  83. package/templates/tanstack-start/docs/design.md +169 -169
  84. package/templates/tanstack-start/docs/guides/conventions.md +43 -43
  85. package/templates/tanstack-start/docs/guides/env-setup.md +35 -35
  86. package/templates/tanstack-start/docs/guides/getting-started.md +19 -19
  87. package/templates/tanstack-start/docs/guides/hooks.md +63 -35
  88. package/templates/tanstack-start/docs/guides/routes.md +61 -42
  89. package/templates/tanstack-start/docs/guides/services.md +45 -45
  90. package/templates/tanstack-start/docs/library/better-auth/index.md +68 -68
  91. package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +19 -19
  92. package/templates/tanstack-start/docs/library/prisma/config.md +16 -16
  93. package/templates/tanstack-start/docs/library/prisma/crud.md +17 -17
  94. package/templates/tanstack-start/docs/library/prisma/index.md +17 -17
  95. package/templates/tanstack-start/docs/library/prisma/relations.md +16 -16
  96. package/templates/tanstack-start/docs/library/prisma/schema.md +23 -23
  97. package/templates/tanstack-start/docs/library/prisma/setup.md +6 -6
  98. package/templates/tanstack-start/docs/library/prisma/transactions.md +10 -10
  99. package/templates/tanstack-start/docs/library/t3-env/index.md +21 -160
  100. package/templates/tanstack-start/docs/library/tanstack-query/index.md +6 -6
  101. package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +19 -19
  102. package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +4 -4
  103. package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +14 -14
  104. package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +21 -21
  105. package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +9 -9
  106. package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +11 -11
  107. package/templates/tanstack-start/docs/library/tanstack-router/index.md +18 -18
  108. package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +17 -17
  109. package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +5 -5
  110. package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +10 -10
  111. package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +8 -8
  112. package/templates/tanstack-start/docs/library/tanstack-start/index.md +15 -15
  113. package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +9 -9
  114. package/templates/tanstack-start/docs/library/tanstack-start/routing.md +6 -6
  115. package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +18 -18
  116. package/templates/tanstack-start/docs/library/tanstack-start/setup.md +4 -4
  117. package/templates/tanstack-start/docs/library/zod/complex-types.md +11 -11
  118. package/templates/tanstack-start/docs/library/zod/index.md +8 -8
  119. package/templates/tanstack-start/docs/library/zod/transforms.md +11 -11
  120. package/templates/tanstack-start/docs/library/zod/validation.md +9 -9
@@ -0,0 +1,291 @@
1
+ # Next.js - Index
2
+
3
+ > Next.js 15 App Router core concepts
4
+
5
+ <context>
6
+ @app-router.md
7
+ @server-actions.md
8
+ @route-handlers.md
9
+ @middleware.md
10
+ @caching.md
11
+ </context>
12
+
13
+ ---
14
+
15
+ ## Core Concepts
16
+
17
+ | Concept | Description |
18
+ |---------|-------------|
19
+ | **App Router** | File-based routing (`app/` directory) |
20
+ | **Server Components** | Default components (server rendering) |
21
+ | **Client Components** | Requires `"use client"` declaration |
22
+ | **Server Actions** | `"use server"` functions (type-safe API) |
23
+ | **Route Handlers** | REST API endpoints (`app/api/`) |
24
+
25
+ ---
26
+
27
+ ## Quick Start
28
+
29
+ ### Create Project
30
+
31
+ ```bash
32
+ npx create-next-app@latest my-app --typescript --tailwind --app
33
+ cd my-app
34
+ npm run dev
35
+ ```
36
+
37
+ ### Basic Page
38
+
39
+ ```typescript
40
+ // app/page.tsx (Server Component - default)
41
+ export default async function HomePage() {
42
+ const data = await fetch('https://api.example.com/data')
43
+ const json = await data.json()
44
+
45
+ return <div>{json.title}</div>
46
+ }
47
+ ```
48
+
49
+ ### Client Component
50
+
51
+ ```typescript
52
+ // app/_components/counter.tsx
53
+ "use client"
54
+
55
+ import { useState } from "react"
56
+
57
+ export function Counter() {
58
+ const [count, setCount] = useState(0)
59
+ return <button onClick={() => setCount(count + 1)}>{count}</button>
60
+ }
61
+ ```
62
+
63
+ ---
64
+
65
+ ## File Structure
66
+
67
+ ```
68
+ app/
69
+ ├── layout.tsx # Root layout (required)
70
+ ├── page.tsx # Home (/)
71
+ ├── about/
72
+ │ └── page.tsx # /about
73
+ ├── blog/
74
+ │ ├── page.tsx # /blog
75
+ │ └── [slug]/
76
+ │ └── page.tsx # /blog/:slug
77
+ └── api/
78
+ └── posts/
79
+ └── route.ts # API /api/posts
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Key Files
85
+
86
+ | File | Purpose |
87
+ |------|---------|
88
+ | `layout.tsx` | Shared layout (nestable) |
89
+ | `page.tsx` | Page component |
90
+ | `loading.tsx` | Loading UI (Suspense) |
91
+ | `error.tsx` | Error UI (Error Boundary) |
92
+ | `not-found.tsx` | 404 page |
93
+ | `route.ts` | API endpoint |
94
+
95
+ ---
96
+
97
+ ## Server vs Client Components
98
+
99
+ | Aspect | Server | Client |
100
+ |--------|--------|--------|
101
+ | Declaration | Default | `"use client"` |
102
+ | Data Fetching | ✅ async/await | ❌ (use useQuery) |
103
+ | Hooks | ❌ | ✅ useState, useEffect |
104
+ | Browser API | ❌ | ✅ window, localStorage |
105
+ | Event Handlers | ❌ | ✅ onClick, onChange |
106
+
107
+ **Rules:**
108
+ - Server Components are default → add `"use client"` only when needed
109
+ - Server Components can contain Client Components
110
+ - Client Components cannot contain Server Components (but can receive them as props)
111
+
112
+ ---
113
+
114
+ ## Server Actions
115
+
116
+ ```typescript
117
+ // app/actions.ts
118
+ "use server"
119
+
120
+ import { z } from "zod"
121
+ import { revalidatePath } from "next/cache"
122
+
123
+ const schema = z.object({
124
+ title: z.string().min(1),
125
+ content: z.string(),
126
+ })
127
+
128
+ export async function createPost(formData: FormData) {
129
+ const parsed = schema.parse({
130
+ title: formData.get("title"),
131
+ content: formData.get("content"),
132
+ })
133
+
134
+ const post = await prisma.post.create({ data: parsed })
135
+ revalidatePath("/posts")
136
+ return post
137
+ }
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Route Handlers
143
+
144
+ ```typescript
145
+ // app/api/posts/route.ts
146
+ import { NextRequest, NextResponse } from "next/server"
147
+
148
+ export async function GET(request: NextRequest) {
149
+ const posts = await prisma.post.findMany()
150
+ return NextResponse.json(posts)
151
+ }
152
+
153
+ export async function POST(request: NextRequest) {
154
+ const body = await request.json()
155
+ const post = await prisma.post.create({ data: body })
156
+ return NextResponse.json(post, { status: 201 })
157
+ }
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Middleware
163
+
164
+ ```typescript
165
+ // middleware.ts
166
+ import { NextResponse } from "next/server"
167
+ import type { NextRequest } from "next/server"
168
+
169
+ export function middleware(request: NextRequest) {
170
+ const token = request.cookies.get("token")
171
+
172
+ if (!token) {
173
+ return NextResponse.redirect(new URL("/login", request.url))
174
+ }
175
+
176
+ return NextResponse.next()
177
+ }
178
+
179
+ export const config = {
180
+ matcher: ["/dashboard/:path*", "/profile/:path*"],
181
+ }
182
+ ```
183
+
184
+ ---
185
+
186
+ ## Data Fetching
187
+
188
+ ### Server Component (recommended)
189
+
190
+ ```typescript
191
+ export default async function PostsPage() {
192
+ const posts = await prisma.post.findMany() // Direct DB access
193
+ return <PostsList posts={posts} />
194
+ }
195
+ ```
196
+
197
+ ### Client Component (TanStack Query)
198
+
199
+ ```typescript
200
+ "use client"
201
+
202
+ import { useQuery } from "@tanstack/react-query"
203
+
204
+ export function PostsList() {
205
+ const { data } = useQuery({
206
+ queryKey: ["posts"],
207
+ queryFn: () => fetch("/api/posts").then(r => r.json()),
208
+ })
209
+
210
+ return <ul>{data?.map(post => <li key={post.id}>{post.title}</li>)}</ul>
211
+ }
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Caching
217
+
218
+ | Function | Purpose |
219
+ |----------|---------|
220
+ | `revalidatePath("/posts")` | Invalidate specific path cache |
221
+ | `revalidateTag("posts")` | Invalidate tag-based cache |
222
+ | `unstable_cache()` | Cache function results |
223
+
224
+ ```typescript
225
+ import { revalidatePath, revalidateTag } from "next/cache"
226
+
227
+ export async function createPost(data: PostInput) {
228
+ const post = await prisma.post.create({ data })
229
+
230
+ revalidatePath("/posts") // Invalidate /posts cache
231
+ revalidateTag("posts") // Invalidate "posts" tag cache
232
+
233
+ return post
234
+ }
235
+ ```
236
+
237
+ ---
238
+
239
+ ## Environment Variables
240
+
241
+ ```bash
242
+ # .env.local
243
+ DATABASE_URL="postgresql://..."
244
+ NEXTAUTH_SECRET="..."
245
+ NEXTAUTH_URL="http://localhost:3000"
246
+ NEXT_PUBLIC_API_URL="https://api.example.com"
247
+ ```
248
+
249
+ **Rules:**
250
+ - `NEXT_PUBLIC_*`: Accessible in client
251
+ - Others: Server-only
252
+
253
+ ---
254
+
255
+ ## Deployment
256
+
257
+ ### Vercel (recommended)
258
+
259
+ ```bash
260
+ npm i -g vercel
261
+ vercel
262
+ ```
263
+
264
+ ### Docker
265
+
266
+ ```dockerfile
267
+ FROM node:20-alpine
268
+ WORKDIR /app
269
+ COPY package*.json ./
270
+ RUN npm ci
271
+ COPY . .
272
+ RUN npm run build
273
+ CMD ["npm", "start"]
274
+ ```
275
+
276
+ ### Node.js
277
+
278
+ ```bash
279
+ npm run build
280
+ npm start
281
+ ```
282
+
283
+ ---
284
+
285
+ ## References
286
+
287
+ - [App Router](app-router.md)
288
+ - [Server Actions](server-actions.md)
289
+ - [Route Handlers](route-handlers.md)
290
+ - [Middleware](middleware.md)
291
+ - [Caching](caching.md)
@@ -0,0 +1,391 @@
1
+ # Middleware
2
+
3
+ > Functions executed before request processing
4
+
5
+ ---
6
+
7
+ ## Basic Usage
8
+
9
+ ```typescript
10
+ // middleware.ts (root)
11
+ import { NextResponse } from "next/server"
12
+ import type { NextRequest } from "next/server"
13
+
14
+ export function middleware(request: NextRequest) {
15
+ // Execute logic...
16
+ return NextResponse.next()
17
+ }
18
+
19
+ // Matcher configuration
20
+ export const config = {
21
+ matcher: ["/dashboard/:path*", "/api/:path*"],
22
+ }
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Response Types
28
+
29
+ ### NextResponse.next()
30
+
31
+ ```typescript
32
+ // Pass request to next middleware or route
33
+ export function middleware(request: NextRequest) {
34
+ return NextResponse.next()
35
+ }
36
+ ```
37
+
38
+ ### NextResponse.redirect()
39
+
40
+ ```typescript
41
+ // Redirect to different URL
42
+ export function middleware(request: NextRequest) {
43
+ return NextResponse.redirect(new URL("/login", request.url))
44
+ }
45
+ ```
46
+
47
+ ### NextResponse.rewrite()
48
+
49
+ ```typescript
50
+ // Render different page while keeping URL
51
+ export function middleware(request: NextRequest) {
52
+ return NextResponse.rewrite(new URL("/dashboard/home", request.url))
53
+ }
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Authentication
59
+
60
+ ```typescript
61
+ import { NextResponse } from "next/server"
62
+ import type { NextRequest } from "next/server"
63
+
64
+ export function middleware(request: NextRequest) {
65
+ const token = request.cookies.get("token")
66
+
67
+ // Redirect to login if no token
68
+ if (!token) {
69
+ return NextResponse.redirect(new URL("/login", request.url))
70
+ }
71
+
72
+ return NextResponse.next()
73
+ }
74
+
75
+ export const config = {
76
+ matcher: ["/dashboard/:path*", "/profile/:path*"],
77
+ }
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Cookie Handling
83
+
84
+ ### Reading
85
+
86
+ ```typescript
87
+ export function middleware(request: NextRequest) {
88
+ const token = request.cookies.get("token")
89
+ const userId = request.cookies.get("userId")
90
+
91
+ console.log({ token, userId })
92
+
93
+ return NextResponse.next()
94
+ }
95
+ ```
96
+
97
+ ### Setting
98
+
99
+ ```typescript
100
+ export function middleware(request: NextRequest) {
101
+ const response = NextResponse.next()
102
+
103
+ response.cookies.set("visited", "true", {
104
+ httpOnly: true,
105
+ secure: true,
106
+ maxAge: 60 * 60 * 24 * 7, // 7 days
107
+ })
108
+
109
+ return response
110
+ }
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Headers Handling
116
+
117
+ ### Reading
118
+
119
+ ```typescript
120
+ export function middleware(request: NextRequest) {
121
+ const userAgent = request.headers.get("user-agent")
122
+ const authorization = request.headers.get("authorization")
123
+
124
+ console.log({ userAgent, authorization })
125
+
126
+ return NextResponse.next()
127
+ }
128
+ ```
129
+
130
+ ### Setting
131
+
132
+ ```typescript
133
+ export function middleware(request: NextRequest) {
134
+ const response = NextResponse.next()
135
+
136
+ response.headers.set("X-Custom-Header", "value")
137
+ response.headers.set("X-Request-Id", crypto.randomUUID())
138
+
139
+ return response
140
+ }
141
+ ```
142
+
143
+ ---
144
+
145
+ ## Path-based Processing
146
+
147
+ ```typescript
148
+ export function middleware(request: NextRequest) {
149
+ const { pathname } = request.nextUrl
150
+
151
+ // /api/* routes
152
+ if (pathname.startsWith("/api/")) {
153
+ const token = request.headers.get("authorization")
154
+
155
+ if (!token) {
156
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 })
157
+ }
158
+ }
159
+
160
+ // /admin/* routes
161
+ if (pathname.startsWith("/admin/")) {
162
+ const role = request.cookies.get("role")?.value
163
+
164
+ if (role !== "admin") {
165
+ return NextResponse.redirect(new URL("/", request.url))
166
+ }
167
+ }
168
+
169
+ return NextResponse.next()
170
+ }
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Matcher Configuration
176
+
177
+ ### Array
178
+
179
+ ```typescript
180
+ export const config = {
181
+ matcher: ["/dashboard/:path*", "/profile/:path*"],
182
+ }
183
+ ```
184
+
185
+ ### Regex
186
+
187
+ ```typescript
188
+ export const config = {
189
+ matcher: [
190
+ /*
191
+ * Exclude paths:
192
+ * - _next/static (static files)
193
+ * - _next/image (image optimization)
194
+ * - favicon.ico (favicon)
195
+ */
196
+ "/((?!_next/static|_next/image|favicon.ico).*)",
197
+ ],
198
+ }
199
+ ```
200
+
201
+ ### Conditional
202
+
203
+ ```typescript
204
+ export const config = {
205
+ matcher: [
206
+ "/dashboard/:path*",
207
+ {
208
+ source: "/api/:path*",
209
+ has: [
210
+ { type: "header", key: "authorization" },
211
+ ],
212
+ },
213
+ ],
214
+ }
215
+ ```
216
+
217
+ ---
218
+
219
+ ## Logging
220
+
221
+ ```typescript
222
+ export function middleware(request: NextRequest) {
223
+ const start = Date.now()
224
+
225
+ const response = NextResponse.next()
226
+
227
+ const duration = Date.now() - start
228
+
229
+ console.log({
230
+ method: request.method,
231
+ url: request.url,
232
+ duration: `${duration}ms`,
233
+ status: response.status,
234
+ })
235
+
236
+ return response
237
+ }
238
+ ```
239
+
240
+ ---
241
+
242
+ ## Rate Limiting
243
+
244
+ ```typescript
245
+ import { NextResponse } from "next/server"
246
+ import type { NextRequest } from "next/server"
247
+
248
+ const rateLimit = new Map<string, { count: number; resetAt: number }>()
249
+
250
+ const LIMIT = 10 // 10 requests
251
+ const WINDOW = 60 * 1000 // 1 minute
252
+
253
+ export function middleware(request: NextRequest) {
254
+ const ip = request.ip || "unknown"
255
+ const now = Date.now()
256
+
257
+ const record = rateLimit.get(ip)
258
+
259
+ if (!record || now > record.resetAt) {
260
+ rateLimit.set(ip, { count: 1, resetAt: now + WINDOW })
261
+ return NextResponse.next()
262
+ }
263
+
264
+ if (record.count >= LIMIT) {
265
+ return NextResponse.json(
266
+ { error: "Too many requests" },
267
+ { status: 429 }
268
+ )
269
+ }
270
+
271
+ record.count++
272
+ return NextResponse.next()
273
+ }
274
+
275
+ export const config = {
276
+ matcher: "/api/:path*",
277
+ }
278
+ ```
279
+
280
+ ---
281
+
282
+ ## Geolocation
283
+
284
+ ```typescript
285
+ export function middleware(request: NextRequest) {
286
+ const country = request.geo?.country || "US"
287
+ const city = request.geo?.city || "Unknown"
288
+
289
+ const response = NextResponse.next()
290
+ response.headers.set("X-Country", country)
291
+ response.headers.set("X-City", city)
292
+
293
+ return response
294
+ }
295
+ ```
296
+
297
+ ---
298
+
299
+ ## A/B Testing
300
+
301
+ ```typescript
302
+ import { NextResponse } from "next/server"
303
+ import type { NextRequest } from "next/server"
304
+
305
+ export function middleware(request: NextRequest) {
306
+ const bucket = request.cookies.get("bucket")
307
+
308
+ if (!bucket) {
309
+ const newBucket = Math.random() > 0.5 ? "A" : "B"
310
+ const response = NextResponse.next()
311
+
312
+ response.cookies.set("bucket", newBucket)
313
+
314
+ if (newBucket === "B") {
315
+ return NextResponse.rewrite(new URL("/variant-b", request.url))
316
+ }
317
+
318
+ return response
319
+ }
320
+
321
+ if (bucket.value === "B") {
322
+ return NextResponse.rewrite(new URL("/variant-b", request.url))
323
+ }
324
+
325
+ return NextResponse.next()
326
+ }
327
+
328
+ export const config = {
329
+ matcher: "/",
330
+ }
331
+ ```
332
+
333
+ ---
334
+
335
+ ## Best Practices
336
+
337
+ ### ✅ DO
338
+
339
+ ```typescript
340
+ // 1. Keep logic lightweight
341
+ export function middleware(request: NextRequest) {
342
+ const token = request.cookies.get("token")
343
+
344
+ if (!token) {
345
+ return NextResponse.redirect(new URL("/login", request.url))
346
+ }
347
+
348
+ return NextResponse.next()
349
+ }
350
+
351
+ // 2. Configure matcher
352
+ export const config = {
353
+ matcher: ["/dashboard/:path*"],
354
+ }
355
+ ```
356
+
357
+ ### ❌ DON'T
358
+
359
+ ```typescript
360
+ // 1. Heavy database queries
361
+ export async function middleware(request: NextRequest) {
362
+ // ❌ No DB queries in middleware
363
+ const user = await prisma.user.findUnique({ where: { id: "..." } })
364
+ return NextResponse.next()
365
+ }
366
+
367
+ // 2. Processing all requests without matcher
368
+ export function middleware(request: NextRequest) {
369
+ // ❌ Performance degradation
370
+ return NextResponse.next()
371
+ }
372
+ ```
373
+
374
+ ---
375
+
376
+ ## Using with NextAuth.js
377
+
378
+ ```typescript
379
+ // middleware.ts
380
+ export { default } from "next-auth/middleware"
381
+
382
+ export const config = {
383
+ matcher: ["/dashboard/:path*", "/profile/:path*"],
384
+ }
385
+ ```
386
+
387
+ ---
388
+
389
+ ## References
390
+
391
+ - [Next.js Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware)