@vetala/vetala 0.1.0-beta

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.

Potentially problematic release.


This version of @vetala/vetala might be problematic. Click here for more details.

Files changed (271) hide show
  1. package/CONTRIBUTING.md +77 -0
  2. package/LICENSE +184 -0
  3. package/README.md +136 -0
  4. package/THIRD_PARTY_LICENSES.md +17 -0
  5. package/dist/src/agent.d.ts +30 -0
  6. package/dist/src/agent.js +216 -0
  7. package/dist/src/agent.js.map +1 -0
  8. package/dist/src/approvals.d.ts +18 -0
  9. package/dist/src/approvals.js +81 -0
  10. package/dist/src/approvals.js.map +1 -0
  11. package/dist/src/cli.d.ts +2 -0
  12. package/dist/src/cli.js +87 -0
  13. package/dist/src/cli.js.map +1 -0
  14. package/dist/src/config.d.ts +12 -0
  15. package/dist/src/config.js +183 -0
  16. package/dist/src/config.js.map +1 -0
  17. package/dist/src/context-memory.d.ts +7 -0
  18. package/dist/src/context-memory.js +96 -0
  19. package/dist/src/context-memory.js.map +1 -0
  20. package/dist/src/ink/command-suggestions.d.ts +7 -0
  21. package/dist/src/ink/command-suggestions.js +179 -0
  22. package/dist/src/ink/command-suggestions.js.map +1 -0
  23. package/dist/src/ink/ink-terminal-ui.d.ts +36 -0
  24. package/dist/src/ink/ink-terminal-ui.js +79 -0
  25. package/dist/src/ink/ink-terminal-ui.js.map +1 -0
  26. package/dist/src/ink/repl-app.d.ts +9 -0
  27. package/dist/src/ink/repl-app.js +789 -0
  28. package/dist/src/ink/repl-app.js.map +1 -0
  29. package/dist/src/ink/transcript-cards.d.ts +6 -0
  30. package/dist/src/ink/transcript-cards.js +24 -0
  31. package/dist/src/ink/transcript-cards.js.map +1 -0
  32. package/dist/src/path-policy.d.ts +11 -0
  33. package/dist/src/path-policy.js +67 -0
  34. package/dist/src/path-policy.js.map +1 -0
  35. package/dist/src/process-utils.d.ts +13 -0
  36. package/dist/src/process-utils.js +52 -0
  37. package/dist/src/process-utils.js.map +1 -0
  38. package/dist/src/repl.d.ts +9 -0
  39. package/dist/src/repl.js +13 -0
  40. package/dist/src/repl.js.map +1 -0
  41. package/dist/src/sarvam/client.d.ts +15 -0
  42. package/dist/src/sarvam/client.js +208 -0
  43. package/dist/src/sarvam/client.js.map +1 -0
  44. package/dist/src/sarvam/models.d.ts +2 -0
  45. package/dist/src/sarvam/models.js +7 -0
  46. package/dist/src/sarvam/models.js.map +1 -0
  47. package/dist/src/search-provider.d.ts +6 -0
  48. package/dist/src/search-provider.js +8 -0
  49. package/dist/src/search-provider.js.map +1 -0
  50. package/dist/src/session-store.d.ts +19 -0
  51. package/dist/src/session-store.js +318 -0
  52. package/dist/src/session-store.js.map +1 -0
  53. package/dist/src/skills/runtime.d.ts +26 -0
  54. package/dist/src/skills/runtime.js +317 -0
  55. package/dist/src/skills/runtime.js.map +1 -0
  56. package/dist/src/skills/types.d.ts +25 -0
  57. package/dist/src/skills/types.js +2 -0
  58. package/dist/src/skills/types.js.map +1 -0
  59. package/dist/src/terminal-ui.d.ts +29 -0
  60. package/dist/src/terminal-ui.js +236 -0
  61. package/dist/src/terminal-ui.js.map +1 -0
  62. package/dist/src/tools/filesystem.d.ts +2 -0
  63. package/dist/src/tools/filesystem.js +622 -0
  64. package/dist/src/tools/filesystem.js.map +1 -0
  65. package/dist/src/tools/git.d.ts +2 -0
  66. package/dist/src/tools/git.js +326 -0
  67. package/dist/src/tools/git.js.map +1 -0
  68. package/dist/src/tools/index.d.ts +6 -0
  69. package/dist/src/tools/index.js +21 -0
  70. package/dist/src/tools/index.js.map +1 -0
  71. package/dist/src/tools/registry.d.ts +15 -0
  72. package/dist/src/tools/registry.js +59 -0
  73. package/dist/src/tools/registry.js.map +1 -0
  74. package/dist/src/tools/shell.d.ts +2 -0
  75. package/dist/src/tools/shell.js +97 -0
  76. package/dist/src/tools/shell.js.map +1 -0
  77. package/dist/src/tools/skill.d.ts +3 -0
  78. package/dist/src/tools/skill.js +130 -0
  79. package/dist/src/tools/skill.js.map +1 -0
  80. package/dist/src/tools/web.d.ts +3 -0
  81. package/dist/src/tools/web.js +144 -0
  82. package/dist/src/tools/web.js.map +1 -0
  83. package/dist/src/types.d.ts +236 -0
  84. package/dist/src/types.js +2 -0
  85. package/dist/src/types.js.map +1 -0
  86. package/dist/src/workspace-trust.d.ts +3 -0
  87. package/dist/src/workspace-trust.js +31 -0
  88. package/dist/src/workspace-trust.js.map +1 -0
  89. package/dist/src/xdg.d.ts +9 -0
  90. package/dist/src/xdg.js +77 -0
  91. package/dist/src/xdg.js.map +1 -0
  92. package/package.json +57 -0
  93. package/skill/agents-md-generator/SKILL.md +75 -0
  94. package/skill/agents-md-generator/references/agents_md_template.md +160 -0
  95. package/skill/agents-md-generator/references/loc_measurement.md +67 -0
  96. package/skill/agents-md-generator/references/monorepo_detection.md +78 -0
  97. package/skill/agents-md-generator/references/monorepo_strategy.md +60 -0
  98. package/skill/agents-md-generator/references/read_only_commands.md +151 -0
  99. package/skill/agents-md-generator/references/update_strategy.md +160 -0
  100. package/skill/agents-md-generator/references/working_agreements.md +53 -0
  101. package/skill/biz-opportunity-scout/SKILL.md +53 -0
  102. package/skill/biz-opportunity-scout/references/competitive_analysis.md +84 -0
  103. package/skill/biz-opportunity-scout/references/market_sizing.md +68 -0
  104. package/skill/biz-opportunity-scout/references/pmf_indicators.md +94 -0
  105. package/skill/biz-opportunity-scout/references/report_template.md +243 -0
  106. package/skill/biz-opportunity-scout/references/unit_economics.md +97 -0
  107. package/skill/code-review/SKILL.md +86 -0
  108. package/skill/code-review/references/change_analysis.md +116 -0
  109. package/skill/code-review/references/git_operations.md +115 -0
  110. package/skill/code-review/references/impact_detection.md +149 -0
  111. package/skill/code-review/references/output_format.md +137 -0
  112. package/skill/code-review/references/severity_criteria.md +100 -0
  113. package/skill/code-security-audit/SKILL.md +123 -0
  114. package/skill/code-security-audit/references/audit_process.md +277 -0
  115. package/skill/code-security-audit/references/remediation_patterns.md +599 -0
  116. package/skill/code-security-audit/references/report_format.md +391 -0
  117. package/skill/code-security-audit/references/security_domains.md +830 -0
  118. package/skill/code-security-audit/references/vulnerability_patterns.md +813 -0
  119. package/skill/composition-patterns/SKILL.md +83 -0
  120. package/skill/composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
  121. package/skill/composition-patterns/rules/architecture-compound-components.md +112 -0
  122. package/skill/composition-patterns/rules/patterns-children-over-render-props.md +87 -0
  123. package/skill/composition-patterns/rules/patterns-explicit-variants.md +100 -0
  124. package/skill/composition-patterns/rules/react19-no-forwardref.md +42 -0
  125. package/skill/composition-patterns/rules/state-context-interface.md +191 -0
  126. package/skill/composition-patterns/rules/state-decouple-implementation.md +113 -0
  127. package/skill/composition-patterns/rules/state-lift-state.md +125 -0
  128. package/skill/deploy-to-vercel/SKILL.md +293 -0
  129. package/skill/deploy-to-vercel/resources/deploy-sandbox.sh +301 -0
  130. package/skill/deploy-to-vercel/resources/deploy.sh +301 -0
  131. package/skill/doc/SKILL_GUIDELINES.md +138 -0
  132. package/skill/git-workflow/SKILL.md +94 -0
  133. package/skill/git-workflow/references/advanced-git.md +632 -0
  134. package/skill/git-workflow/references/branching-strategies.md +344 -0
  135. package/skill/git-workflow/references/ci-cd-integration.md +683 -0
  136. package/skill/git-workflow/references/code-quality-tools.md +351 -0
  137. package/skill/git-workflow/references/commit-conventions.md +439 -0
  138. package/skill/git-workflow/references/github-releases.md +288 -0
  139. package/skill/git-workflow/references/pull-request-workflow.md +773 -0
  140. package/skill/git-workflow/scripts/verify-git-workflow.sh +263 -0
  141. package/skill/jetbrains-vmoptions/SKILL.md +51 -0
  142. package/skill/jetbrains-vmoptions/references/common-options.md +357 -0
  143. package/skill/jetbrains-vmoptions/references/gc-options.md +350 -0
  144. package/skill/jetbrains-vmoptions/references/memory-options.md +339 -0
  145. package/skill/jetbrains-vmoptions/references/prerequisite-check.md +65 -0
  146. package/skill/kysely-converter/SKILL.md +62 -0
  147. package/skill/kysely-converter/references/delete.md +323 -0
  148. package/skill/kysely-converter/references/insert.md +386 -0
  149. package/skill/kysely-converter/references/operators.md +331 -0
  150. package/skill/kysely-converter/references/select.md +1000 -0
  151. package/skill/kysely-converter/references/update.md +349 -0
  152. package/skill/kysely-converter/references/window_function.md +537 -0
  153. package/skill/react-best-practices/SKILL.md +131 -0
  154. package/skill/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  155. package/skill/react-best-practices/rules/advanced-init-once.md +42 -0
  156. package/skill/react-best-practices/rules/advanced-use-latest.md +39 -0
  157. package/skill/react-best-practices/rules/async-api-routes.md +38 -0
  158. package/skill/react-best-practices/rules/async-defer-await.md +80 -0
  159. package/skill/react-best-practices/rules/async-dependencies.md +51 -0
  160. package/skill/react-best-practices/rules/async-parallel.md +28 -0
  161. package/skill/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  162. package/skill/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  163. package/skill/react-best-practices/rules/bundle-conditional.md +31 -0
  164. package/skill/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  165. package/skill/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  166. package/skill/react-best-practices/rules/bundle-preload.md +50 -0
  167. package/skill/react-best-practices/rules/client-event-listeners.md +74 -0
  168. package/skill/react-best-practices/rules/client-localstorage-schema.md +71 -0
  169. package/skill/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  170. package/skill/react-best-practices/rules/client-swr-dedup.md +56 -0
  171. package/skill/react-best-practices/rules/js-batch-dom-css.md +107 -0
  172. package/skill/react-best-practices/rules/js-cache-function-results.md +80 -0
  173. package/skill/react-best-practices/rules/js-cache-property-access.md +28 -0
  174. package/skill/react-best-practices/rules/js-cache-storage.md +70 -0
  175. package/skill/react-best-practices/rules/js-combine-iterations.md +32 -0
  176. package/skill/react-best-practices/rules/js-early-exit.md +50 -0
  177. package/skill/react-best-practices/rules/js-hoist-regexp.md +45 -0
  178. package/skill/react-best-practices/rules/js-index-maps.md +37 -0
  179. package/skill/react-best-practices/rules/js-length-check-first.md +49 -0
  180. package/skill/react-best-practices/rules/js-min-max-loop.md +82 -0
  181. package/skill/react-best-practices/rules/js-set-map-lookups.md +24 -0
  182. package/skill/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  183. package/skill/react-best-practices/rules/rendering-activity.md +26 -0
  184. package/skill/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  185. package/skill/react-best-practices/rules/rendering-conditional-render.md +40 -0
  186. package/skill/react-best-practices/rules/rendering-content-visibility.md +38 -0
  187. package/skill/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  188. package/skill/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  189. package/skill/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  190. package/skill/react-best-practices/rules/rendering-svg-precision.md +28 -0
  191. package/skill/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  192. package/skill/react-best-practices/rules/rerender-defer-reads.md +39 -0
  193. package/skill/react-best-practices/rules/rerender-dependencies.md +45 -0
  194. package/skill/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  195. package/skill/react-best-practices/rules/rerender-derived-state.md +29 -0
  196. package/skill/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  197. package/skill/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  198. package/skill/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  199. package/skill/react-best-practices/rules/rerender-memo.md +44 -0
  200. package/skill/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  201. package/skill/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  202. package/skill/react-best-practices/rules/rerender-transitions.md +40 -0
  203. package/skill/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  204. package/skill/react-best-practices/rules/server-after-nonblocking.md +73 -0
  205. package/skill/react-best-practices/rules/server-auth-actions.md +96 -0
  206. package/skill/react-best-practices/rules/server-cache-lru.md +41 -0
  207. package/skill/react-best-practices/rules/server-cache-react.md +76 -0
  208. package/skill/react-best-practices/rules/server-dedup-props.md +65 -0
  209. package/skill/react-best-practices/rules/server-hoist-static-io.md +142 -0
  210. package/skill/react-best-practices/rules/server-parallel-fetching.md +83 -0
  211. package/skill/react-best-practices/rules/server-serialization.md +38 -0
  212. package/skill/react-native-skills/SKILL.md +115 -0
  213. package/skill/react-native-skills/rules/animation-derived-value.md +53 -0
  214. package/skill/react-native-skills/rules/animation-gesture-detector-press.md +95 -0
  215. package/skill/react-native-skills/rules/animation-gpu-properties.md +65 -0
  216. package/skill/react-native-skills/rules/design-system-compound-components.md +66 -0
  217. package/skill/react-native-skills/rules/fonts-config-plugin.md +71 -0
  218. package/skill/react-native-skills/rules/imports-design-system-folder.md +68 -0
  219. package/skill/react-native-skills/rules/js-hoist-intl.md +61 -0
  220. package/skill/react-native-skills/rules/list-performance-callbacks.md +44 -0
  221. package/skill/react-native-skills/rules/list-performance-function-references.md +132 -0
  222. package/skill/react-native-skills/rules/list-performance-images.md +53 -0
  223. package/skill/react-native-skills/rules/list-performance-inline-objects.md +97 -0
  224. package/skill/react-native-skills/rules/list-performance-item-expensive.md +94 -0
  225. package/skill/react-native-skills/rules/list-performance-item-memo.md +82 -0
  226. package/skill/react-native-skills/rules/list-performance-item-types.md +104 -0
  227. package/skill/react-native-skills/rules/list-performance-virtualize.md +67 -0
  228. package/skill/react-native-skills/rules/monorepo-native-deps-in-app.md +46 -0
  229. package/skill/react-native-skills/rules/monorepo-single-dependency-versions.md +63 -0
  230. package/skill/react-native-skills/rules/navigation-native-navigators.md +188 -0
  231. package/skill/react-native-skills/rules/react-compiler-destructure-functions.md +50 -0
  232. package/skill/react-native-skills/rules/react-compiler-reanimated-shared-values.md +48 -0
  233. package/skill/react-native-skills/rules/react-state-dispatcher.md +91 -0
  234. package/skill/react-native-skills/rules/react-state-fallback.md +56 -0
  235. package/skill/react-native-skills/rules/react-state-minimize.md +65 -0
  236. package/skill/react-native-skills/rules/rendering-no-falsy-and.md +74 -0
  237. package/skill/react-native-skills/rules/rendering-text-in-text-component.md +36 -0
  238. package/skill/react-native-skills/rules/scroll-position-no-state.md +82 -0
  239. package/skill/react-native-skills/rules/state-ground-truth.md +80 -0
  240. package/skill/react-native-skills/rules/ui-expo-image.md +66 -0
  241. package/skill/react-native-skills/rules/ui-image-gallery.md +104 -0
  242. package/skill/react-native-skills/rules/ui-measure-views.md +78 -0
  243. package/skill/react-native-skills/rules/ui-menus.md +174 -0
  244. package/skill/react-native-skills/rules/ui-native-modals.md +77 -0
  245. package/skill/react-native-skills/rules/ui-pressable.md +61 -0
  246. package/skill/react-native-skills/rules/ui-safe-area-scroll.md +65 -0
  247. package/skill/react-native-skills/rules/ui-scrollview-content-inset.md +45 -0
  248. package/skill/react-native-skills/rules/ui-styling.md +87 -0
  249. package/skill/react-vite-guide/SKILL.md +101 -0
  250. package/skill/react-vite-guide/references/composition-patterns.md +709 -0
  251. package/skill/react-vite-guide/references/performance-optimization.md +1222 -0
  252. package/skill/react-vite-guide/references/vite-specific.md +385 -0
  253. package/skill/react-vite-guide/references/web-interface.md +146 -0
  254. package/skill/skill-maker/SKILL.md +52 -0
  255. package/skill/skill-maker/references/content_spec.md +67 -0
  256. package/skill/skill-maker/references/frontmatter_spec.md +96 -0
  257. package/skill/skill-maker/references/input_validation.md +90 -0
  258. package/skill/skill-maker/references/skill_structure.md +74 -0
  259. package/skill/system-prompt-creator/SKILL.md +50 -0
  260. package/skill/system-prompt-creator/references/data_format_selection.md +135 -0
  261. package/skill/system-prompt-creator/references/multi_prompt_architecture.md +386 -0
  262. package/skill/system-prompt-creator/references/prompt_structure.md +140 -0
  263. package/skill/system-prompt-creator/references/quality_criteria.md +83 -0
  264. package/skill/typst-creator/SKILL.md +51 -0
  265. package/skill/typst-creator/references/layout.md +401 -0
  266. package/skill/typst-creator/references/math.md +297 -0
  267. package/skill/typst-creator/references/scripting.md +237 -0
  268. package/skill/typst-creator/references/styling.md +217 -0
  269. package/skill/typst-creator/references/syntax.md +234 -0
  270. package/skill/web-design-guidelines/SKILL.md +35 -0
  271. package/terminal.png +0 -0
@@ -0,0 +1,96 @@
1
+ ---
2
+ title: Authenticate Server Actions Like API Routes
3
+ impact: CRITICAL
4
+ impactDescription: prevents unauthorized access to server mutations
5
+ tags: server, server-actions, authentication, security, authorization
6
+ ---
7
+
8
+ ## Authenticate Server Actions Like API Routes
9
+
10
+ **Impact: CRITICAL (prevents unauthorized access to server mutations)**
11
+
12
+ Server Actions (functions with `"use server"`) are exposed as public endpoints, just like API routes. Always verify authentication and authorization **inside** each Server Action—do not rely solely on middleware, layout guards, or page-level checks, as Server Actions can be invoked directly.
13
+
14
+ Next.js documentation explicitly states: "Treat Server Actions with the same security considerations as public-facing API endpoints, and verify if the user is allowed to perform a mutation."
15
+
16
+ **Incorrect (no authentication check):**
17
+
18
+ ```typescript
19
+ 'use server'
20
+
21
+ export async function deleteUser(userId: string) {
22
+ // Anyone can call this! No auth check
23
+ await db.user.delete({ where: { id: userId } })
24
+ return { success: true }
25
+ }
26
+ ```
27
+
28
+ **Correct (authentication inside the action):**
29
+
30
+ ```typescript
31
+ 'use server'
32
+
33
+ import { verifySession } from '@/lib/auth'
34
+ import { unauthorized } from '@/lib/errors'
35
+
36
+ export async function deleteUser(userId: string) {
37
+ // Always check auth inside the action
38
+ const session = await verifySession()
39
+
40
+ if (!session) {
41
+ throw unauthorized('Must be logged in')
42
+ }
43
+
44
+ // Check authorization too
45
+ if (session.user.role !== 'admin' && session.user.id !== userId) {
46
+ throw unauthorized('Cannot delete other users')
47
+ }
48
+
49
+ await db.user.delete({ where: { id: userId } })
50
+ return { success: true }
51
+ }
52
+ ```
53
+
54
+ **With input validation:**
55
+
56
+ ```typescript
57
+ 'use server'
58
+
59
+ import { verifySession } from '@/lib/auth'
60
+ import { z } from 'zod'
61
+
62
+ const updateProfileSchema = z.object({
63
+ userId: z.string().uuid(),
64
+ name: z.string().min(1).max(100),
65
+ email: z.string().email()
66
+ })
67
+
68
+ export async function updateProfile(data: unknown) {
69
+ // Validate input first
70
+ const validated = updateProfileSchema.parse(data)
71
+
72
+ // Then authenticate
73
+ const session = await verifySession()
74
+ if (!session) {
75
+ throw new Error('Unauthorized')
76
+ }
77
+
78
+ // Then authorize
79
+ if (session.user.id !== validated.userId) {
80
+ throw new Error('Can only update own profile')
81
+ }
82
+
83
+ // Finally perform the mutation
84
+ await db.user.update({
85
+ where: { id: validated.userId },
86
+ data: {
87
+ name: validated.name,
88
+ email: validated.email
89
+ }
90
+ })
91
+
92
+ return { success: true }
93
+ }
94
+ ```
95
+
96
+ Reference: [https://nextjs.org/docs/app/guides/authentication](https://nextjs.org/docs/app/guides/authentication)
@@ -0,0 +1,41 @@
1
+ ---
2
+ title: Cross-Request LRU Caching
3
+ impact: HIGH
4
+ impactDescription: caches across requests
5
+ tags: server, cache, lru, cross-request
6
+ ---
7
+
8
+ ## Cross-Request LRU Caching
9
+
10
+ `React.cache()` only works within one request. For data shared across sequential requests (user clicks button A then button B), use an LRU cache.
11
+
12
+ **Implementation:**
13
+
14
+ ```typescript
15
+ import { LRUCache } from 'lru-cache'
16
+
17
+ const cache = new LRUCache<string, any>({
18
+ max: 1000,
19
+ ttl: 5 * 60 * 1000 // 5 minutes
20
+ })
21
+
22
+ export async function getUser(id: string) {
23
+ const cached = cache.get(id)
24
+ if (cached) return cached
25
+
26
+ const user = await db.user.findUnique({ where: { id } })
27
+ cache.set(id, user)
28
+ return user
29
+ }
30
+
31
+ // Request 1: DB query, result cached
32
+ // Request 2: cache hit, no DB query
33
+ ```
34
+
35
+ Use when sequential user actions hit multiple endpoints needing the same data within seconds.
36
+
37
+ **With Vercel's [Fluid Compute](https://vercel.com/docs/fluid-compute):** LRU caching is especially effective because multiple concurrent requests can share the same function instance and cache. This means the cache persists across requests without needing external storage like Redis.
38
+
39
+ **In traditional serverless:** Each invocation runs in isolation, so consider Redis for cross-process caching.
40
+
41
+ Reference: [https://github.com/isaacs/node-lru-cache](https://github.com/isaacs/node-lru-cache)
@@ -0,0 +1,76 @@
1
+ ---
2
+ title: Per-Request Deduplication with React.cache()
3
+ impact: MEDIUM
4
+ impactDescription: deduplicates within request
5
+ tags: server, cache, react-cache, deduplication
6
+ ---
7
+
8
+ ## Per-Request Deduplication with React.cache()
9
+
10
+ Use `React.cache()` for server-side request deduplication. Authentication and database queries benefit most.
11
+
12
+ **Usage:**
13
+
14
+ ```typescript
15
+ import { cache } from 'react'
16
+
17
+ export const getCurrentUser = cache(async () => {
18
+ const session = await auth()
19
+ if (!session?.user?.id) return null
20
+ return await db.user.findUnique({
21
+ where: { id: session.user.id }
22
+ })
23
+ })
24
+ ```
25
+
26
+ Within a single request, multiple calls to `getCurrentUser()` execute the query only once.
27
+
28
+ **Avoid inline objects as arguments:**
29
+
30
+ `React.cache()` uses shallow equality (`Object.is`) to determine cache hits. Inline objects create new references each call, preventing cache hits.
31
+
32
+ **Incorrect (always cache miss):**
33
+
34
+ ```typescript
35
+ const getUser = cache(async (params: { uid: number }) => {
36
+ return await db.user.findUnique({ where: { id: params.uid } })
37
+ })
38
+
39
+ // Each call creates new object, never hits cache
40
+ getUser({ uid: 1 })
41
+ getUser({ uid: 1 }) // Cache miss, runs query again
42
+ ```
43
+
44
+ **Correct (cache hit):**
45
+
46
+ ```typescript
47
+ const getUser = cache(async (uid: number) => {
48
+ return await db.user.findUnique({ where: { id: uid } })
49
+ })
50
+
51
+ // Primitive args use value equality
52
+ getUser(1)
53
+ getUser(1) // Cache hit, returns cached result
54
+ ```
55
+
56
+ If you must pass objects, pass the same reference:
57
+
58
+ ```typescript
59
+ const params = { uid: 1 }
60
+ getUser(params) // Query runs
61
+ getUser(params) // Cache hit (same reference)
62
+ ```
63
+
64
+ **Next.js-Specific Note:**
65
+
66
+ In Next.js, the `fetch` API is automatically extended with request memoization. Requests with the same URL and options are automatically deduplicated within a single request, so you don't need `React.cache()` for `fetch` calls. However, `React.cache()` is still essential for other async tasks:
67
+
68
+ - Database queries (Prisma, Drizzle, etc.)
69
+ - Heavy computations
70
+ - Authentication checks
71
+ - File system operations
72
+ - Any non-fetch async work
73
+
74
+ Use `React.cache()` to deduplicate these operations across your component tree.
75
+
76
+ Reference: [React.cache documentation](https://react.dev/reference/react/cache)
@@ -0,0 +1,65 @@
1
+ ---
2
+ title: Avoid Duplicate Serialization in RSC Props
3
+ impact: LOW
4
+ impactDescription: reduces network payload by avoiding duplicate serialization
5
+ tags: server, rsc, serialization, props, client-components
6
+ ---
7
+
8
+ ## Avoid Duplicate Serialization in RSC Props
9
+
10
+ **Impact: LOW (reduces network payload by avoiding duplicate serialization)**
11
+
12
+ RSC→client serialization deduplicates by object reference, not value. Same reference = serialized once; new reference = serialized again. Do transformations (`.toSorted()`, `.filter()`, `.map()`) in client, not server.
13
+
14
+ **Incorrect (duplicates array):**
15
+
16
+ ```tsx
17
+ // RSC: sends 6 strings (2 arrays × 3 items)
18
+ <ClientList usernames={usernames} usernamesOrdered={usernames.toSorted()} />
19
+ ```
20
+
21
+ **Correct (sends 3 strings):**
22
+
23
+ ```tsx
24
+ // RSC: send once
25
+ <ClientList usernames={usernames} />
26
+
27
+ // Client: transform there
28
+ 'use client'
29
+ const sorted = useMemo(() => [...usernames].sort(), [usernames])
30
+ ```
31
+
32
+ **Nested deduplication behavior:**
33
+
34
+ Deduplication works recursively. Impact varies by data type:
35
+
36
+ - `string[]`, `number[]`, `boolean[]`: **HIGH impact** - array + all primitives fully duplicated
37
+ - `object[]`: **LOW impact** - array duplicated, but nested objects deduplicated by reference
38
+
39
+ ```tsx
40
+ // string[] - duplicates everything
41
+ usernames={['a','b']} sorted={usernames.toSorted()} // sends 4 strings
42
+
43
+ // object[] - duplicates array structure only
44
+ users={[{id:1},{id:2}]} sorted={users.toSorted()} // sends 2 arrays + 2 unique objects (not 4)
45
+ ```
46
+
47
+ **Operations breaking deduplication (create new references):**
48
+
49
+ - Arrays: `.toSorted()`, `.filter()`, `.map()`, `.slice()`, `[...arr]`
50
+ - Objects: `{...obj}`, `Object.assign()`, `structuredClone()`, `JSON.parse(JSON.stringify())`
51
+
52
+ **More examples:**
53
+
54
+ ```tsx
55
+ // ❌ Bad
56
+ <C users={users} active={users.filter(u => u.active)} />
57
+ <C product={product} productName={product.name} />
58
+
59
+ // ✅ Good
60
+ <C users={users} />
61
+ <C product={product} />
62
+ // Do filtering/destructuring in client
63
+ ```
64
+
65
+ **Exception:** Pass derived data when transformation is expensive or client doesn't need original.
@@ -0,0 +1,142 @@
1
+ ---
2
+ title: Hoist Static I/O to Module Level
3
+ impact: HIGH
4
+ impactDescription: avoids repeated file/network I/O per request
5
+ tags: server, io, performance, next.js, route-handlers, og-image
6
+ ---
7
+
8
+ ## Hoist Static I/O to Module Level
9
+
10
+ **Impact: HIGH (avoids repeated file/network I/O per request)**
11
+
12
+ When loading static assets (fonts, logos, images, config files) in route handlers or server functions, hoist the I/O operation to module level. Module-level code runs once when the module is first imported, not on every request. This eliminates redundant file system reads or network fetches that would otherwise run on every invocation.
13
+
14
+ **Incorrect: reads font file on every request**
15
+
16
+ ```typescript
17
+ // app/api/og/route.tsx
18
+ import { ImageResponse } from 'next/og'
19
+
20
+ export async function GET(request: Request) {
21
+ // Runs on EVERY request - expensive!
22
+ const fontData = await fetch(
23
+ new URL('./fonts/Inter.ttf', import.meta.url)
24
+ ).then(res => res.arrayBuffer())
25
+
26
+ const logoData = await fetch(
27
+ new URL('./images/logo.png', import.meta.url)
28
+ ).then(res => res.arrayBuffer())
29
+
30
+ return new ImageResponse(
31
+ <div style={{ fontFamily: 'Inter' }}>
32
+ <img src={logoData} />
33
+ Hello World
34
+ </div>,
35
+ { fonts: [{ name: 'Inter', data: fontData }] }
36
+ )
37
+ }
38
+ ```
39
+
40
+ **Correct: loads once at module initialization**
41
+
42
+ ```typescript
43
+ // app/api/og/route.tsx
44
+ import { ImageResponse } from 'next/og'
45
+
46
+ // Module-level: runs ONCE when module is first imported
47
+ const fontData = fetch(
48
+ new URL('./fonts/Inter.ttf', import.meta.url)
49
+ ).then(res => res.arrayBuffer())
50
+
51
+ const logoData = fetch(
52
+ new URL('./images/logo.png', import.meta.url)
53
+ ).then(res => res.arrayBuffer())
54
+
55
+ export async function GET(request: Request) {
56
+ // Await the already-started promises
57
+ const [font, logo] = await Promise.all([fontData, logoData])
58
+
59
+ return new ImageResponse(
60
+ <div style={{ fontFamily: 'Inter' }}>
61
+ <img src={logo} />
62
+ Hello World
63
+ </div>,
64
+ { fonts: [{ name: 'Inter', data: font }] }
65
+ )
66
+ }
67
+ ```
68
+
69
+ **Alternative: synchronous file reads with Node.js fs**
70
+
71
+ ```typescript
72
+ // app/api/og/route.tsx
73
+ import { ImageResponse } from 'next/og'
74
+ import { readFileSync } from 'fs'
75
+ import { join } from 'path'
76
+
77
+ // Synchronous read at module level - blocks only during module init
78
+ const fontData = readFileSync(
79
+ join(process.cwd(), 'public/fonts/Inter.ttf')
80
+ )
81
+
82
+ const logoData = readFileSync(
83
+ join(process.cwd(), 'public/images/logo.png')
84
+ )
85
+
86
+ export async function GET(request: Request) {
87
+ return new ImageResponse(
88
+ <div style={{ fontFamily: 'Inter' }}>
89
+ <img src={logoData} />
90
+ Hello World
91
+ </div>,
92
+ { fonts: [{ name: 'Inter', data: fontData }] }
93
+ )
94
+ }
95
+ ```
96
+
97
+ **General Node.js example: loading config or templates**
98
+
99
+ ```typescript
100
+ // Incorrect: reads config on every call
101
+ export async function processRequest(data: Data) {
102
+ const config = JSON.parse(
103
+ await fs.readFile('./config.json', 'utf-8')
104
+ )
105
+ const template = await fs.readFile('./template.html', 'utf-8')
106
+
107
+ return render(template, data, config)
108
+ }
109
+
110
+ // Correct: loads once at module level
111
+ const configPromise = fs.readFile('./config.json', 'utf-8')
112
+ .then(JSON.parse)
113
+ const templatePromise = fs.readFile('./template.html', 'utf-8')
114
+
115
+ export async function processRequest(data: Data) {
116
+ const [config, template] = await Promise.all([
117
+ configPromise,
118
+ templatePromise
119
+ ])
120
+
121
+ return render(template, data, config)
122
+ }
123
+ ```
124
+
125
+ **When to use this pattern:**
126
+
127
+ - Loading fonts for OG image generation
128
+ - Loading static logos, icons, or watermarks
129
+ - Reading configuration files that don't change at runtime
130
+ - Loading email templates or other static templates
131
+ - Any static asset that's the same across all requests
132
+
133
+ **When NOT to use this pattern:**
134
+
135
+ - Assets that vary per request or user
136
+ - Files that may change during runtime (use caching with TTL instead)
137
+ - Large files that would consume too much memory if kept loaded
138
+ - Sensitive data that shouldn't persist in memory
139
+
140
+ **With Vercel's [Fluid Compute](https://vercel.com/docs/fluid-compute):** Module-level caching is especially effective because multiple concurrent requests share the same function instance. The static assets stay loaded in memory across requests without cold start penalties.
141
+
142
+ **In traditional serverless:** Each cold start re-executes module-level code, but subsequent warm invocations reuse the loaded assets until the instance is recycled.
@@ -0,0 +1,83 @@
1
+ ---
2
+ title: Parallel Data Fetching with Component Composition
3
+ impact: CRITICAL
4
+ impactDescription: eliminates server-side waterfalls
5
+ tags: server, rsc, parallel-fetching, composition
6
+ ---
7
+
8
+ ## Parallel Data Fetching with Component Composition
9
+
10
+ React Server Components execute sequentially within a tree. Restructure with composition to parallelize data fetching.
11
+
12
+ **Incorrect (Sidebar waits for Page's fetch to complete):**
13
+
14
+ ```tsx
15
+ export default async function Page() {
16
+ const header = await fetchHeader()
17
+ return (
18
+ <div>
19
+ <div>{header}</div>
20
+ <Sidebar />
21
+ </div>
22
+ )
23
+ }
24
+
25
+ async function Sidebar() {
26
+ const items = await fetchSidebarItems()
27
+ return <nav>{items.map(renderItem)}</nav>
28
+ }
29
+ ```
30
+
31
+ **Correct (both fetch simultaneously):**
32
+
33
+ ```tsx
34
+ async function Header() {
35
+ const data = await fetchHeader()
36
+ return <div>{data}</div>
37
+ }
38
+
39
+ async function Sidebar() {
40
+ const items = await fetchSidebarItems()
41
+ return <nav>{items.map(renderItem)}</nav>
42
+ }
43
+
44
+ export default function Page() {
45
+ return (
46
+ <div>
47
+ <Header />
48
+ <Sidebar />
49
+ </div>
50
+ )
51
+ }
52
+ ```
53
+
54
+ **Alternative with children prop:**
55
+
56
+ ```tsx
57
+ async function Header() {
58
+ const data = await fetchHeader()
59
+ return <div>{data}</div>
60
+ }
61
+
62
+ async function Sidebar() {
63
+ const items = await fetchSidebarItems()
64
+ return <nav>{items.map(renderItem)}</nav>
65
+ }
66
+
67
+ function Layout({ children }: { children: ReactNode }) {
68
+ return (
69
+ <div>
70
+ <Header />
71
+ {children}
72
+ </div>
73
+ )
74
+ }
75
+
76
+ export default function Page() {
77
+ return (
78
+ <Layout>
79
+ <Sidebar />
80
+ </Layout>
81
+ )
82
+ }
83
+ ```
@@ -0,0 +1,38 @@
1
+ ---
2
+ title: Minimize Serialization at RSC Boundaries
3
+ impact: HIGH
4
+ impactDescription: reduces data transfer size
5
+ tags: server, rsc, serialization, props
6
+ ---
7
+
8
+ ## Minimize Serialization at RSC Boundaries
9
+
10
+ The React Server/Client boundary serializes all object properties into strings and embeds them in the HTML response and subsequent RSC requests. This serialized data directly impacts page weight and load time, so **size matters a lot**. Only pass fields that the client actually uses.
11
+
12
+ **Incorrect (serializes all 50 fields):**
13
+
14
+ ```tsx
15
+ async function Page() {
16
+ const user = await fetchUser() // 50 fields
17
+ return <Profile user={user} />
18
+ }
19
+
20
+ 'use client'
21
+ function Profile({ user }: { user: User }) {
22
+ return <div>{user.name}</div> // uses 1 field
23
+ }
24
+ ```
25
+
26
+ **Correct (serializes only 1 field):**
27
+
28
+ ```tsx
29
+ async function Page() {
30
+ const user = await fetchUser()
31
+ return <Profile name={user.name} />
32
+ }
33
+
34
+ 'use client'
35
+ function Profile({ name }: { name: string }) {
36
+ return <div>{name}</div>
37
+ }
38
+ ```
@@ -0,0 +1,115 @@
1
+ ---
2
+ name: react-native-skills
3
+ description:
4
+ React Native and Expo best practices for building performant mobile apps. Use
5
+ when building React Native components, optimizing list performance,
6
+ implementing animations, or working with native modules. Triggers on tasks
7
+ involving React Native, Expo, mobile performance, or native platform APIs.
8
+ ---
9
+
10
+ # React Native Skills
11
+
12
+ Comprehensive best practices for React Native and Expo applications. Contains
13
+ rules across multiple categories covering performance, animations, UI patterns,
14
+ and platform-specific optimizations.
15
+
16
+ ## When to Apply
17
+
18
+ Reference these guidelines when:
19
+
20
+ - Building React Native or Expo apps
21
+ - Optimizing list and scroll performance
22
+ - Implementing animations with Reanimated
23
+ - Working with images and media
24
+ - Configuring native modules or fonts
25
+ - Structuring monorepo projects with native dependencies
26
+
27
+ ## Rule Categories by Priority
28
+
29
+ | Priority | Category | Impact | Prefix |
30
+ | -------- | ---------------- | -------- | -------------------- |
31
+ | 1 | List Performance | CRITICAL | `list-performance-` |
32
+ | 2 | Animation | HIGH | `animation-` |
33
+ | 3 | Navigation | HIGH | `navigation-` |
34
+ | 4 | UI Patterns | HIGH | `ui-` |
35
+ | 5 | State Management | MEDIUM | `react-state-` |
36
+ | 6 | Rendering | MEDIUM | `rendering-` |
37
+ | 7 | Monorepo | MEDIUM | `monorepo-` |
38
+ | 8 | Configuration | LOW | `fonts-`, `imports-` |
39
+
40
+ ## Quick Reference
41
+
42
+ ### 1. List Performance (CRITICAL)
43
+
44
+ - `list-performance-virtualize` - Use FlashList for large lists
45
+ - `list-performance-item-memo` - Memoize list item components
46
+ - `list-performance-callbacks` - Stabilize callback references
47
+ - `list-performance-inline-objects` - Avoid inline style objects
48
+ - `list-performance-function-references` - Extract functions outside render
49
+ - `list-performance-images` - Optimize images in lists
50
+ - `list-performance-item-expensive` - Move expensive work outside items
51
+ - `list-performance-item-types` - Use item types for heterogeneous lists
52
+
53
+ ### 2. Animation (HIGH)
54
+
55
+ - `animation-gpu-properties` - Animate only transform and opacity
56
+ - `animation-derived-value` - Use useDerivedValue for computed animations
57
+ - `animation-gesture-detector-press` - Use Gesture.Tap instead of Pressable
58
+
59
+ ### 3. Navigation (HIGH)
60
+
61
+ - `navigation-native-navigators` - Use native stack and native tabs over JS navigators
62
+
63
+ ### 4. UI Patterns (HIGH)
64
+
65
+ - `ui-expo-image` - Use expo-image for all images
66
+ - `ui-image-gallery` - Use Galeria for image lightboxes
67
+ - `ui-pressable` - Use Pressable over TouchableOpacity
68
+ - `ui-safe-area-scroll` - Handle safe areas in ScrollViews
69
+ - `ui-scrollview-content-inset` - Use contentInset for headers
70
+ - `ui-menus` - Use native context menus
71
+ - `ui-native-modals` - Use native modals when possible
72
+ - `ui-measure-views` - Use onLayout, not measure()
73
+ - `ui-styling` - Use StyleSheet.create or Nativewind
74
+
75
+ ### 5. State Management (MEDIUM)
76
+
77
+ - `react-state-minimize` - Minimize state subscriptions
78
+ - `react-state-dispatcher` - Use dispatcher pattern for callbacks
79
+ - `react-state-fallback` - Show fallback on first render
80
+ - `react-compiler-destructure-functions` - Destructure for React Compiler
81
+ - `react-compiler-reanimated-shared-values` - Handle shared values with compiler
82
+
83
+ ### 6. Rendering (MEDIUM)
84
+
85
+ - `rendering-text-in-text-component` - Wrap text in Text components
86
+ - `rendering-no-falsy-and` - Avoid falsy && for conditional rendering
87
+
88
+ ### 7. Monorepo (MEDIUM)
89
+
90
+ - `monorepo-native-deps-in-app` - Keep native dependencies in app package
91
+ - `monorepo-single-dependency-versions` - Use single versions across packages
92
+
93
+ ### 8. Configuration (LOW)
94
+
95
+ - `fonts-config-plugin` - Use config plugins for custom fonts
96
+ - `imports-design-system-folder` - Organize design system imports
97
+ - `js-hoist-intl` - Hoist Intl object creation
98
+
99
+ ## How to Use
100
+
101
+ Read individual rule files for detailed explanations and code examples:
102
+
103
+ ```
104
+ rules/list-performance-virtualize.md
105
+ rules/animation-gpu-properties.md
106
+ ```
107
+
108
+ Each rule file contains:
109
+
110
+ - Brief explanation of why it matters
111
+ - Incorrect code example with explanation
112
+ - Correct code example with explanation
113
+ - Additional context and references
114
+
115
+ Use the relevant files in `rules/` for the expanded guide.