@xaviele/ag-kit 1.0.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 (235) hide show
  1. package/README.md +20 -0
  2. package/bin/cli.js +63 -0
  3. package/package.json +27 -0
  4. package/template/.agent/.shared/ui-ux-pro-max/data/charts.csv +26 -0
  5. package/template/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
  6. package/template/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
  7. package/template/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
  8. package/template/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
  9. package/template/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
  10. package/template/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
  11. package/template/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  12. package/template/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  13. package/template/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  14. package/template/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  15. package/template/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  16. package/template/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  17. package/template/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  18. package/template/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
  19. package/template/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  20. package/template/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  21. package/template/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  22. package/template/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  23. package/template/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
  24. package/template/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
  25. package/template/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  26. package/template/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  27. package/template/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
  28. package/template/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
  29. package/template/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  30. package/template/.agent/.shared/ui-ux-pro-max/scripts/core.py +258 -0
  31. package/template/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +1067 -0
  32. package/template/.agent/.shared/ui-ux-pro-max/scripts/search.py +106 -0
  33. package/template/.agent/ARCHITECTURE.md +281 -0
  34. package/template/.agent/agents/backend-specialist.md +263 -0
  35. package/template/.agent/agents/code-archaeologist.md +106 -0
  36. package/template/.agent/agents/database-architect.md +226 -0
  37. package/template/.agent/agents/debugger.md +225 -0
  38. package/template/.agent/agents/devops-engineer.md +242 -0
  39. package/template/.agent/agents/documentation-writer.md +104 -0
  40. package/template/.agent/agents/explorer-agent.md +73 -0
  41. package/template/.agent/agents/frontend-specialist.md +593 -0
  42. package/template/.agent/agents/game-developer.md +162 -0
  43. package/template/.agent/agents/mobile-developer.md +377 -0
  44. package/template/.agent/agents/orchestrator.md +416 -0
  45. package/template/.agent/agents/penetration-tester.md +188 -0
  46. package/template/.agent/agents/performance-optimizer.md +187 -0
  47. package/template/.agent/agents/product-manager.md +112 -0
  48. package/template/.agent/agents/product-owner.md +95 -0
  49. package/template/.agent/agents/project-planner.md +406 -0
  50. package/template/.agent/agents/qa-automation-engineer.md +103 -0
  51. package/template/.agent/agents/security-auditor.md +170 -0
  52. package/template/.agent/agents/seo-specialist.md +111 -0
  53. package/template/.agent/agents/test-engineer.md +158 -0
  54. package/template/.agent/mcp_config.json +24 -0
  55. package/template/.agent/rules/GEMINI.md +273 -0
  56. package/template/.agent/scripts/auto_preview.py +148 -0
  57. package/template/.agent/scripts/checklist.py +217 -0
  58. package/template/.agent/scripts/session_manager.py +120 -0
  59. package/template/.agent/scripts/verify_all.py +327 -0
  60. package/template/.agent/skills/adr/SKILL.md +282 -0
  61. package/template/.agent/skills/alirezarezvani-code-to-prd/SKILL.md +499 -0
  62. package/template/.agent/skills/api-patterns/SKILL.md +81 -0
  63. package/template/.agent/skills/api-patterns/api-style.md +42 -0
  64. package/template/.agent/skills/api-patterns/auth.md +24 -0
  65. package/template/.agent/skills/api-patterns/documentation.md +26 -0
  66. package/template/.agent/skills/api-patterns/graphql.md +41 -0
  67. package/template/.agent/skills/api-patterns/rate-limiting.md +31 -0
  68. package/template/.agent/skills/api-patterns/response.md +37 -0
  69. package/template/.agent/skills/api-patterns/rest.md +40 -0
  70. package/template/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
  71. package/template/.agent/skills/api-patterns/security-testing.md +122 -0
  72. package/template/.agent/skills/api-patterns/trpc.md +41 -0
  73. package/template/.agent/skills/api-patterns/versioning.md +22 -0
  74. package/template/.agent/skills/app-builder/SKILL.md +75 -0
  75. package/template/.agent/skills/app-builder/agent-coordination.md +71 -0
  76. package/template/.agent/skills/app-builder/feature-building.md +53 -0
  77. package/template/.agent/skills/app-builder/project-detection.md +34 -0
  78. package/template/.agent/skills/app-builder/scaffolding.md +118 -0
  79. package/template/.agent/skills/app-builder/tech-stack.md +41 -0
  80. package/template/.agent/skills/app-builder/templates/SKILL.md +39 -0
  81. package/template/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  82. package/template/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  83. package/template/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  84. package/template/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  85. package/template/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  86. package/template/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  87. package/template/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  88. package/template/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  89. package/template/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  90. package/template/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  91. package/template/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  92. package/template/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  93. package/template/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  94. package/template/.agent/skills/architecture/SKILL.md +55 -0
  95. package/template/.agent/skills/architecture/context-discovery.md +43 -0
  96. package/template/.agent/skills/architecture/examples.md +94 -0
  97. package/template/.agent/skills/architecture/pattern-selection.md +68 -0
  98. package/template/.agent/skills/architecture/patterns-reference.md +50 -0
  99. package/template/.agent/skills/architecture/trade-off-analysis.md +77 -0
  100. package/template/.agent/skills/bash-linux/SKILL.md +199 -0
  101. package/template/.agent/skills/behavioral-modes/SKILL.md +242 -0
  102. package/template/.agent/skills/brainstorming/SKILL.md +163 -0
  103. package/template/.agent/skills/brainstorming/dynamic-questioning.md +350 -0
  104. package/template/.agent/skills/claudekit-ai-multimodal/SKILL.md +353 -0
  105. package/template/.agent/skills/clean-code/SKILL.md +201 -0
  106. package/template/.agent/skills/code-review-checklist/SKILL.md +109 -0
  107. package/template/.agent/skills/database-design/SKILL.md +52 -0
  108. package/template/.agent/skills/database-design/database-selection.md +43 -0
  109. package/template/.agent/skills/database-design/indexing.md +39 -0
  110. package/template/.agent/skills/database-design/migrations.md +48 -0
  111. package/template/.agent/skills/database-design/optimization.md +36 -0
  112. package/template/.agent/skills/database-design/orm-selection.md +30 -0
  113. package/template/.agent/skills/database-design/schema-design.md +56 -0
  114. package/template/.agent/skills/database-design/scripts/schema_validator.py +172 -0
  115. package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
  116. package/template/.agent/skills/doc.md +177 -0
  117. package/template/.agent/skills/document/SKILL.md +250 -0
  118. package/template/.agent/skills/documentation-templates/SKILL.md +194 -0
  119. package/template/.agent/skills/frontend-design/SKILL.md +452 -0
  120. package/template/.agent/skills/frontend-design/animation-guide.md +331 -0
  121. package/template/.agent/skills/frontend-design/color-system.md +311 -0
  122. package/template/.agent/skills/frontend-design/decision-trees.md +418 -0
  123. package/template/.agent/skills/frontend-design/motion-graphics.md +306 -0
  124. package/template/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
  125. package/template/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
  126. package/template/.agent/skills/frontend-design/typography-system.md +345 -0
  127. package/template/.agent/skills/frontend-design/ux-psychology.md +1116 -0
  128. package/template/.agent/skills/frontend-design/visual-effects.md +383 -0
  129. package/template/.agent/skills/game-development/2d-games/SKILL.md +119 -0
  130. package/template/.agent/skills/game-development/3d-games/SKILL.md +135 -0
  131. package/template/.agent/skills/game-development/SKILL.md +167 -0
  132. package/template/.agent/skills/game-development/game-art/SKILL.md +185 -0
  133. package/template/.agent/skills/game-development/game-audio/SKILL.md +190 -0
  134. package/template/.agent/skills/game-development/game-design/SKILL.md +129 -0
  135. package/template/.agent/skills/game-development/mobile-games/SKILL.md +108 -0
  136. package/template/.agent/skills/game-development/multiplayer/SKILL.md +132 -0
  137. package/template/.agent/skills/game-development/pc-games/SKILL.md +144 -0
  138. package/template/.agent/skills/game-development/vr-ar/SKILL.md +123 -0
  139. package/template/.agent/skills/game-development/web-games/SKILL.md +150 -0
  140. package/template/.agent/skills/geo-fundamentals/SKILL.md +156 -0
  141. package/template/.agent/skills/geo-fundamentals/scripts/geo_checker.py +289 -0
  142. package/template/.agent/skills/i18n-localization/SKILL.md +154 -0
  143. package/template/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  144. package/template/.agent/skills/intelligent-routing/SKILL.md +335 -0
  145. package/template/.agent/skills/lint-and-validate/SKILL.md +45 -0
  146. package/template/.agent/skills/lint-and-validate/scripts/lint_runner.py +184 -0
  147. package/template/.agent/skills/lint-and-validate/scripts/type_coverage.py +173 -0
  148. package/template/.agent/skills/mcp-builder/SKILL.md +176 -0
  149. package/template/.agent/skills/mindrally-meta-prompt/SKILL.md +129 -0
  150. package/template/.agent/skills/mobile-design/SKILL.md +394 -0
  151. package/template/.agent/skills/mobile-design/decision-trees.md +516 -0
  152. package/template/.agent/skills/mobile-design/mobile-backend.md +491 -0
  153. package/template/.agent/skills/mobile-design/mobile-color-system.md +420 -0
  154. package/template/.agent/skills/mobile-design/mobile-debugging.md +122 -0
  155. package/template/.agent/skills/mobile-design/mobile-design-thinking.md +357 -0
  156. package/template/.agent/skills/mobile-design/mobile-navigation.md +458 -0
  157. package/template/.agent/skills/mobile-design/mobile-performance.md +767 -0
  158. package/template/.agent/skills/mobile-design/mobile-testing.md +356 -0
  159. package/template/.agent/skills/mobile-design/mobile-typography.md +433 -0
  160. package/template/.agent/skills/mobile-design/platform-android.md +666 -0
  161. package/template/.agent/skills/mobile-design/platform-ios.md +561 -0
  162. package/template/.agent/skills/mobile-design/scripts/mobile_audit.py +670 -0
  163. package/template/.agent/skills/mobile-design/touch-psychology.md +537 -0
  164. package/template/.agent/skills/nextjs-react-expert/1-async-eliminating-waterfalls.md +351 -0
  165. package/template/.agent/skills/nextjs-react-expert/2-bundle-bundle-size-optimization.md +240 -0
  166. package/template/.agent/skills/nextjs-react-expert/3-server-server-side-performance.md +490 -0
  167. package/template/.agent/skills/nextjs-react-expert/4-client-client-side-data-fetching.md +264 -0
  168. package/template/.agent/skills/nextjs-react-expert/5-rerender-re-render-optimization.md +581 -0
  169. package/template/.agent/skills/nextjs-react-expert/6-rendering-rendering-performance.md +432 -0
  170. package/template/.agent/skills/nextjs-react-expert/7-js-javascript-performance.md +684 -0
  171. package/template/.agent/skills/nextjs-react-expert/8-advanced-advanced-patterns.md +150 -0
  172. package/template/.agent/skills/nextjs-react-expert/9-cache-components.md +103 -0
  173. package/template/.agent/skills/nextjs-react-expert/SKILL.md +293 -0
  174. package/template/.agent/skills/nextjs-react-expert/scripts/convert_rules.py +222 -0
  175. package/template/.agent/skills/nextjs-react-expert/scripts/react_performance_checker.py +252 -0
  176. package/template/.agent/skills/nodejs-best-practices/SKILL.md +333 -0
  177. package/template/.agent/skills/parallel-agents/SKILL.md +175 -0
  178. package/template/.agent/skills/performance-profiling/SKILL.md +143 -0
  179. package/template/.agent/skills/performance-profiling/scripts/lighthouse_audit.py +76 -0
  180. package/template/.agent/skills/plan-writing/SKILL.md +152 -0
  181. package/template/.agent/skills/pm-skills-create-prd/SKILL.md +88 -0
  182. package/template/.agent/skills/powershell-windows/SKILL.md +167 -0
  183. package/template/.agent/skills/prompt-engineering/SKILL.md +566 -0
  184. package/template/.agent/skills/python-patterns/SKILL.md +441 -0
  185. package/template/.agent/skills/red-team-tactics/SKILL.md +199 -0
  186. package/template/.agent/skills/rust-pro/SKILL.md +176 -0
  187. package/template/.agent/skills/seo-fundamentals/SKILL.md +129 -0
  188. package/template/.agent/skills/seo-fundamentals/scripts/seo_checker.py +219 -0
  189. package/template/.agent/skills/server-management/SKILL.md +161 -0
  190. package/template/.agent/skills/skills/adr/SKILL.md +282 -0
  191. package/template/.agent/skills/skills/alirezarezvani-code-to-prd/SKILL.md +499 -0
  192. package/template/.agent/skills/skills/claudekit-ai-multimodal/SKILL.md +353 -0
  193. package/template/.agent/skills/skills/document/SKILL.md +250 -0
  194. package/template/.agent/skills/skills/mindrally-meta-prompt/SKILL.md +129 -0
  195. package/template/.agent/skills/skills/pm-skills-create-prd/SKILL.md +88 -0
  196. package/template/.agent/skills/skills/prompt-engineering/SKILL.md +566 -0
  197. package/template/.agent/skills/systematic-debugging/SKILL.md +109 -0
  198. package/template/.agent/skills/tailwind-patterns/SKILL.md +269 -0
  199. package/template/.agent/skills/tdd-workflow/SKILL.md +149 -0
  200. package/template/.agent/skills/testing-patterns/SKILL.md +178 -0
  201. package/template/.agent/skills/testing-patterns/scripts/test_runner.py +219 -0
  202. package/template/.agent/skills/vulnerability-scanner/SKILL.md +276 -0
  203. package/template/.agent/skills/vulnerability-scanner/checklists.md +121 -0
  204. package/template/.agent/skills/vulnerability-scanner/scripts/security_scan.py +458 -0
  205. package/template/.agent/skills/web-design-guidelines/SKILL.md +57 -0
  206. package/template/.agent/skills/webapp-testing/SKILL.md +187 -0
  207. package/template/.agent/skills/webapp-testing/scripts/playwright_runner.py +173 -0
  208. package/template/.agent/skills/zalo-mini-app/SKILL.md +81 -0
  209. package/template/.agent/skills/zalo-mini-app/references/api-device.md +121 -0
  210. package/template/.agent/skills/zalo-mini-app/references/api-overview.md +88 -0
  211. package/template/.agent/skills/zalo-mini-app/references/api-storage.md +74 -0
  212. package/template/.agent/skills/zalo-mini-app/references/api-ui.md +124 -0
  213. package/template/.agent/skills/zalo-mini-app/references/api-user.md +113 -0
  214. package/template/.agent/skills/zalo-mini-app/references/api-zalo.md +127 -0
  215. package/template/.agent/skills/zalo-mini-app/references/design-guidelines.md +70 -0
  216. package/template/.agent/skills/zalo-mini-app/references/getting-started.md +95 -0
  217. package/template/.agent/skills/zalo-mini-app/references/react-best-practices.md +790 -0
  218. package/template/.agent/skills/zalo-mini-app/references/web-design-guidelines.md +591 -0
  219. package/template/.agent/skills/zalo-mini-app/references/zaui-display.md +103 -0
  220. package/template/.agent/skills/zalo-mini-app/references/zaui-form.md +108 -0
  221. package/template/.agent/skills/zalo-mini-app/references/zaui-layout.md +94 -0
  222. package/template/.agent/skills/zalo-mini-app/references/zaui-overlay.md +98 -0
  223. package/template/.agent/skills/zalo-mini-app/references/zaui-overview.md +82 -0
  224. package/template/.agent/workflows/brainstorm.md +113 -0
  225. package/template/.agent/workflows/create.md +59 -0
  226. package/template/.agent/workflows/debug.md +103 -0
  227. package/template/.agent/workflows/deploy.md +176 -0
  228. package/template/.agent/workflows/enhance.md +63 -0
  229. package/template/.agent/workflows/orchestrate.md +237 -0
  230. package/template/.agent/workflows/plan.md +89 -0
  231. package/template/.agent/workflows/preview.md +81 -0
  232. package/template/.agent/workflows/status.md +86 -0
  233. package/template/.agent/workflows/test.md +144 -0
  234. package/template/.agent/workflows/ui-ux-pro-max.md +296 -0
  235. package/template/.agent/workflows/veo-marketing.md +46 -0
@@ -0,0 +1,790 @@
1
+ # React Best Practices
2
+
3
+ Comprehensive performance optimization guide for React applications in Zalo Mini Apps. Based on Vercel Engineering guidelines.
4
+
5
+ ---
6
+
7
+ ## 1. Eliminating Waterfalls (CRITICAL)
8
+
9
+ Waterfalls are the #1 performance killer. Each sequential await adds full network latency.
10
+
11
+ ### 1.1 Defer Await Until Needed
12
+
13
+ Move `await` into branches where actually used.
14
+
15
+ ```typescript
16
+ // Incorrect: blocks both branches
17
+ async function handleRequest(userId: string, skipProcessing: boolean) {
18
+ const userData = await fetchUserData(userId)
19
+ if (skipProcessing) return { skipped: true }
20
+ return processUserData(userData)
21
+ }
22
+
23
+ // Correct: only blocks when needed
24
+ async function handleRequest(userId: string, skipProcessing: boolean) {
25
+ if (skipProcessing) return { skipped: true }
26
+ const userData = await fetchUserData(userId)
27
+ return processUserData(userData)
28
+ }
29
+ ```
30
+
31
+ ### 1.2 Promise.all() for Independent Operations
32
+
33
+ ```typescript
34
+ // Incorrect: 3 round trips
35
+ const user = await fetchUser()
36
+ const posts = await fetchPosts()
37
+ const comments = await fetchComments()
38
+
39
+ // Correct: 1 round trip
40
+ const [user, posts, comments] = await Promise.all([
41
+ fetchUser(),
42
+ fetchPosts(),
43
+ fetchComments()
44
+ ])
45
+ ```
46
+
47
+ ### 1.3 Dependency-Based Parallelization
48
+
49
+ For operations with partial dependencies, use `better-all`:
50
+
51
+ ```typescript
52
+ import { all } from 'better-all'
53
+
54
+ const { user, config, profile } = await all({
55
+ async user() { return fetchUser() },
56
+ async config() { return fetchConfig() },
57
+ async profile() {
58
+ return fetchProfile((await this.$.user).id)
59
+ }
60
+ })
61
+ ```
62
+
63
+ ### 1.4 Strategic Suspense Boundaries
64
+
65
+ ```tsx
66
+ // Correct: wrapper shows immediately, data streams in
67
+ function Page() {
68
+ return (
69
+ <div>
70
+ <Header />
71
+ <Suspense fallback={<Skeleton />}>
72
+ <DataDisplay />
73
+ </Suspense>
74
+ <Footer />
75
+ </div>
76
+ )
77
+ }
78
+
79
+ async function DataDisplay() {
80
+ const data = await fetchData()
81
+ return <div>{data.content}</div>
82
+ }
83
+ ```
84
+
85
+ **When NOT to use:**
86
+ - Critical data needed for layout decisions
87
+ - SEO-critical content above the fold
88
+ - Small, fast queries where suspense overhead isn't worth it
89
+
90
+ ---
91
+
92
+ ## 2. Bundle Size Optimization (CRITICAL)
93
+
94
+ Keep bundle <10MB for Zalo Mini App approval.
95
+
96
+ ### 2.1 Avoid Barrel File Imports
97
+
98
+ Barrel files can load 1000+ modules, taking 200-800ms extra.
99
+
100
+ ```tsx
101
+ // Incorrect: imports entire library (1,583 modules)
102
+ import { Check, X, Menu } from 'lucide-react'
103
+
104
+ // Correct: imports only what you need (~3 modules)
105
+ import Check from 'lucide-react/dist/esm/icons/check'
106
+ import X from 'lucide-react/dist/esm/icons/x'
107
+ import Menu from 'lucide-react/dist/esm/icons/menu'
108
+ ```
109
+
110
+ **Commonly affected libraries:** `lucide-react`, `@mui/material`, `react-icons`, `lodash`, `date-fns`
111
+
112
+ ### 2.2 Dynamic Imports for Heavy Components
113
+
114
+ ```tsx
115
+ import { lazy, Suspense } from 'react'
116
+
117
+ const HeavyEditor = lazy(() => import('./HeavyEditor'))
118
+
119
+ function CodePanel({ code }) {
120
+ return (
121
+ <Suspense fallback={<Skeleton />}>
122
+ <HeavyEditor value={code} />
123
+ </Suspense>
124
+ )
125
+ }
126
+ ```
127
+
128
+ ### 2.3 Conditional Module Loading
129
+
130
+ ```tsx
131
+ function AnimationPlayer({ enabled }) {
132
+ const [frames, setFrames] = useState(null)
133
+
134
+ useEffect(() => {
135
+ if (enabled && !frames) {
136
+ import('./animation-frames.js')
137
+ .then(mod => setFrames(mod.frames))
138
+ .catch(() => {})
139
+ }
140
+ }, [enabled, frames])
141
+
142
+ if (!frames) return <Skeleton />
143
+ return <Canvas frames={frames} />
144
+ }
145
+ ```
146
+
147
+ ### 2.4 Preload on User Intent
148
+
149
+ ```tsx
150
+ function EditorButton({ onClick }) {
151
+ const preload = () => void import('./HeavyEditor')
152
+
153
+ return (
154
+ <button
155
+ onMouseEnter={preload}
156
+ onFocus={preload}
157
+ onClick={onClick}
158
+ >
159
+ Open Editor
160
+ </button>
161
+ )
162
+ }
163
+ ```
164
+
165
+ ### 2.5 Defer Non-Critical Libraries
166
+
167
+ ```tsx
168
+ // Analytics, logging load after hydration
169
+ import { lazy, Suspense } from 'react'
170
+
171
+ const Analytics = lazy(() => import('@/lib/analytics'))
172
+
173
+ function RootLayout({ children }) {
174
+ return (
175
+ <>
176
+ {children}
177
+ <Suspense fallback={null}>
178
+ <Analytics />
179
+ </Suspense>
180
+ </>
181
+ )
182
+ }
183
+ ```
184
+
185
+ ---
186
+
187
+ ## 3. Client-Side Data Fetching (MEDIUM-HIGH)
188
+
189
+ ### 3.1 Use SWR for Automatic Deduplication
190
+
191
+ ```tsx
192
+ import useSWR from 'swr'
193
+
194
+ // Multiple instances share one request
195
+ function UserList() {
196
+ const { data: users } = useSWR('/api/users', fetcher)
197
+ return <div>{users?.map(renderUser)}</div>
198
+ }
199
+ ```
200
+
201
+ ### 3.2 Passive Event Listeners for Scroll Performance
202
+
203
+ ```typescript
204
+ useEffect(() => {
205
+ const handleScroll = (e) => console.log(e.deltaY)
206
+
207
+ // Correct: passive allows immediate scrolling
208
+ document.addEventListener('wheel', handleScroll, { passive: true })
209
+
210
+ return () => document.removeEventListener('wheel', handleScroll)
211
+ }, [])
212
+ ```
213
+
214
+ ### 3.3 Deduplicate Global Event Listeners
215
+
216
+ Use `useSWRSubscription` to share listeners across component instances:
217
+
218
+ ```tsx
219
+ import useSWRSubscription from 'swr/subscription'
220
+
221
+ const keyCallbacks = new Map()
222
+
223
+ function useKeyboardShortcut(key, callback) {
224
+ useEffect(() => {
225
+ if (!keyCallbacks.has(key)) keyCallbacks.set(key, new Set())
226
+ keyCallbacks.get(key).add(callback)
227
+ return () => {
228
+ keyCallbacks.get(key)?.delete(callback)
229
+ if (keyCallbacks.get(key)?.size === 0) keyCallbacks.delete(key)
230
+ }
231
+ }, [key, callback])
232
+
233
+ useSWRSubscription('global-keydown', () => {
234
+ const handler = (e) => {
235
+ if (e.metaKey && keyCallbacks.has(e.key)) {
236
+ keyCallbacks.get(e.key).forEach(cb => cb())
237
+ }
238
+ }
239
+ window.addEventListener('keydown', handler)
240
+ return () => window.removeEventListener('keydown', handler)
241
+ })
242
+ }
243
+ ```
244
+
245
+ ### 3.4 Version localStorage Data
246
+
247
+ ```typescript
248
+ const VERSION = 'v2'
249
+
250
+ function saveConfig(config) {
251
+ try {
252
+ localStorage.setItem(`userConfig:${VERSION}`, JSON.stringify(config))
253
+ } catch {}
254
+ }
255
+
256
+ function loadConfig() {
257
+ try {
258
+ const data = localStorage.getItem(`userConfig:${VERSION}`)
259
+ return data ? JSON.parse(data) : null
260
+ } catch {
261
+ return null
262
+ }
263
+ }
264
+ ```
265
+
266
+ ---
267
+
268
+ ## 4. Re-render Optimization (MEDIUM)
269
+
270
+ ### 4.1 Defer State Reads to Usage Point
271
+
272
+ ```tsx
273
+ // Incorrect: subscribes to all searchParams changes
274
+ function ShareButton({ chatId }) {
275
+ const searchParams = useSearchParams()
276
+ const handleShare = () => shareChat(chatId, { ref: searchParams.get('ref') })
277
+ return <button onClick={handleShare}>Share</button>
278
+ }
279
+
280
+ // Correct: reads on demand, no subscription
281
+ function ShareButton({ chatId }) {
282
+ const handleShare = () => {
283
+ const params = new URLSearchParams(window.location.search)
284
+ shareChat(chatId, { ref: params.get('ref') })
285
+ }
286
+ return <button onClick={handleShare}>Share</button>
287
+ }
288
+ ```
289
+
290
+ ### 4.2 Use Functional setState Updates
291
+
292
+ ```tsx
293
+ // Incorrect: requires state as dependency, recreated on every change
294
+ const addItems = useCallback((newItems) => {
295
+ setItems([...items, ...newItems])
296
+ }, [items])
297
+
298
+ // Correct: stable callback, no stale closures
299
+ const addItems = useCallback((newItems) => {
300
+ setItems(curr => [...curr, ...newItems])
301
+ }, [])
302
+ ```
303
+
304
+ **Benefits:**
305
+ - Stable callback references
306
+ - No stale closures
307
+ - Fewer dependencies
308
+ - Prevents common React bugs
309
+
310
+ ### 4.3 Use Lazy State Initialization
311
+
312
+ ```tsx
313
+ // Incorrect: buildSearchIndex runs on EVERY render
314
+ const [searchIndex] = useState(buildSearchIndex(items))
315
+
316
+ // Correct: runs only on initial render
317
+ const [searchIndex] = useState(() => buildSearchIndex(items))
318
+ ```
319
+
320
+ ### 4.4 Narrow Effect Dependencies
321
+
322
+ ```tsx
323
+ // Incorrect: re-runs on any user field change
324
+ useEffect(() => {
325
+ console.log(user.id)
326
+ }, [user])
327
+
328
+ // Correct: re-runs only when id changes
329
+ useEffect(() => {
330
+ console.log(user.id)
331
+ }, [user.id])
332
+ ```
333
+
334
+ ### 4.5 Subscribe to Derived State
335
+
336
+ ```tsx
337
+ // Incorrect: re-renders on every pixel change
338
+ function Sidebar() {
339
+ const width = useWindowWidth()
340
+ const isMobile = width < 768
341
+ return <nav className={isMobile ? 'mobile' : 'desktop'} />
342
+ }
343
+
344
+ // Correct: re-renders only when boolean changes
345
+ function Sidebar() {
346
+ const isMobile = useMediaQuery('(max-width: 767px)')
347
+ return <nav className={isMobile ? 'mobile' : 'desktop'} />
348
+ }
349
+ ```
350
+
351
+ ### 4.6 Use Transitions for Non-Urgent Updates
352
+
353
+ ```tsx
354
+ import { startTransition } from 'react'
355
+
356
+ function ScrollTracker() {
357
+ const [scrollY, setScrollY] = useState(0)
358
+
359
+ useEffect(() => {
360
+ const handler = () => {
361
+ startTransition(() => setScrollY(window.scrollY))
362
+ }
363
+ window.addEventListener('scroll', handler, { passive: true })
364
+ return () => window.removeEventListener('scroll', handler)
365
+ }, [])
366
+ }
367
+ ```
368
+
369
+ ### 4.7 Extract to Memoized Components
370
+
371
+ ```tsx
372
+ // Incorrect: computes avatar even when loading
373
+ function Profile({ user, loading }) {
374
+ const avatar = useMemo(() => {
375
+ const id = computeAvatarId(user)
376
+ return <Avatar id={id} />
377
+ }, [user])
378
+
379
+ if (loading) return <Skeleton />
380
+ return <div>{avatar}</div>
381
+ }
382
+
383
+ // Correct: skips computation when loading
384
+ const UserAvatar = memo(function UserAvatar({ user }) {
385
+ const id = useMemo(() => computeAvatarId(user), [user])
386
+ return <Avatar id={id} />
387
+ })
388
+
389
+ function Profile({ user, loading }) {
390
+ if (loading) return <Skeleton />
391
+ return <div><UserAvatar user={user} /></div>
392
+ }
393
+ ```
394
+
395
+ ---
396
+
397
+ ## 5. Rendering Performance (MEDIUM)
398
+
399
+ ### 5.1 CSS content-visibility for Long Lists
400
+
401
+ ```css
402
+ .message-item {
403
+ content-visibility: auto;
404
+ contain-intrinsic-size: 0 80px;
405
+ }
406
+ ```
407
+
408
+ For 1000 messages, browser skips layout/paint for ~990 off-screen items (10× faster initial render).
409
+
410
+ ### 5.2 Animate SVG Wrapper
411
+
412
+ Many browsers don't have hardware acceleration for CSS animations on SVG elements.
413
+
414
+ ```tsx
415
+ // Incorrect: no hardware acceleration
416
+ <svg className="animate-spin">
417
+ <circle cx="12" cy="12" r="10" />
418
+ </svg>
419
+
420
+ // Correct: hardware accelerated
421
+ <div className="animate-spin">
422
+ <svg>
423
+ <circle cx="12" cy="12" r="10" />
424
+ </svg>
425
+ </div>
426
+ ```
427
+
428
+ ### 5.3 Hoist Static JSX Elements
429
+
430
+ ```tsx
431
+ // Correct: reuses same element across renders
432
+ const loadingSkeleton = (
433
+ <div className="animate-pulse h-20 bg-gray-200" />
434
+ )
435
+
436
+ function Container({ loading }) {
437
+ return <div>{loading && loadingSkeleton}</div>
438
+ }
439
+ ```
440
+
441
+ ### 5.4 Use Explicit Conditional Rendering
442
+
443
+ ```tsx
444
+ // Incorrect: renders "0" when count is 0
445
+ {count && <span className="badge">{count}</span>}
446
+
447
+ // Correct: renders nothing when count is 0
448
+ {count > 0 ? <span className="badge">{count}</span> : null}
449
+ ```
450
+
451
+ ### 5.5 Prevent Hydration Mismatch Without Flickering
452
+
453
+ ```tsx
454
+ function ThemeWrapper({ children }) {
455
+ return (
456
+ <>
457
+ <div id="theme-wrapper">
458
+ {children}
459
+ </div>
460
+ <script
461
+ dangerouslySetInnerHTML={{
462
+ __html: `
463
+ (function() {
464
+ try {
465
+ var theme = localStorage.getItem('theme') || 'light';
466
+ var el = document.getElementById('theme-wrapper');
467
+ if (el) el.className = theme;
468
+ } catch (e) {}
469
+ })();
470
+ `,
471
+ }}
472
+ />
473
+ </>
474
+ )
475
+ }
476
+ ```
477
+
478
+ ### 5.6 Use Activity Component for Show/Hide
479
+
480
+ ```tsx
481
+ import { Activity } from 'react'
482
+
483
+ function Dropdown({ isOpen }) {
484
+ return (
485
+ <Activity mode={isOpen ? 'visible' : 'hidden'}>
486
+ <ExpensiveMenu />
487
+ </Activity>
488
+ )
489
+ }
490
+ ```
491
+
492
+ Preserves state/DOM for expensive components that frequently toggle visibility.
493
+
494
+ ---
495
+
496
+ ## 6. JavaScript Performance (LOW-MEDIUM)
497
+
498
+ ### 6.1 Build Index Maps for Repeated Lookups
499
+
500
+ ```typescript
501
+ // Incorrect: O(n) per lookup - 1M ops for 1000×1000
502
+ orders.map(order => ({
503
+ ...order,
504
+ user: users.find(u => u.id === order.userId)
505
+ }))
506
+
507
+ // Correct: O(1) per lookup - 2K ops
508
+ const userById = new Map(users.map(u => [u.id, u]))
509
+ orders.map(order => ({
510
+ ...order,
511
+ user: userById.get(order.userId)
512
+ }))
513
+ ```
514
+
515
+ ### 6.2 Use Set/Map for O(1) Lookups
516
+
517
+ ```typescript
518
+ // Incorrect: O(n) per check
519
+ items.filter(item => allowedIds.includes(item.id))
520
+
521
+ // Correct: O(1) per check
522
+ const allowedSet = new Set(allowedIds)
523
+ items.filter(item => allowedSet.has(item.id))
524
+ ```
525
+
526
+ ### 6.3 Combine Multiple Array Iterations
527
+
528
+ ```typescript
529
+ // Incorrect: 3 iterations
530
+ const admins = users.filter(u => u.isAdmin)
531
+ const testers = users.filter(u => u.isTester)
532
+ const inactive = users.filter(u => !u.isActive)
533
+
534
+ // Correct: 1 iteration
535
+ const admins = [], testers = [], inactive = []
536
+ for (const user of users) {
537
+ if (user.isAdmin) admins.push(user)
538
+ if (user.isTester) testers.push(user)
539
+ if (!user.isActive) inactive.push(user)
540
+ }
541
+ ```
542
+
543
+ ### 6.4 Cache Storage API Calls
544
+
545
+ ```typescript
546
+ const storageCache = new Map()
547
+
548
+ function getLocalStorage(key) {
549
+ if (!storageCache.has(key)) {
550
+ storageCache.set(key, localStorage.getItem(key))
551
+ }
552
+ return storageCache.get(key)
553
+ }
554
+
555
+ function setLocalStorage(key, value) {
556
+ localStorage.setItem(key, value)
557
+ storageCache.set(key, value)
558
+ }
559
+
560
+ // Invalidate on external changes
561
+ window.addEventListener('storage', (e) => {
562
+ if (e.key) storageCache.delete(e.key)
563
+ })
564
+ ```
565
+
566
+ ### 6.5 Cache Repeated Function Calls
567
+
568
+ ```typescript
569
+ const slugifyCache = new Map()
570
+
571
+ function cachedSlugify(text) {
572
+ if (slugifyCache.has(text)) return slugifyCache.get(text)
573
+ const result = slugify(text)
574
+ slugifyCache.set(text, result)
575
+ return result
576
+ }
577
+ ```
578
+
579
+ ### 6.6 Use toSorted() for Immutability
580
+
581
+ ```typescript
582
+ // Incorrect: mutates original array
583
+ const sorted = users.sort((a, b) => a.name.localeCompare(b.name))
584
+
585
+ // Correct: creates new array, original unchanged
586
+ const sorted = users.toSorted((a, b) => a.name.localeCompare(b.name))
587
+
588
+ // Fallback for older browsers
589
+ const sorted = [...users].sort((a, b) => a.name.localeCompare(b.name))
590
+ ```
591
+
592
+ **Other immutable methods:** `.toReversed()`, `.toSpliced()`, `.with()`
593
+
594
+ ### 6.7 Early Return from Functions
595
+
596
+ ```typescript
597
+ // Incorrect: processes all items after error found
598
+ function validateUsers(users) {
599
+ let hasError = false
600
+ for (const user of users) {
601
+ if (!user.email) hasError = true
602
+ }
603
+ return hasError ? { valid: false } : { valid: true }
604
+ }
605
+
606
+ // Correct: returns on first error
607
+ function validateUsers(users) {
608
+ for (const user of users) {
609
+ if (!user.email) return { valid: false, error: 'Email required' }
610
+ }
611
+ return { valid: true }
612
+ }
613
+ ```
614
+
615
+ ### 6.8 Early Length Check for Array Comparisons
616
+
617
+ ```typescript
618
+ // Incorrect: always sorts even when lengths differ
619
+ function hasChanges(current, original) {
620
+ return current.sort().join() !== original.sort().join()
621
+ }
622
+
623
+ // Correct: O(1) length check first
624
+ function hasChanges(current, original) {
625
+ if (current.length !== original.length) return true
626
+ const currentSorted = current.toSorted()
627
+ const originalSorted = original.toSorted()
628
+ for (let i = 0; i < currentSorted.length; i++) {
629
+ if (currentSorted[i] !== originalSorted[i]) return true
630
+ }
631
+ return false
632
+ }
633
+ ```
634
+
635
+ ### 6.9 Use Loop for Min/Max Instead of Sort
636
+
637
+ ```typescript
638
+ // Incorrect: O(n log n)
639
+ function getLatestProject(projects) {
640
+ const sorted = [...projects].sort((a, b) => b.updatedAt - a.updatedAt)
641
+ return sorted[0]
642
+ }
643
+
644
+ // Correct: O(n)
645
+ function getLatestProject(projects) {
646
+ if (projects.length === 0) return null
647
+ let latest = projects[0]
648
+ for (let i = 1; i < projects.length; i++) {
649
+ if (projects[i].updatedAt > latest.updatedAt) {
650
+ latest = projects[i]
651
+ }
652
+ }
653
+ return latest
654
+ }
655
+ ```
656
+
657
+ ### 6.10 Cache Property Access in Loops
658
+
659
+ ```typescript
660
+ // Incorrect: 3 lookups × N iterations
661
+ for (let i = 0; i < arr.length; i++) {
662
+ process(obj.config.settings.value)
663
+ }
664
+
665
+ // Correct: 1 lookup total
666
+ const value = obj.config.settings.value
667
+ const len = arr.length
668
+ for (let i = 0; i < len; i++) {
669
+ process(value)
670
+ }
671
+ ```
672
+
673
+ ### 6.11 Hoist RegExp Creation
674
+
675
+ ```tsx
676
+ // Incorrect: new RegExp every render
677
+ function Highlighter({ text, query }) {
678
+ const regex = new RegExp(`(${query})`, 'gi')
679
+ const parts = text.split(regex)
680
+ return <>{parts.map((part, i) => ...)}</>
681
+ }
682
+
683
+ // Correct: memoize
684
+ function Highlighter({ text, query }) {
685
+ const regex = useMemo(
686
+ () => new RegExp(`(${escapeRegex(query)})`, 'gi'),
687
+ [query]
688
+ )
689
+ const parts = text.split(regex)
690
+ return <>{parts.map((part, i) => ...)}</>
691
+ }
692
+ ```
693
+
694
+ ### 6.12 Batch DOM CSS Changes
695
+
696
+ ```typescript
697
+ // Incorrect: multiple reflows
698
+ element.style.width = '100px'
699
+ element.style.height = '200px'
700
+ element.style.backgroundColor = 'blue'
701
+
702
+ // Correct: single reflow via class
703
+ element.classList.add('highlighted-box')
704
+
705
+ // Or via cssText
706
+ element.style.cssText = `
707
+ width: 100px;
708
+ height: 200px;
709
+ background-color: blue;
710
+ `
711
+ ```
712
+
713
+ ---
714
+
715
+ ## 7. Advanced Patterns (LOW)
716
+
717
+ ### 7.1 Store Event Handlers in Refs
718
+
719
+ ```tsx
720
+ import { useEffectEvent } from 'react'
721
+
722
+ function useWindowEvent(event, handler) {
723
+ const onEvent = useEffectEvent(handler)
724
+
725
+ useEffect(() => {
726
+ window.addEventListener(event, onEvent)
727
+ return () => window.removeEventListener(event, onEvent)
728
+ }, [event])
729
+ }
730
+ ```
731
+
732
+ ### 7.2 useLatest for Stable Callback Refs
733
+
734
+ ```typescript
735
+ function useLatest(value) {
736
+ const ref = useRef(value)
737
+ useEffect(() => {
738
+ ref.current = value
739
+ }, [value])
740
+ return ref
741
+ }
742
+
743
+ // Usage: stable effect, fresh callback
744
+ function SearchInput({ onSearch }) {
745
+ const [query, setQuery] = useState('')
746
+ const onSearchRef = useLatest(onSearch)
747
+
748
+ useEffect(() => {
749
+ const timeout = setTimeout(() => onSearchRef.current(query), 300)
750
+ return () => clearTimeout(timeout)
751
+ }, [query])
752
+ }
753
+ ```
754
+
755
+ ---
756
+
757
+ ## Anti-patterns Checklist
758
+
759
+ ### Critical Performance
760
+ - [ ] Sequential awaits for independent operations
761
+ - [ ] Barrel file imports (`import { X } from 'library'`)
762
+ - [ ] Large arrays `.map()` without virtualization
763
+ - [ ] `transition: all` instead of specific properties
764
+
765
+ ### React State
766
+ - [ ] Mutating arrays with `.sort()` (use `.toSorted()`)
767
+ - [ ] Missing functional setState for state-dependent updates
768
+ - [ ] Non-lazy expensive state initialization
769
+ - [ ] Object dependencies in useEffect (use primitives)
770
+
771
+ ### Rendering
772
+ - [ ] Animating SVG elements directly (wrap in div)
773
+ - [ ] Using `&&` with numbers (`count && <Badge />`)
774
+ - [ ] Creating RegExp in render without memoization
775
+ - [ ] Layout reads in render (`getBoundingClientRect`)
776
+
777
+ ### Events
778
+ - [ ] Missing `{ passive: true }` for scroll/touch listeners
779
+ - [ ] Multiple listeners for same global event
780
+ - [ ] Non-versioned localStorage keys
781
+
782
+ ---
783
+
784
+ ## References
785
+
786
+ - React: https://react.dev
787
+ - SWR: https://swr.vercel.app
788
+ - better-all: https://github.com/shuding/better-all
789
+ - LRU Cache: https://github.com/isaacs/node-lru-cache
790
+ - Vercel Blog: https://vercel.com/blog/how-we-made-the-vercel-dashboard-twice-as-fast