@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,188 @@
1
+ ---
2
+ title: Use Native Navigators for Navigation
3
+ impact: HIGH
4
+ impactDescription: native performance, platform-appropriate UI
5
+ tags: navigation, react-navigation, expo-router, native-stack, tabs
6
+ ---
7
+
8
+ ## Use Native Navigators for Navigation
9
+
10
+ Always use native navigators instead of JS-based ones. Native navigators use
11
+ platform APIs (UINavigationController on iOS, Fragment on Android) for better
12
+ performance and native behavior.
13
+
14
+ **For stacks:** Use `@react-navigation/native-stack` or expo-router's default
15
+ stack (which uses native-stack). Avoid `@react-navigation/stack`.
16
+
17
+ **For tabs:** Use `react-native-bottom-tabs` (native) or expo-router's native
18
+ tabs. Avoid `@react-navigation/bottom-tabs` when native feel matters.
19
+
20
+ ### Stack Navigation
21
+
22
+ **Incorrect (JS stack navigator):**
23
+
24
+ ```tsx
25
+ import { createStackNavigator } from '@react-navigation/stack'
26
+
27
+ const Stack = createStackNavigator()
28
+
29
+ function App() {
30
+ return (
31
+ <Stack.Navigator>
32
+ <Stack.Screen name='Home' component={HomeScreen} />
33
+ <Stack.Screen name='Details' component={DetailsScreen} />
34
+ </Stack.Navigator>
35
+ )
36
+ }
37
+ ```
38
+
39
+ **Correct (native stack with react-navigation):**
40
+
41
+ ```tsx
42
+ import { createNativeStackNavigator } from '@react-navigation/native-stack'
43
+
44
+ const Stack = createNativeStackNavigator()
45
+
46
+ function App() {
47
+ return (
48
+ <Stack.Navigator>
49
+ <Stack.Screen name='Home' component={HomeScreen} />
50
+ <Stack.Screen name='Details' component={DetailsScreen} />
51
+ </Stack.Navigator>
52
+ )
53
+ }
54
+ ```
55
+
56
+ **Correct (expo-router uses native stack by default):**
57
+
58
+ ```tsx
59
+ // app/_layout.tsx
60
+ import { Stack } from 'expo-router'
61
+
62
+ export default function Layout() {
63
+ return <Stack />
64
+ }
65
+ ```
66
+
67
+ ### Tab Navigation
68
+
69
+ **Incorrect (JS bottom tabs):**
70
+
71
+ ```tsx
72
+ import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
73
+
74
+ const Tab = createBottomTabNavigator()
75
+
76
+ function App() {
77
+ return (
78
+ <Tab.Navigator>
79
+ <Tab.Screen name='Home' component={HomeScreen} />
80
+ <Tab.Screen name='Settings' component={SettingsScreen} />
81
+ </Tab.Navigator>
82
+ )
83
+ }
84
+ ```
85
+
86
+ **Correct (native bottom tabs with react-navigation):**
87
+
88
+ ```tsx
89
+ import { createNativeBottomTabNavigator } from '@bottom-tabs/react-navigation'
90
+
91
+ const Tab = createNativeBottomTabNavigator()
92
+
93
+ function App() {
94
+ return (
95
+ <Tab.Navigator>
96
+ <Tab.Screen
97
+ name='Home'
98
+ component={HomeScreen}
99
+ options={{
100
+ tabBarIcon: () => ({ sfSymbol: 'house' }),
101
+ }}
102
+ />
103
+ <Tab.Screen
104
+ name='Settings'
105
+ component={SettingsScreen}
106
+ options={{
107
+ tabBarIcon: () => ({ sfSymbol: 'gear' }),
108
+ }}
109
+ />
110
+ </Tab.Navigator>
111
+ )
112
+ }
113
+ ```
114
+
115
+ **Correct (expo-router native tabs):**
116
+
117
+ ```tsx
118
+ // app/(tabs)/_layout.tsx
119
+ import { NativeTabs } from 'expo-router/unstable-native-tabs'
120
+
121
+ export default function TabLayout() {
122
+ return (
123
+ <NativeTabs>
124
+ <NativeTabs.Trigger name='index'>
125
+ <NativeTabs.Trigger.Label>Home</NativeTabs.Trigger.Label>
126
+ <NativeTabs.Trigger.Icon sf='house.fill' md='home' />
127
+ </NativeTabs.Trigger>
128
+ <NativeTabs.Trigger name='settings'>
129
+ <NativeTabs.Trigger.Label>Settings</NativeTabs.Trigger.Label>
130
+ <NativeTabs.Trigger.Icon sf='gear' md='settings' />
131
+ </NativeTabs.Trigger>
132
+ </NativeTabs>
133
+ )
134
+ }
135
+ ```
136
+
137
+ On iOS, native tabs automatically enable `contentInsetAdjustmentBehavior` on the
138
+ first `ScrollView` at the root of each tab screen, so content scrolls correctly
139
+ behind the translucent tab bar. If you need to disable this, use
140
+ `disableAutomaticContentInsets` on the trigger.
141
+
142
+ ### Prefer Native Header Options Over Custom Components
143
+
144
+ **Incorrect (custom header component):**
145
+
146
+ ```tsx
147
+ <Stack.Screen
148
+ name='Profile'
149
+ component={ProfileScreen}
150
+ options={{
151
+ header: () => <CustomHeader title='Profile' />,
152
+ }}
153
+ />
154
+ ```
155
+
156
+ **Correct (native header options):**
157
+
158
+ ```tsx
159
+ <Stack.Screen
160
+ name='Profile'
161
+ component={ProfileScreen}
162
+ options={{
163
+ title: 'Profile',
164
+ headerLargeTitleEnabled: true,
165
+ headerSearchBarOptions: {
166
+ placeholder: 'Search',
167
+ },
168
+ }}
169
+ />
170
+ ```
171
+
172
+ Native headers support iOS large titles, search bars, blur effects, and proper
173
+ safe area handling automatically.
174
+
175
+ ### Why Native Navigators
176
+
177
+ - **Performance**: Native transitions and gestures run on the UI thread
178
+ - **Platform behavior**: Automatic iOS large titles, Android material design
179
+ - **System integration**: Scroll-to-top on tab tap, PiP avoidance, proper safe
180
+ areas
181
+ - **Accessibility**: Platform accessibility features work automatically
182
+
183
+ Reference:
184
+
185
+ - [React Navigation Native Stack](https://reactnavigation.org/docs/native-stack-navigator)
186
+ - [React Native Bottom Tabs with React Navigation](https://oss.callstack.com/react-native-bottom-tabs/docs/guides/usage-with-react-navigation)
187
+ - [React Native Bottom Tabs with Expo Router](https://oss.callstack.com/react-native-bottom-tabs/docs/guides/usage-with-expo-router)
188
+ - [Expo Router Native Tabs](https://docs.expo.dev/router/advanced/native-tabs)
@@ -0,0 +1,50 @@
1
+ ---
2
+ title: Destructure Functions Early in Render (React Compiler)
3
+ impact: HIGH
4
+ impactDescription: stable references, fewer re-renders
5
+ tags: rerender, hooks, performance, react-compiler
6
+ ---
7
+
8
+ ## Destructure Functions Early in Render
9
+
10
+ This rule is only applicable if you are using the React Compiler.
11
+
12
+ Destructure functions from hooks at the top of render scope. Never dot into
13
+ objects to call functions. Destructured functions are stable references; dotting
14
+ creates new references and breaks memoization.
15
+
16
+ **Incorrect (dotting into object):**
17
+
18
+ ```tsx
19
+ import { useRouter } from 'expo-router'
20
+
21
+ function SaveButton(props) {
22
+ const router = useRouter()
23
+
24
+ // bad: react-compiler will key the cache on "props" and "router", which are objects that change each render
25
+ const handlePress = () => {
26
+ props.onSave()
27
+ router.push('/success') // unstable reference
28
+ }
29
+
30
+ return <Button onPress={handlePress}>Save</Button>
31
+ }
32
+ ```
33
+
34
+ **Correct (destructure early):**
35
+
36
+ ```tsx
37
+ import { useRouter } from 'expo-router'
38
+
39
+ function SaveButton({ onSave }) {
40
+ const { push } = useRouter()
41
+
42
+ // good: react-compiler will key on push and onSave
43
+ const handlePress = () => {
44
+ onSave()
45
+ push('/success') // stable reference
46
+ }
47
+
48
+ return <Button onPress={handlePress}>Save</Button>
49
+ }
50
+ ```
@@ -0,0 +1,48 @@
1
+ ---
2
+ title: Use .get() and .set() for Reanimated Shared Values (not .value)
3
+ impact: LOW
4
+ impactDescription: required for React Compiler compatibility
5
+ tags: reanimated, react-compiler, shared-values
6
+ ---
7
+
8
+ ## Use .get() and .set() for Shared Values with React Compiler
9
+
10
+ With React Compiler enabled, use `.get()` and `.set()` instead of reading or
11
+ writing `.value` directly on Reanimated shared values. The compiler can't track
12
+ property access—explicit methods ensure correct behavior.
13
+
14
+ **Incorrect (breaks with React Compiler):**
15
+
16
+ ```tsx
17
+ import { useSharedValue } from 'react-native-reanimated'
18
+
19
+ function Counter() {
20
+ const count = useSharedValue(0)
21
+
22
+ const increment = () => {
23
+ count.value = count.value + 1 // opts out of react compiler
24
+ }
25
+
26
+ return <Button onPress={increment} title={`Count: ${count.value}`} />
27
+ }
28
+ ```
29
+
30
+ **Correct (React Compiler compatible):**
31
+
32
+ ```tsx
33
+ import { useSharedValue } from 'react-native-reanimated'
34
+
35
+ function Counter() {
36
+ const count = useSharedValue(0)
37
+
38
+ const increment = () => {
39
+ count.set(count.get() + 1)
40
+ }
41
+
42
+ return <Button onPress={increment} title={`Count: ${count.get()}`} />
43
+ }
44
+ ```
45
+
46
+ See the
47
+ [Reanimated docs](https://docs.swmansion.com/react-native-reanimated/docs/core/useSharedValue/#react-compiler-support)
48
+ for more.
@@ -0,0 +1,91 @@
1
+ ---
2
+ title: useState Dispatch updaters for State That Depends on Current Value
3
+ impact: MEDIUM
4
+ impactDescription: avoids stale closures, prevents unnecessary re-renders
5
+ tags: state, hooks, useState, callbacks
6
+ ---
7
+
8
+ ## Use Dispatch Updaters for State That Depends on Current Value
9
+
10
+ When the next state depends on the current state, use a dispatch updater
11
+ (`setState(prev => ...)`) instead of reading the state variable directly in a
12
+ callback. This avoids stale closures and ensures you're comparing against the
13
+ latest value.
14
+
15
+ **Incorrect (reads state directly):**
16
+
17
+ ```tsx
18
+ const [size, setSize] = useState<Size | undefined>(undefined)
19
+
20
+ const onLayout = (e: LayoutChangeEvent) => {
21
+ const { width, height } = e.nativeEvent.layout
22
+ // size may be stale in this closure
23
+ if (size?.width !== width || size?.height !== height) {
24
+ setSize({ width, height })
25
+ }
26
+ }
27
+ ```
28
+
29
+ **Correct (dispatch updater):**
30
+
31
+ ```tsx
32
+ const [size, setSize] = useState<Size | undefined>(undefined)
33
+
34
+ const onLayout = (e: LayoutChangeEvent) => {
35
+ const { width, height } = e.nativeEvent.layout
36
+ setSize((prev) => {
37
+ if (prev?.width === width && prev?.height === height) return prev
38
+ return { width, height }
39
+ })
40
+ }
41
+ ```
42
+
43
+ Returning the previous value from the updater skips the re-render.
44
+
45
+ For primitive states, you don't need to compare values before firing a
46
+ re-render.
47
+
48
+ **Incorrect (unnecessary comparison for primitive state):**
49
+
50
+ ```tsx
51
+ const [size, setSize] = useState<Size | undefined>(undefined)
52
+
53
+ const onLayout = (e: LayoutChangeEvent) => {
54
+ const { width, height } = e.nativeEvent.layout
55
+ setSize((prev) => (prev === width ? prev : width))
56
+ }
57
+ ```
58
+
59
+ **Correct (sets primitive state directly):**
60
+
61
+ ```tsx
62
+ const [size, setSize] = useState<Size | undefined>(undefined)
63
+
64
+ const onLayout = (e: LayoutChangeEvent) => {
65
+ const { width, height } = e.nativeEvent.layout
66
+ setSize(width)
67
+ }
68
+ ```
69
+
70
+ However, if the next state depends on the current state, you should still use a
71
+ dispatch updater.
72
+
73
+ **Incorrect (reads state directly from the callback):**
74
+
75
+ ```tsx
76
+ const [count, setCount] = useState(0)
77
+
78
+ const onTap = () => {
79
+ setCount(count + 1)
80
+ }
81
+ ```
82
+
83
+ **Correct (dispatch updater):**
84
+
85
+ ```tsx
86
+ const [count, setCount] = useState(0)
87
+
88
+ const onTap = () => {
89
+ setCount((prev) => prev + 1)
90
+ }
91
+ ```
@@ -0,0 +1,56 @@
1
+ ---
2
+ title: Use fallback state instead of initialState
3
+ impact: MEDIUM
4
+ impactDescription: reactive fallbacks without syncing
5
+ tags: state, hooks, derived-state, props, initialState
6
+ ---
7
+
8
+ ## Use fallback state instead of initialState
9
+
10
+ Use `undefined` as initial state and nullish coalescing (`??`) to fall back to
11
+ parent or server values. State represents user intent only—`undefined` means
12
+ "user hasn't chosen yet." This enables reactive fallbacks that update when the
13
+ source changes, not just on initial render.
14
+
15
+ **Incorrect (syncs state, loses reactivity):**
16
+
17
+ ```tsx
18
+ type Props = { fallbackEnabled: boolean }
19
+
20
+ function Toggle({ fallbackEnabled }: Props) {
21
+ const [enabled, setEnabled] = useState(defaultEnabled)
22
+ // If fallbackEnabled changes, state is stale
23
+ // State mixes user intent with default value
24
+
25
+ return <Switch value={enabled} onValueChange={setEnabled} />
26
+ }
27
+ ```
28
+
29
+ **Correct (state is user intent, reactive fallback):**
30
+
31
+ ```tsx
32
+ type Props = { fallbackEnabled: boolean }
33
+
34
+ function Toggle({ fallbackEnabled }: Props) {
35
+ const [_enabled, setEnabled] = useState<boolean | undefined>(undefined)
36
+ const enabled = _enabled ?? defaultEnabled
37
+ // undefined = user hasn't touched it, falls back to prop
38
+ // If defaultEnabled changes, component reflects it
39
+ // Once user interacts, their choice persists
40
+
41
+ return <Switch value={enabled} onValueChange={setEnabled} />
42
+ }
43
+ ```
44
+
45
+ **With server data:**
46
+
47
+ ```tsx
48
+ function ProfileForm({ data }: { data: User }) {
49
+ const [_theme, setTheme] = useState<string | undefined>(undefined)
50
+ const theme = _theme ?? data.theme
51
+ // Shows server value until user overrides
52
+ // Server refetch updates the fallback automatically
53
+
54
+ return <ThemePicker value={theme} onChange={setTheme} />
55
+ }
56
+ ```
@@ -0,0 +1,65 @@
1
+ ---
2
+ title: Minimize State Variables and Derive Values
3
+ impact: MEDIUM
4
+ impactDescription: fewer re-renders, less state drift
5
+ tags: state, derived-state, hooks, optimization
6
+ ---
7
+
8
+ ## Minimize State Variables and Derive Values
9
+
10
+ Use the fewest state variables possible. If a value can be computed from existing state or props, derive it during render instead of storing it in state. Redundant state causes unnecessary re-renders and can drift out of sync.
11
+
12
+ **Incorrect (redundant state):**
13
+
14
+ ```tsx
15
+ function Cart({ items }: { items: Item[] }) {
16
+ const [total, setTotal] = useState(0)
17
+ const [itemCount, setItemCount] = useState(0)
18
+
19
+ useEffect(() => {
20
+ setTotal(items.reduce((sum, item) => sum + item.price, 0))
21
+ setItemCount(items.length)
22
+ }, [items])
23
+
24
+ return (
25
+ <View>
26
+ <Text>{itemCount} items</Text>
27
+ <Text>Total: ${total}</Text>
28
+ </View>
29
+ )
30
+ }
31
+ ```
32
+
33
+ **Correct (derived values):**
34
+
35
+ ```tsx
36
+ function Cart({ items }: { items: Item[] }) {
37
+ const total = items.reduce((sum, item) => sum + item.price, 0)
38
+ const itemCount = items.length
39
+
40
+ return (
41
+ <View>
42
+ <Text>{itemCount} items</Text>
43
+ <Text>Total: ${total}</Text>
44
+ </View>
45
+ )
46
+ }
47
+ ```
48
+
49
+ **Another example:**
50
+
51
+ ```tsx
52
+ // Incorrect: storing both firstName, lastName, AND fullName
53
+ const [firstName, setFirstName] = useState('')
54
+ const [lastName, setLastName] = useState('')
55
+ const [fullName, setFullName] = useState('')
56
+
57
+ // Correct: derive fullName
58
+ const [firstName, setFirstName] = useState('')
59
+ const [lastName, setLastName] = useState('')
60
+ const fullName = `${firstName} ${lastName}`
61
+ ```
62
+
63
+ State should be the minimal source of truth. Everything else is derived.
64
+
65
+ Reference: [Choosing the State Structure](https://react.dev/learn/choosing-the-state-structure)
@@ -0,0 +1,74 @@
1
+ ---
2
+ title: Never Use && with Potentially Falsy Values
3
+ impact: CRITICAL
4
+ impactDescription: prevents production crash
5
+ tags: rendering, conditional, jsx, crash
6
+ ---
7
+
8
+ ## Never Use && with Potentially Falsy Values
9
+
10
+ Never use `{value && <Component />}` when `value` could be an empty string or
11
+ `0`. These are falsy but JSX-renderable—React Native will try to render them as
12
+ text outside a `<Text>` component, causing a hard crash in production.
13
+
14
+ **Incorrect (crashes if count is 0 or name is ""):**
15
+
16
+ ```tsx
17
+ function Profile({ name, count }: { name: string; count: number }) {
18
+ return (
19
+ <View>
20
+ {name && <Text>{name}</Text>}
21
+ {count && <Text>{count} items</Text>}
22
+ </View>
23
+ )
24
+ }
25
+ // If name="" or count=0, renders the falsy value → crash
26
+ ```
27
+
28
+ **Correct (ternary with null):**
29
+
30
+ ```tsx
31
+ function Profile({ name, count }: { name: string; count: number }) {
32
+ return (
33
+ <View>
34
+ {name ? <Text>{name}</Text> : null}
35
+ {count ? <Text>{count} items</Text> : null}
36
+ </View>
37
+ )
38
+ }
39
+ ```
40
+
41
+ **Correct (explicit boolean coercion):**
42
+
43
+ ```tsx
44
+ function Profile({ name, count }: { name: string; count: number }) {
45
+ return (
46
+ <View>
47
+ {!!name && <Text>{name}</Text>}
48
+ {!!count && <Text>{count} items</Text>}
49
+ </View>
50
+ )
51
+ }
52
+ ```
53
+
54
+ **Best (early return):**
55
+
56
+ ```tsx
57
+ function Profile({ name, count }: { name: string; count: number }) {
58
+ if (!name) return null
59
+
60
+ return (
61
+ <View>
62
+ <Text>{name}</Text>
63
+ {count > 0 ? <Text>{count} items</Text> : null}
64
+ </View>
65
+ )
66
+ }
67
+ ```
68
+
69
+ Early returns are clearest. When using conditionals inline, prefer ternary or
70
+ explicit boolean checks.
71
+
72
+ **Lint rule:** Enable `react/jsx-no-leaked-render` from
73
+ [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-leaked-render.md)
74
+ to catch this automatically.
@@ -0,0 +1,36 @@
1
+ ---
2
+ title: Wrap Strings in Text Components
3
+ impact: CRITICAL
4
+ impactDescription: prevents runtime crash
5
+ tags: rendering, text, core
6
+ ---
7
+
8
+ ## Wrap Strings in Text Components
9
+
10
+ Strings must be rendered inside `<Text>`. React Native crashes if a string is a
11
+ direct child of `<View>`.
12
+
13
+ **Incorrect (crashes):**
14
+
15
+ ```tsx
16
+ import { View } from 'react-native'
17
+
18
+ function Greeting({ name }: { name: string }) {
19
+ return <View>Hello, {name}!</View>
20
+ }
21
+ // Error: Text strings must be rendered within a <Text> component.
22
+ ```
23
+
24
+ **Correct:**
25
+
26
+ ```tsx
27
+ import { View, Text } from 'react-native'
28
+
29
+ function Greeting({ name }: { name: string }) {
30
+ return (
31
+ <View>
32
+ <Text>Hello, {name}!</Text>
33
+ </View>
34
+ )
35
+ }
36
+ ```
@@ -0,0 +1,82 @@
1
+ ---
2
+ title: Never Track Scroll Position in useState
3
+ impact: HIGH
4
+ impactDescription: prevents render thrashing during scroll
5
+ tags: scroll, performance, reanimated, useRef
6
+ ---
7
+
8
+ ## Never Track Scroll Position in useState
9
+
10
+ Never store scroll position in `useState`. Scroll events fire rapidly—state
11
+ updates cause render thrashing and dropped frames. Use a Reanimated shared value
12
+ for animations or a ref for non-reactive tracking.
13
+
14
+ **Incorrect (useState causes jank):**
15
+
16
+ ```tsx
17
+ import { useState } from 'react'
18
+ import {
19
+ ScrollView,
20
+ NativeSyntheticEvent,
21
+ NativeScrollEvent,
22
+ } from 'react-native'
23
+
24
+ function Feed() {
25
+ const [scrollY, setScrollY] = useState(0)
26
+
27
+ const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
28
+ setScrollY(e.nativeEvent.contentOffset.y) // re-renders on every frame
29
+ }
30
+
31
+ return <ScrollView onScroll={onScroll} scrollEventThrottle={16} />
32
+ }
33
+ ```
34
+
35
+ **Correct (Reanimated for animations):**
36
+
37
+ ```tsx
38
+ import Animated, {
39
+ useSharedValue,
40
+ useAnimatedScrollHandler,
41
+ } from 'react-native-reanimated'
42
+
43
+ function Feed() {
44
+ const scrollY = useSharedValue(0)
45
+
46
+ const onScroll = useAnimatedScrollHandler({
47
+ onScroll: (e) => {
48
+ scrollY.value = e.contentOffset.y // runs on UI thread, no re-render
49
+ },
50
+ })
51
+
52
+ return (
53
+ <Animated.ScrollView
54
+ onScroll={onScroll}
55
+ // higher number has better performance, but it fires less often.
56
+ // unset this if you need higher precision over performance.
57
+ scrollEventThrottle={16}
58
+ />
59
+ )
60
+ }
61
+ ```
62
+
63
+ **Correct (ref for non-reactive tracking):**
64
+
65
+ ```tsx
66
+ import { useRef } from 'react'
67
+ import {
68
+ ScrollView,
69
+ NativeSyntheticEvent,
70
+ NativeScrollEvent,
71
+ } from 'react-native'
72
+
73
+ function Feed() {
74
+ const scrollY = useRef(0)
75
+
76
+ const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
77
+ scrollY.current = e.nativeEvent.contentOffset.y // no re-render
78
+ }
79
+
80
+ return <ScrollView onScroll={onScroll} scrollEventThrottle={16} />
81
+ }
82
+ ```