@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,269 @@
1
+ # App Router
2
+
3
+ > File-based routing system
4
+
5
+ ---
6
+
7
+ ## File Structure and Routing
8
+
9
+ ### Basic Rules
10
+
11
+ | File | Route | Description |
12
+ |------|-------|-------------|
13
+ | `app/page.tsx` | `/` | Home page |
14
+ | `app/about/page.tsx` | `/about` | About page |
15
+ | `app/blog/[slug]/page.tsx` | `/blog/:slug` | Dynamic route |
16
+ | `app/shop/[...slug]/page.tsx` | `/shop/*` | Catch-all |
17
+ | `app/docs/[[...slug]]/page.tsx` | `/docs/*` | Optional catch-all |
18
+
19
+ ### Example
20
+
21
+ ```typescript
22
+ // app/blog/[slug]/page.tsx
23
+ interface PageProps {
24
+ params: { slug: string }
25
+ searchParams: { [key: string]: string | string[] | undefined }
26
+ }
27
+
28
+ export default async function BlogPost({ params, searchParams }: PageProps) {
29
+ const post = await prisma.post.findUnique({ where: { slug: params.slug } })
30
+
31
+ if (!post) notFound()
32
+
33
+ return <article>{post.content}</article>
34
+ }
35
+ ```
36
+
37
+ ---
38
+
39
+ ## Layouts
40
+
41
+ ### Root Layout (required)
42
+
43
+ ```typescript
44
+ // app/layout.tsx
45
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
46
+ return (
47
+ <html lang="en">
48
+ <body>{children}</body>
49
+ </html>
50
+ )
51
+ }
52
+ ```
53
+
54
+ ### Nested Layout
55
+
56
+ ```typescript
57
+ // app/dashboard/layout.tsx
58
+ export default function DashboardLayout({ children }: { children: React.ReactNode }) {
59
+ return (
60
+ <div>
61
+ <nav>Dashboard Nav</nav>
62
+ <main>{children}</main>
63
+ </div>
64
+ )
65
+ }
66
+ ```
67
+
68
+ **Features:**
69
+ - Nestable (parent → child order)
70
+ - Persists without re-rendering
71
+ - Receives `children` as props
72
+
73
+ ---
74
+
75
+ ## Route Groups
76
+
77
+ ```
78
+ app/
79
+ ├── (marketing)/
80
+ │ ├── layout.tsx # Marketing layout
81
+ │ ├── page.tsx # /
82
+ │ └── about/
83
+ │ └── page.tsx # /about
84
+ └── (shop)/
85
+ ├── layout.tsx # Shop layout
86
+ └── products/
87
+ └── page.tsx # /products
88
+ ```
89
+
90
+ **Purpose:**
91
+ - Group folders without affecting URLs
92
+ - Apply different layouts
93
+
94
+ ---
95
+
96
+ ## Dynamic Routes
97
+
98
+ ### Single Parameter
99
+
100
+ ```typescript
101
+ // app/posts/[id]/page.tsx
102
+ export default async function PostPage({ params }: { params: { id: string } }) {
103
+ const post = await prisma.post.findUnique({ where: { id: params.id } })
104
+ return <article>{post.title}</article>
105
+ }
106
+
107
+ // Static generation (at build time)
108
+ export async function generateStaticParams() {
109
+ const posts = await prisma.post.findMany()
110
+ return posts.map(post => ({ id: post.id }))
111
+ }
112
+ ```
113
+
114
+ ### Catch-all
115
+
116
+ ```typescript
117
+ // app/docs/[...slug]/page.tsx
118
+ export default function DocsPage({ params }: { params: { slug: string[] } }) {
119
+ // /docs/a/b/c → params.slug = ["a", "b", "c"]
120
+ return <div>{params.slug.join("/")}</div>
121
+ }
122
+ ```
123
+
124
+ ---
125
+
126
+ ## Parallel Routes
127
+
128
+ ```
129
+ app/
130
+ ├── @analytics/
131
+ │ └── page.tsx
132
+ ├── @team/
133
+ │ └── page.tsx
134
+ └── layout.tsx
135
+ ```
136
+
137
+ ```typescript
138
+ // app/layout.tsx
139
+ export default function Layout({
140
+ children,
141
+ analytics,
142
+ team,
143
+ }: {
144
+ children: React.ReactNode
145
+ analytics: React.ReactNode
146
+ team: React.ReactNode
147
+ }) {
148
+ return (
149
+ <>
150
+ {children}
151
+ {analytics}
152
+ {team}
153
+ </>
154
+ )
155
+ }
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Intercepting Routes
161
+
162
+ ```
163
+ app/
164
+ ├── feed/
165
+ │ └── page.tsx
166
+ ├── photo/
167
+ │ └── [id]/
168
+ │ └── page.tsx
169
+ └── @modal/
170
+ └── (.)photo/
171
+ └── [id]/
172
+ └── page.tsx
173
+ ```
174
+
175
+ **Conventions:**
176
+ - `(.)` - same level
177
+ - `(..)` - one level up
178
+ - `(..)(..)` - two levels up
179
+ - `(...)` - from root
180
+
181
+ ---
182
+
183
+ ## Metadata
184
+
185
+ ```typescript
186
+ // app/blog/[slug]/page.tsx
187
+ import type { Metadata } from "next"
188
+
189
+ export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> {
190
+ const post = await prisma.post.findUnique({ where: { slug: params.slug } })
191
+
192
+ return {
193
+ title: post.title,
194
+ description: post.excerpt,
195
+ openGraph: {
196
+ title: post.title,
197
+ description: post.excerpt,
198
+ images: [post.image],
199
+ },
200
+ }
201
+ }
202
+ ```
203
+
204
+ ---
205
+
206
+ ## Special Files
207
+
208
+ | File | Purpose |
209
+ |------|---------|
210
+ | `loading.tsx` | Suspense fallback |
211
+ | `error.tsx` | Error Boundary |
212
+ | `not-found.tsx` | 404 page |
213
+ | `template.tsx` | Re-rendering Layout |
214
+ | `default.tsx` | Parallel route fallback |
215
+
216
+ ### Loading UI
217
+
218
+ ```typescript
219
+ // app/dashboard/loading.tsx
220
+ export default function Loading() {
221
+ return <div>Loading...</div>
222
+ }
223
+ ```
224
+
225
+ ### Error UI
226
+
227
+ ```typescript
228
+ // app/dashboard/error.tsx
229
+ "use client"
230
+
231
+ export default function Error({ error, reset }: { error: Error; reset: () => void }) {
232
+ return (
233
+ <div>
234
+ <h2>An error occurred</h2>
235
+ <button onClick={reset}>Try again</button>
236
+ </div>
237
+ )
238
+ }
239
+ ```
240
+
241
+ ---
242
+
243
+ ## Navigation
244
+
245
+ ```typescript
246
+ "use client"
247
+
248
+ import { useRouter, usePathname, useSearchParams } from "next/navigation"
249
+ import Link from "next/link"
250
+
251
+ export function Navigation() {
252
+ const router = useRouter()
253
+ const pathname = usePathname() // current path
254
+ const searchParams = useSearchParams() // query parameters
255
+
256
+ return (
257
+ <>
258
+ <Link href="/about">About</Link>
259
+ <button onClick={() => router.push("/posts")}>Go to Posts</button>
260
+ </>
261
+ )
262
+ }
263
+ ```
264
+
265
+ ---
266
+
267
+ ## References
268
+
269
+ - [Next.js App Router Official Docs](https://nextjs.org/docs/app)
@@ -0,0 +1,351 @@
1
+ # Caching
2
+
3
+ > Next.js caching strategies
4
+
5
+ ---
6
+
7
+ ## Cache Levels
8
+
9
+ | Level | Description |
10
+ |-------|-------------|
11
+ | **Request Memoization** | Deduplicate same requests (React) |
12
+ | **Data Cache** | Server data cache (persistent) |
13
+ | **Full Route Cache** | Static rendering at build time |
14
+ | **Router Cache** | Client-side router cache |
15
+
16
+ ---
17
+
18
+ ## Request Memoization
19
+
20
+ ```typescript
21
+ // Same requests execute only once
22
+ async function getUser(id: string) {
23
+ const res = await fetch(`https://api.example.com/users/${id}`)
24
+ return res.json()
25
+ }
26
+
27
+ export default async function Page() {
28
+ const user1 = await getUser("1") // fetch executes
29
+ const user2 = await getUser("1") // cache used (deduplicated)
30
+
31
+ return <div>{user1.name}</div>
32
+ }
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Data Cache (fetch)
38
+
39
+ ### Default (cached)
40
+
41
+ ```typescript
42
+ // Cached by default
43
+ const res = await fetch("https://api.example.com/posts")
44
+ ```
45
+
46
+ ### Disable Cache
47
+
48
+ ```typescript
49
+ // Fetch fresh data on every request
50
+ const res = await fetch("https://api.example.com/posts", {
51
+ cache: "no-store",
52
+ })
53
+ ```
54
+
55
+ ### Revalidate (time-based)
56
+
57
+ ```typescript
58
+ // Revalidate every 60 seconds
59
+ const res = await fetch("https://api.example.com/posts", {
60
+ next: { revalidate: 60 },
61
+ })
62
+ ```
63
+
64
+ ### Tag-based Cache
65
+
66
+ ```typescript
67
+ // Set tag
68
+ const res = await fetch("https://api.example.com/posts", {
69
+ next: { tags: ["posts"] },
70
+ })
71
+
72
+ // Invalidate tag in Server Action
73
+ "use server"
74
+ import { revalidateTag } from "next/cache"
75
+
76
+ export async function createPost(data: PostInput) {
77
+ await prisma.post.create({ data })
78
+ revalidateTag("posts") // Invalidate "posts" tag cache
79
+ }
80
+ ```
81
+
82
+ ---
83
+
84
+ ## unstable_cache (function caching)
85
+
86
+ ```typescript
87
+ import { unstable_cache } from "next/cache"
88
+
89
+ const getCachedPosts = unstable_cache(
90
+ async () => {
91
+ return prisma.post.findMany()
92
+ },
93
+ ["posts"], // cache key
94
+ {
95
+ revalidate: 60, // 60 seconds
96
+ tags: ["posts"], // tags
97
+ }
98
+ )
99
+
100
+ export default async function PostsPage() {
101
+ const posts = await getCachedPosts()
102
+ return <PostsList posts={posts} />
103
+ }
104
+ ```
105
+
106
+ ---
107
+
108
+ ## revalidatePath
109
+
110
+ ```typescript
111
+ "use server"
112
+
113
+ import { revalidatePath } from "next/cache"
114
+
115
+ export async function createPost(data: PostInput) {
116
+ const post = await prisma.post.create({ data })
117
+
118
+ // Invalidate specific path cache
119
+ revalidatePath("/posts")
120
+ revalidatePath(`/posts/${post.id}`)
121
+
122
+ // Invalidate all caches including layout
123
+ revalidatePath("/posts", "layout")
124
+
125
+ return post
126
+ }
127
+ ```
128
+
129
+ ---
130
+
131
+ ## revalidateTag
132
+
133
+ ```typescript
134
+ "use server"
135
+
136
+ import { revalidateTag } from "next/cache"
137
+
138
+ export async function createPost(data: PostInput) {
139
+ const post = await prisma.post.create({ data })
140
+
141
+ // Invalidate all caches with "posts" tag
142
+ revalidateTag("posts")
143
+
144
+ return post
145
+ }
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Full Route Cache (static rendering)
151
+
152
+ ### Static Page
153
+
154
+ ```typescript
155
+ // Generated at build time (default)
156
+ export default async function PostsPage() {
157
+ const posts = await prisma.post.findMany()
158
+ return <PostsList posts={posts} />
159
+ }
160
+ ```
161
+
162
+ ### Dynamic Page (disable cache)
163
+
164
+ ```typescript
165
+ // Render on every request
166
+ export const dynamic = "force-dynamic"
167
+
168
+ export default async function PostsPage() {
169
+ const posts = await prisma.post.findMany()
170
+ return <PostsList posts={posts} />
171
+ }
172
+ ```
173
+
174
+ ### Revalidate (time-based)
175
+
176
+ ```typescript
177
+ // Regenerate every 60 seconds
178
+ export const revalidate = 60
179
+
180
+ export default async function PostsPage() {
181
+ const posts = await prisma.post.findMany()
182
+ return <PostsList posts={posts} />
183
+ }
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Route Segment Config
189
+
190
+ ```typescript
191
+ // app/posts/page.tsx
192
+
193
+ // Force dynamic rendering
194
+ export const dynamic = "force-dynamic" // "auto" | "force-static" | "error"
195
+
196
+ // Revalidate interval (seconds)
197
+ export const revalidate = 60 // false | 0 | number
198
+
199
+ // Runtime configuration
200
+ export const runtime = "nodejs" // "edge"
201
+
202
+ // Maximum execution time (seconds)
203
+ export const maxDuration = 60
204
+
205
+ export default async function PostsPage() {
206
+ // ...
207
+ }
208
+ ```
209
+
210
+ ---
211
+
212
+ ## Router Cache (client-side)
213
+
214
+ ```typescript
215
+ "use client"
216
+
217
+ import { useRouter } from "next/navigation"
218
+
219
+ export function Navigation() {
220
+ const router = useRouter()
221
+
222
+ return (
223
+ <button
224
+ onClick={() => {
225
+ router.push("/posts") // Use cached page
226
+ router.refresh() // Force refresh
227
+ }}
228
+ >
229
+ Go to Posts
230
+ </button>
231
+ )
232
+ }
233
+ ```
234
+
235
+ ---
236
+
237
+ ## generateStaticParams (dynamic routes)
238
+
239
+ ```typescript
240
+ // app/posts/[id]/page.tsx
241
+
242
+ // List of pages to generate at build time
243
+ export async function generateStaticParams() {
244
+ const posts = await prisma.post.findMany({ select: { id: true } })
245
+ return posts.map(post => ({ id: post.id }))
246
+ }
247
+
248
+ export default async function PostPage({ params }: { params: { id: string } }) {
249
+ const post = await prisma.post.findUnique({ where: { id: params.id } })
250
+ return <article>{post.title}</article>
251
+ }
252
+ ```
253
+
254
+ ---
255
+
256
+ ## Caching Flow
257
+
258
+ ### Static Page
259
+
260
+ ```
261
+ 1. Render at build time
262
+ 2. Save to Full Route Cache
263
+ 3. Subsequent requests use cache
264
+ 4. Regenerate after revalidate time
265
+ ```
266
+
267
+ ### Dynamic Page
268
+
269
+ ```
270
+ 1. Render on every request
271
+ 2. No cache
272
+ 3. Update data with Server Actions
273
+ 4. Invalidate only specific paths with revalidatePath
274
+ ```
275
+
276
+ ---
277
+
278
+ ## Cache Invalidation Strategies
279
+
280
+ ### Time-based
281
+
282
+ ```typescript
283
+ // Regenerate every 60 seconds
284
+ export const revalidate = 60
285
+
286
+ const res = await fetch("...", { next: { revalidate: 60 } })
287
+ ```
288
+
289
+ ### On-demand (Server Actions)
290
+
291
+ ```typescript
292
+ "use server"
293
+
294
+ import { revalidatePath, revalidateTag } from "next/cache"
295
+
296
+ export async function updatePost(id: string, data: PostInput) {
297
+ await prisma.post.update({ where: { id }, data })
298
+
299
+ // Path invalidation
300
+ revalidatePath(`/posts/${id}`)
301
+
302
+ // Tag invalidation
303
+ revalidateTag("posts")
304
+ }
305
+ ```
306
+
307
+ ---
308
+
309
+ ## Best Practices
310
+
311
+ ### ✅ DO
312
+
313
+ ```typescript
314
+ // 1. Use default cache for static data
315
+ const posts = await fetch("https://api.example.com/posts")
316
+
317
+ // 2. Use no-store for dynamic data
318
+ const user = await fetch("https://api.example.com/user", {
319
+ cache: "no-store",
320
+ })
321
+
322
+ // 3. Tag-based invalidation
323
+ const posts = await fetch("...", { next: { tags: ["posts"] } })
324
+ revalidateTag("posts")
325
+
326
+ // 4. Function caching
327
+ const getCachedData = unstable_cache(
328
+ async () => prisma.post.findMany(),
329
+ ["posts"],
330
+ { revalidate: 60 }
331
+ )
332
+ ```
333
+
334
+ ### ❌ DON'T
335
+
336
+ ```typescript
337
+ // 1. Caching sensitive data
338
+ const user = await fetch("/api/user") // ❌ Don't cache personal data
339
+
340
+ // 2. Excessive revalidatePath
341
+ revalidatePath("/") // ❌ Invalidates entire site
342
+
343
+ // 3. Short revalidate interval
344
+ export const revalidate = 1 // ❌ Increases load
345
+ ```
346
+
347
+ ---
348
+
349
+ ## References
350
+
351
+ - [Next.js Caching](https://nextjs.org/docs/app/building-your-application/caching)