@kood/claude-code 0.3.12 → 0.3.15

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 (104) hide show
  1. package/dist/index.js +30 -8
  2. package/package.json +4 -4
  3. package/templates/.claude/skills/korea-uiux-design/SKILL.md +444 -0
  4. package/templates/.claude/skills/korea-uiux-design/references/accessibility.md +298 -0
  5. package/templates/.claude/skills/korea-uiux-design/references/checklist.md +107 -0
  6. package/templates/.claude/skills/korea-uiux-design/references/color-system.md +156 -0
  7. package/templates/.claude/skills/korea-uiux-design/references/design-philosophy.md +25 -0
  8. package/templates/.claude/skills/korea-uiux-design/references/icon-guide.md +180 -0
  9. package/templates/.claude/skills/korea-uiux-design/references/micro-interactions.md +259 -0
  10. package/templates/.claude/skills/korea-uiux-design/references/responsive-patterns.md +115 -0
  11. package/templates/.claude/skills/korea-uiux-design/references/service-patterns.md +206 -0
  12. package/templates/.claude/skills/korea-uiux-design/references/state-patterns.md +320 -0
  13. package/templates/.claude/skills/korea-uiux-design/references/typography.md +70 -0
  14. package/templates/.claude/skills/nextjs-react-best-practices/AGENTS.md +663 -0
  15. package/templates/.claude/skills/nextjs-react-best-practices/SKILL.md +269 -0
  16. package/templates/.claude/skills/tanstack-start-react-best-practices/AGENTS.md +751 -0
  17. package/templates/.claude/skills/tanstack-start-react-best-practices/SKILL.md +431 -0
  18. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/async-defer-await.md +80 -0
  19. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/async-dependencies.md +36 -0
  20. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/async-loader.md +44 -0
  21. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/async-parallel.md +28 -0
  22. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/bundle-barrel-imports.md +59 -0
  23. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/bundle-conditional.md +31 -0
  24. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  25. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/bundle-lazy-routes.md +67 -0
  26. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/bundle-preload.md +50 -0
  27. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-event-listeners.md +74 -0
  28. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-tanstack-query.md +77 -0
  29. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/js-batch-dom-css.md +82 -0
  30. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/js-cache-function-results.md +80 -0
  31. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/js-cache-property-access.md +28 -0
  32. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/js-cache-storage.md +70 -0
  33. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/js-combine-iterations.md +32 -0
  34. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/js-early-exit.md +50 -0
  35. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/js-hoist-regexp.md +45 -0
  36. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/js-index-maps.md +37 -0
  37. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/js-length-check-first.md +49 -0
  38. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/js-min-max-loop.md +82 -0
  39. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/js-set-map-lookups.md +24 -0
  40. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  41. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  42. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rendering-conditional-render.md +40 -0
  43. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rendering-content-visibility.md +38 -0
  44. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  45. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rendering-svg-precision.md +28 -0
  46. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rerender-defer-reads.md +39 -0
  47. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rerender-dependencies.md +45 -0
  48. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rerender-derived-state.md +29 -0
  49. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  50. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  51. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rerender-memo.md +44 -0
  52. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rerender-transitions.md +40 -0
  53. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-cache-lru.md +41 -0
  54. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-deferred-data.md +67 -0
  55. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-parallel-fetching.md +60 -0
  56. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-serialization.md +38 -0
  57. package/templates/.claude/skills/vercel-react-best-practices/AGENTS.md +0 -2249
  58. package/templates/.claude/skills/vercel-react-best-practices/SKILL.md +0 -125
  59. package/templates/.claude/skills/vs-design-diverge/SKILL.md +0 -307
  60. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/advanced-event-handler-refs.md +0 -0
  61. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/advanced-use-latest.md +0 -0
  62. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/async-api-routes.md +0 -0
  63. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/async-defer-await.md +0 -0
  64. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/async-dependencies.md +0 -0
  65. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/async-parallel.md +0 -0
  66. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/async-suspense-boundaries.md +0 -0
  67. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/bundle-barrel-imports.md +0 -0
  68. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/bundle-conditional.md +0 -0
  69. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/bundle-defer-third-party.md +0 -0
  70. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/bundle-dynamic-imports.md +0 -0
  71. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/bundle-preload.md +0 -0
  72. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/client-event-listeners.md +0 -0
  73. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/client-swr-dedup.md +0 -0
  74. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/js-batch-dom-css.md +0 -0
  75. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/js-cache-function-results.md +0 -0
  76. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/js-cache-property-access.md +0 -0
  77. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/js-cache-storage.md +0 -0
  78. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/js-combine-iterations.md +0 -0
  79. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/js-early-exit.md +0 -0
  80. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/js-hoist-regexp.md +0 -0
  81. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/js-index-maps.md +0 -0
  82. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/js-length-check-first.md +0 -0
  83. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/js-min-max-loop.md +0 -0
  84. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/js-set-map-lookups.md +0 -0
  85. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/js-tosorted-immutable.md +0 -0
  86. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rendering-activity.md +0 -0
  87. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rendering-animate-svg-wrapper.md +0 -0
  88. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rendering-conditional-render.md +0 -0
  89. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rendering-content-visibility.md +0 -0
  90. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rendering-hoist-jsx.md +0 -0
  91. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rendering-hydration-no-flicker.md +0 -0
  92. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rendering-svg-precision.md +0 -0
  93. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rerender-defer-reads.md +0 -0
  94. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rerender-dependencies.md +0 -0
  95. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rerender-derived-state.md +0 -0
  96. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rerender-functional-setstate.md +0 -0
  97. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rerender-lazy-state-init.md +0 -0
  98. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rerender-memo.md +0 -0
  99. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/rerender-transitions.md +0 -0
  100. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/server-after-nonblocking.md +0 -0
  101. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/server-cache-lru.md +0 -0
  102. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/server-cache-react.md +0 -0
  103. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/server-parallel-fetching.md +0 -0
  104. /package/templates/.claude/skills/{vercel-react-best-practices → nextjs-react-best-practices}/rules/server-serialization.md +0 -0
@@ -0,0 +1,751 @@
1
+ # TanStack Start React Best Practices
2
+
3
+ **Version 1.0.0**
4
+ TanStack Start Optimization Guide
5
+ January 2026
6
+
7
+ > **Note:**
8
+ > This document is mainly for agents and LLMs to follow when maintaining,
9
+ > generating, or refactoring React and TanStack Start codebases. Humans
10
+ > may also find it useful, but guidance here is optimized for automation
11
+ > and consistency by AI-assisted workflows.
12
+
13
+ ---
14
+
15
+ <communication>
16
+
17
+ ## User Communication Protocol
18
+
19
+ **CRITICAL: Always communicate with the user in Korean (한국어).**
20
+
21
+ This applies to:
22
+ - Questions and clarifications
23
+ - Progress updates and summaries
24
+ - Explaining decisions and trade-offs
25
+ - Reporting errors or blockers
26
+
27
+ Internal processing and code comments remain in English. Only user-facing messages must be in Korean.
28
+
29
+ </communication>
30
+
31
+ ---
32
+
33
+ ## Abstract
34
+
35
+ Comprehensive performance optimization guide for React and TanStack Start applications, designed for AI agents and LLMs. Contains 38 rules across 7 categories, prioritized by impact from critical (eliminating waterfalls, reducing bundle size) to incremental (JavaScript performance). Each rule includes detailed explanations, real-world examples comparing incorrect vs. correct implementations, and specific impact metrics to guide automated refactoring and code generation.
36
+
37
+ ---
38
+
39
+ <instructions>
40
+
41
+ ## Document Usage Instructions
42
+
43
+ @rules/async-defer-await.md
44
+ @rules/async-parallel.md
45
+ @rules/async-dependencies.md
46
+ @rules/async-loader.md
47
+ @rules/bundle-barrel-imports.md
48
+ @rules/bundle-lazy-routes.md
49
+ @rules/bundle-conditional.md
50
+ @rules/bundle-defer-third-party.md
51
+ @rules/bundle-preload.md
52
+ @rules/server-cache-lru.md
53
+ @rules/server-serialization.md
54
+ @rules/server-parallel-fetching.md
55
+ @rules/server-deferred-data.md
56
+ @rules/client-tanstack-query.md
57
+ @rules/client-event-listeners.md
58
+ @rules/rerender-defer-reads.md
59
+ @rules/rerender-memo.md
60
+ @rules/rerender-dependencies.md
61
+ @rules/rerender-derived-state.md
62
+ @rules/rerender-functional-setstate.md
63
+ @rules/rerender-lazy-state-init.md
64
+ @rules/rerender-transitions.md
65
+ @rules/rendering-animate-svg-wrapper.md
66
+ @rules/rendering-content-visibility.md
67
+ @rules/rendering-hoist-jsx.md
68
+ @rules/rendering-svg-precision.md
69
+ @rules/rendering-conditional-render.md
70
+ @rules/js-batch-dom-css.md
71
+ @rules/js-index-maps.md
72
+ @rules/js-cache-property-access.md
73
+ @rules/js-cache-function-results.md
74
+ @rules/js-cache-storage.md
75
+ @rules/js-combine-iterations.md
76
+ @rules/js-length-check-first.md
77
+ @rules/js-early-exit.md
78
+ @rules/js-hoist-regexp.md
79
+ @rules/js-min-max-loop.md
80
+ @rules/js-set-map-lookups.md
81
+ @rules/js-tosorted-immutable.md
82
+
83
+ </instructions>
84
+
85
+ ---
86
+
87
+ <categories>
88
+
89
+ ## Categories by Priority
90
+
91
+ | Priority | Category | Impact | Description |
92
+ |----------|----------|--------|-------------|
93
+ | 1 | Eliminating Waterfalls | **CRITICAL** | Convert sequential awaits to parallel. Biggest gains |
94
+ | 2 | Bundle Size Optimization | **CRITICAL** | Improve TTI and LCP. Faster initial loads |
95
+ | 3 | Server-Side Performance | HIGH | Eliminate server-side waterfalls, reduce response times |
96
+ | 4 | Client-Side Data Fetching | MEDIUM-HIGH | Automatic deduplication, efficient data fetching |
97
+ | 5 | Re-render Optimization | MEDIUM | Minimize unnecessary re-renders, improve UI responsiveness |
98
+ | 6 | Rendering Performance | MEDIUM | Optimize browser rendering work |
99
+ | 7 | JavaScript Performance | LOW-MEDIUM | Hot path micro-optimizations |
100
+
101
+ </categories>
102
+
103
+ ---
104
+
105
+ <critical_patterns>
106
+
107
+ ## 1. Eliminating Waterfalls (CRITICAL)
108
+
109
+ Waterfalls are the #1 performance killer. Each sequential await adds full network latency.
110
+
111
+ ### Parallel Execution
112
+
113
+ ```typescript
114
+ // ❌ Sequential execution (3 round trips)
115
+ const user = await fetchUser()
116
+ const posts = await fetchPosts()
117
+ const comments = await fetchComments()
118
+
119
+ // ✅ Parallel execution (1 round trip)
120
+ const [user, posts, comments] = await Promise.all([
121
+ fetchUser(),
122
+ fetchPosts(),
123
+ fetchComments()
124
+ ])
125
+ ```
126
+
127
+ ### createServerFn + Loader Parallel Fetching
128
+
129
+ ```typescript
130
+ import { createServerFn } from '@tanstack/react-start'
131
+ import { createFileRoute } from '@tanstack/react-router'
132
+
133
+ // Define Server Functions
134
+ const getPost = createServerFn().handler(async (postId: string) => {
135
+ return await db.post.findUnique({ where: { id: postId } })
136
+ })
137
+
138
+ const getAuthor = createServerFn().handler(async (authorId: string) => {
139
+ return await db.author.findUnique({ where: { id: authorId } })
140
+ })
141
+
142
+ const getComments = createServerFn().handler(async (postId: string) => {
143
+ return await db.comment.findMany({ where: { postId } })
144
+ })
145
+
146
+ // ❌ Sequential loading
147
+ export const Route = createFileRoute('/posts/$postId')({
148
+ loader: async ({ params }) => {
149
+ const post = await getPost(params.postId)
150
+ const author = await getAuthor(post.authorId)
151
+ const comments = await getComments(params.postId)
152
+ return { post, author, comments }
153
+ }
154
+ })
155
+
156
+ // ✅ Parallel loading (independent data)
157
+ export const Route = createFileRoute('/posts/$postId')({
158
+ loader: async ({ params }) => {
159
+ const [post, comments] = await Promise.all([
160
+ getPost(params.postId),
161
+ getComments(params.postId)
162
+ ])
163
+ return { post, comments }
164
+ }
165
+ })
166
+ ```
167
+
168
+ ### Dependency-Based Parallelization
169
+
170
+ ```typescript
171
+ import { all } from 'better-all'
172
+
173
+ // ✅ Maximum parallelization with better-all
174
+ export const Route = createFileRoute('/posts/$postId')({
175
+ loader: async ({ params }) => {
176
+ const { post, author, comments } = await all({
177
+ async post() {
178
+ return fetchPost(params.postId)
179
+ },
180
+ async author() {
181
+ const p = await this.$.post
182
+ return fetchAuthor(p.authorId)
183
+ },
184
+ async comments() {
185
+ return fetchComments(params.postId)
186
+ }
187
+ })
188
+ return { post, author, comments }
189
+ }
190
+ })
191
+ ```
192
+
193
+ ### Deferred Data for Non-Blocking Loading (Automatic)
194
+
195
+ ```typescript
196
+ import { createServerFn } from '@tanstack/react-start'
197
+ import { createFileRoute, Await } from '@tanstack/react-router'
198
+ import { Suspense } from 'react'
199
+
200
+ // Fast Server Function
201
+ const getPost = createServerFn().handler(async (postId: string) => {
202
+ return await db.post.findUnique({ where: { id: postId } })
203
+ })
204
+
205
+ // Slow Server Function
206
+ const getComments = createServerFn().handler(async (postId: string) => {
207
+ await new Promise(r => setTimeout(r, 3000)) // Slow query
208
+ return await db.comment.findMany({ where: { postId } })
209
+ })
210
+
211
+ // ✅ Await important data, defer non-critical data
212
+ export const Route = createFileRoute('/posts/$postId')({
213
+ loader: async ({ params }) => {
214
+ // Important: post loads immediately (await)
215
+ const post = await getPost(params.postId)
216
+
217
+ // Non-critical: comments returns Promise (automatically deferred)
218
+ const deferredComments = getComments(params.postId)
219
+
220
+ return {
221
+ post,
222
+ deferredComments
223
+ }
224
+ }
225
+ })
226
+
227
+ function PostPage() {
228
+ const { post, deferredComments } = Route.useLoaderData()
229
+
230
+ return (
231
+ <div>
232
+ {/* post renders immediately */}
233
+ <PostContent post={post} />
234
+
235
+ {/* comments stream in */}
236
+ <Suspense fallback={<CommentsSkeleton />}>
237
+ <Await promise={deferredComments}>
238
+ {(comments) => <Comments comments={comments} />}
239
+ </Await>
240
+ </Suspense>
241
+ </div>
242
+ )
243
+ }
244
+ ```
245
+
246
+ **Important:** TanStack Start doesn't require calling `defer()` explicitly. Simply return a Promise and it's automatically deferred.
247
+
248
+ </critical_patterns>
249
+
250
+ ---
251
+
252
+ <bundle_optimization>
253
+
254
+ ## 2. Bundle Size Optimization (CRITICAL)
255
+
256
+ ### Avoid Barrel File Imports
257
+
258
+ ```tsx
259
+ // ❌ Import entire library (1583 modules, ~2.8s)
260
+ import { Check, X, Menu } from 'lucide-react'
261
+
262
+ // ✅ Direct imports (3 modules only)
263
+ import Check from 'lucide-react/dist/esm/icons/check'
264
+ import X from 'lucide-react/dist/esm/icons/x'
265
+ import Menu from 'lucide-react/dist/esm/icons/menu'
266
+ ```
267
+
268
+ Affected libraries: `lucide-react`, `@mui/material`, `@mui/icons-material`, `@tabler/icons-react`, `react-icons`, `@headlessui/react`, `@radix-ui/react-*`, `lodash`, `ramda`, `date-fns`, `rxjs`, `react-use`
269
+
270
+ ### Route-Based Code Splitting
271
+
272
+ ```typescript
273
+ import { lazy } from 'react'
274
+ import { createFileRoute } from '@tanstack/react-router'
275
+
276
+ // ❌ All components bundled in main chunk
277
+ import { HeavyEditor } from './components/HeavyEditor'
278
+ import { ComplexChart } from './components/ComplexChart'
279
+
280
+ export const Route = createFileRoute('/dashboard')({
281
+ component: DashboardPage
282
+ })
283
+
284
+ function DashboardPage() {
285
+ return (
286
+ <div>
287
+ <HeavyEditor />
288
+ <ComplexChart />
289
+ </div>
290
+ )
291
+ }
292
+
293
+ // ✅ Heavy components lazy loaded
294
+ const HeavyEditor = lazy(() => import('./components/HeavyEditor'))
295
+ const ComplexChart = lazy(() => import('./components/ComplexChart'))
296
+
297
+ export const Route = createFileRoute('/dashboard')({
298
+ component: DashboardPage
299
+ })
300
+
301
+ function DashboardPage() {
302
+ return (
303
+ <div>
304
+ <Suspense fallback={<EditorSkeleton />}>
305
+ <HeavyEditor />
306
+ </Suspense>
307
+ <Suspense fallback={<ChartSkeleton />}>
308
+ <ComplexChart />
309
+ </Suspense>
310
+ </div>
311
+ )
312
+ }
313
+ ```
314
+
315
+ ### Conditional Module Loading
316
+
317
+ ```tsx
318
+ // ❌ Always loaded
319
+ import { AnimationFrames } from './animation-frames'
320
+
321
+ function AnimationPlayer({ enabled }: { enabled: boolean }) {
322
+ if (!enabled) return null
323
+ return <Canvas frames={AnimationFrames} />
324
+ }
325
+
326
+ // ✅ Load only when activated
327
+ function AnimationPlayer({ enabled }: { enabled: boolean }) {
328
+ const [frames, setFrames] = useState<Frame[] | null>(null)
329
+
330
+ useEffect(() => {
331
+ if (enabled && !frames) {
332
+ import('./animation-frames')
333
+ .then(mod => setFrames(mod.frames))
334
+ .catch(() => setEnabled(false))
335
+ }
336
+ }, [enabled, frames])
337
+
338
+ if (!frames) return <Skeleton />
339
+ return <Canvas frames={frames} />
340
+ }
341
+ ```
342
+
343
+ </bundle_optimization>
344
+
345
+ ---
346
+
347
+ <server_performance>
348
+
349
+ ## 3. Server-Side Performance (HIGH)
350
+
351
+ ### LRU Cache - Cross-Request Caching
352
+
353
+ ```typescript
354
+ import { LRUCache } from 'lru-cache'
355
+
356
+ const cache = new LRUCache<string, any>({
357
+ max: 1000,
358
+ ttl: 5 * 60 * 1000 // 5 minutes
359
+ })
360
+
361
+ export async function getUser(id: string) {
362
+ const cached = cache.get(id)
363
+ if (cached) return cached
364
+
365
+ const user = await db.user.findUnique({ where: { id } })
366
+ cache.set(id, user)
367
+ return user
368
+ }
369
+
370
+ // Request 1: DB query, result cached
371
+ // Request 2: cache hit, no DB query
372
+ ```
373
+
374
+ ### Minimize Serialization
375
+
376
+ ```typescript
377
+ // ❌ Serializes all 50 fields
378
+ export const Route = createFileRoute('/profile')({
379
+ loader: async () => {
380
+ const user = await fetchUser() // 50 fields
381
+ return { user }
382
+ }
383
+ })
384
+
385
+ function ProfilePage() {
386
+ const { user } = Route.useLoaderData()
387
+ return <div>{user.name}</div> // uses 1 field
388
+ }
389
+
390
+ // ✅ Serializes only needed fields
391
+ export const Route = createFileRoute('/profile')({
392
+ loader: async () => {
393
+ const user = await fetchUser()
394
+ return {
395
+ userName: user.name,
396
+ userEmail: user.email
397
+ }
398
+ }
399
+ })
400
+
401
+ function ProfilePage() {
402
+ const { userName, userEmail } = Route.useLoaderData()
403
+ return (
404
+ <div>
405
+ <div>{userName}</div>
406
+ <div>{userEmail}</div>
407
+ </div>
408
+ )
409
+ }
410
+ ```
411
+
412
+ ### Parallel Fetching in Loader + createServerFn
413
+
414
+ ```typescript
415
+ import { createServerFn } from '@tanstack/react-start'
416
+ import { createFileRoute } from '@tanstack/react-router'
417
+
418
+ // Define Server Functions
419
+ const getUser = createServerFn().handler(async () => {
420
+ return await db.user.findMany()
421
+ })
422
+
423
+ const getStats = createServerFn().handler(async () => {
424
+ return await db.stats.findMany()
425
+ })
426
+
427
+ const getNotifications = createServerFn().handler(async () => {
428
+ return await db.notification.findMany()
429
+ })
430
+
431
+ // ❌ Sequential fetching
432
+ export const Route = createFileRoute('/dashboard')({
433
+ loader: async () => {
434
+ const user = await getUser()
435
+ const stats = await getStats()
436
+ const notifications = await getNotifications()
437
+ return { user, stats, notifications }
438
+ }
439
+ })
440
+
441
+ // ✅ Parallel fetching
442
+ export const Route = createFileRoute('/dashboard')({
443
+ loader: async () => {
444
+ const [user, stats, notifications] = await Promise.all([
445
+ getUser(),
446
+ getStats(),
447
+ getNotifications()
448
+ ])
449
+ return { user, stats, notifications }
450
+ }
451
+ })
452
+ ```
453
+
454
+ **Important:** TanStack Start loaders are isomorphic. They run on both server and client, so separate server-only code with `createServerFn()`.
455
+
456
+ </server_performance>
457
+
458
+ ---
459
+
460
+ <client_data_fetching>
461
+
462
+ ## 4. Client-Side Data Fetching (MEDIUM-HIGH)
463
+
464
+ ### TanStack Query for Automatic Caching
465
+
466
+ ```tsx
467
+ import { useQuery } from '@tanstack/react-query'
468
+
469
+ // ❌ No deduplication, each instance fetches
470
+ function UserList() {
471
+ const [users, setUsers] = useState([])
472
+ useEffect(() => {
473
+ fetch('/api/users')
474
+ .then(r => r.json())
475
+ .then(setUsers)
476
+ }, [])
477
+ }
478
+
479
+ // ✅ Multiple instances share one request
480
+ function UserList() {
481
+ const { data: users } = useQuery({
482
+ queryKey: ['users'],
483
+ queryFn: fetchUsers
484
+ })
485
+ }
486
+ ```
487
+
488
+ ### TanStack Query Mutations
489
+
490
+ ```tsx
491
+ import { useMutation, useQueryClient } from '@tanstack/react-query'
492
+
493
+ function UpdateButton() {
494
+ const queryClient = useQueryClient()
495
+
496
+ const mutation = useMutation({
497
+ mutationFn: updateUser,
498
+ onSuccess: () => {
499
+ // Invalidate cache for automatic refetch
500
+ queryClient.invalidateQueries({ queryKey: ['users'] })
501
+ }
502
+ })
503
+
504
+ return (
505
+ <button onClick={() => mutation.mutate()}>
506
+ Update
507
+ </button>
508
+ )
509
+ }
510
+ ```
511
+
512
+ </client_data_fetching>
513
+
514
+ ---
515
+
516
+ <rerender_optimization>
517
+
518
+ ## 5. Re-render Optimization (MEDIUM)
519
+
520
+ ### Functional setState
521
+
522
+ ```tsx
523
+ // ❌ items as dependency, recreated every time
524
+ function TodoList() {
525
+ const [items, setItems] = useState(initialItems)
526
+
527
+ const addItems = useCallback((newItems: Item[]) => {
528
+ setItems([...items, ...newItems])
529
+ }, [items]) // Recreated on items change
530
+ }
531
+
532
+ // ✅ Stable callback, never recreated
533
+ function TodoList() {
534
+ const [items, setItems] = useState(initialItems)
535
+
536
+ const addItems = useCallback((newItems: Item[]) => {
537
+ setItems(curr => [...curr, ...newItems])
538
+ }, []) // No dependencies, always uses latest state
539
+ }
540
+ ```
541
+
542
+ ### Lazy State Initialization
543
+
544
+ ```tsx
545
+ // ❌ Runs on every render
546
+ function FilteredList({ items }: { items: Item[] }) {
547
+ const [searchIndex, setSearchIndex] = useState(buildSearchIndex(items))
548
+ }
549
+
550
+ // ✅ Runs only on initial render
551
+ function FilteredList({ items }: { items: Item[] }) {
552
+ const [searchIndex, setSearchIndex] = useState(() => buildSearchIndex(items))
553
+ }
554
+ ```
555
+
556
+ ### Subscribe to Derived State
557
+
558
+ ```tsx
559
+ // ❌ Re-renders on every pixel change
560
+ function Sidebar() {
561
+ const width = useWindowWidth() // continuous updates
562
+ const isMobile = width < 768
563
+ return <nav className={isMobile ? 'mobile' : 'desktop'}>
564
+ }
565
+
566
+ // ✅ Re-renders only when boolean changes
567
+ function Sidebar() {
568
+ const isMobile = useMediaQuery('(max-width: 767px)')
569
+ return <nav className={isMobile ? 'mobile' : 'desktop'}>
570
+ }
571
+ ```
572
+
573
+ </rerender_optimization>
574
+
575
+ ---
576
+
577
+ <rendering_performance>
578
+
579
+ ## 6. Rendering Performance (MEDIUM)
580
+
581
+ ### Animate SVG Wrapper
582
+
583
+ ```tsx
584
+ // ❌ Animating SVG directly - no hardware acceleration
585
+ function LoadingSpinner() {
586
+ return (
587
+ <svg className="animate-spin" width="24" height="24">
588
+ <circle cx="12" cy="12" r="10" />
589
+ </svg>
590
+ )
591
+ }
592
+
593
+ // ✅ Animating wrapper div - hardware accelerated
594
+ function LoadingSpinner() {
595
+ return (
596
+ <div className="animate-spin">
597
+ <svg width="24" height="24">
598
+ <circle cx="12" cy="12" r="10" />
599
+ </svg>
600
+ </div>
601
+ )
602
+ }
603
+ ```
604
+
605
+ ### content-visibility
606
+
607
+ ```css
608
+ .message-item {
609
+ content-visibility: auto;
610
+ contain-intrinsic-size: 0 80px;
611
+ }
612
+ ```
613
+
614
+ ```tsx
615
+ function MessageList({ messages }: { messages: Message[] }) {
616
+ return (
617
+ <div className="overflow-y-auto h-screen">
618
+ {messages.map(msg => (
619
+ <div key={msg.id} className="message-item">
620
+ <Avatar user={msg.author} />
621
+ <div>{msg.content}</div>
622
+ </div>
623
+ ))}
624
+ </div>
625
+ )
626
+ }
627
+ ```
628
+
629
+ For 1000 messages, browser skips layout/paint for ~990 off-screen items (10× faster initial render)
630
+
631
+ ### JSX Hoisting
632
+
633
+ ```tsx
634
+ // ❌ Recreated every render
635
+ function Container() {
636
+ return (
637
+ <div>
638
+ {loading && <div className="animate-pulse h-20 bg-gray-200" />}
639
+ </div>
640
+ )
641
+ }
642
+
643
+ // ✅ Created once
644
+ const loadingSkeleton = (
645
+ <div className="animate-pulse h-20 bg-gray-200" />
646
+ )
647
+
648
+ function Container() {
649
+ return (
650
+ <div>
651
+ {loading && loadingSkeleton}
652
+ </div>
653
+ )
654
+ }
655
+ ```
656
+
657
+ </rendering_performance>
658
+
659
+ ---
660
+
661
+ <javascript_performance>
662
+
663
+ ## 7. JavaScript Performance (LOW-MEDIUM)
664
+
665
+ ### Build Index Maps for Repeated Lookups
666
+
667
+ ```typescript
668
+ // ❌ O(n) per lookup
669
+ function processOrders(orders: Order[], users: User[]) {
670
+ return orders.map(order => ({
671
+ ...order,
672
+ user: users.find(u => u.id === order.userId)
673
+ }))
674
+ }
675
+
676
+ // ✅ O(1) per lookup
677
+ function processOrders(orders: Order[], users: User[]) {
678
+ const userById = new Map(users.map(u => [u.id, u]))
679
+ return orders.map(order => ({
680
+ ...order,
681
+ user: userById.get(order.userId)
682
+ }))
683
+ }
684
+ ```
685
+
686
+ 1000 orders × 1000 users: 1M ops → 2K ops
687
+
688
+ ### Early Length Check for Array Comparisons
689
+
690
+ ```typescript
691
+ // ❌ Always runs expensive comparison
692
+ function hasChanges(current: string[], original: string[]) {
693
+ return current.sort().join() !== original.sort().join()
694
+ }
695
+
696
+ // ✅ O(1) length check first
697
+ function hasChanges(current: string[], original: string[]) {
698
+ if (current.length !== original.length) return true
699
+
700
+ const currentSorted = current.toSorted()
701
+ const originalSorted = original.toSorted()
702
+ for (let i = 0; i < currentSorted.length; i++) {
703
+ if (currentSorted[i] !== originalSorted[i]) return true
704
+ }
705
+ return false
706
+ }
707
+ ```
708
+
709
+ ### Use toSorted() for Immutability
710
+
711
+ ```typescript
712
+ // ❌ Mutates original array
713
+ function UserList({ users }: { users: User[] }) {
714
+ const sorted = useMemo(
715
+ () => users.sort((a, b) => a.name.localeCompare(b.name)),
716
+ [users]
717
+ )
718
+ }
719
+
720
+ // ✅ Creates new array
721
+ function UserList({ users }: { users: User[] }) {
722
+ const sorted = useMemo(
723
+ () => users.toSorted((a, b) => a.name.localeCompare(b.name)),
724
+ [users]
725
+ )
726
+ }
727
+ ```
728
+
729
+ </javascript_performance>
730
+
731
+ ---
732
+
733
+ <references>
734
+
735
+ ## References
736
+
737
+ ### TanStack Official Documentation
738
+ 1. [React](https://react.dev)
739
+ 2. [TanStack Start Overview](https://tanstack.com/start/latest/docs/framework/react/overview)
740
+ 3. [TanStack Start Quick Start](https://tanstack.com/start/latest/docs/framework/react/quick-start)
741
+ 4. [TanStack Router](https://tanstack.com/router)
742
+ 5. [TanStack Router Deferred Data Loading](https://tanstack.com/router/v1/docs/framework/react/guide/deferred-data-loading)
743
+ 6. [TanStack Query](https://tanstack.com/query)
744
+ 7. [Server Functions Guide](https://tanstack.com/start/latest/docs/framework/react/guide/server-functions)
745
+
746
+ ### External Resources
747
+ 8. [better-all](https://github.com/shuding/better-all)
748
+ 9. [node-lru-cache](https://github.com/isaacs/node-lru-cache)
749
+ 10. [Using Server Functions and TanStack Query](https://www.brenelz.com/posts/using-server-functions-and-tanstack-query/)
750
+
751
+ </references>