@0xsown/vibe-code-fe 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 (189) hide show
  1. package/bin/index.js +181 -0
  2. package/package.json +32 -0
  3. package/skills/claude-md-improver/SKILL.md +179 -0
  4. package/skills/claude-md-improver/references/quality-criteria.md +109 -0
  5. package/skills/claude-md-improver/references/templates.md +253 -0
  6. package/skills/claude-md-improver/references/update-guidelines.md +150 -0
  7. package/skills/find-skills/SKILL.md +133 -0
  8. package/skills/frontend-design/LICENSE.txt +177 -0
  9. package/skills/frontend-design/SKILL.md +42 -0
  10. package/skills/next-best-practices/SKILL.md +153 -0
  11. package/skills/next-best-practices/async-patterns.md +87 -0
  12. package/skills/next-best-practices/bundling.md +180 -0
  13. package/skills/next-best-practices/data-patterns.md +297 -0
  14. package/skills/next-best-practices/debug-tricks.md +105 -0
  15. package/skills/next-best-practices/directives.md +73 -0
  16. package/skills/next-best-practices/error-handling.md +227 -0
  17. package/skills/next-best-practices/file-conventions.md +140 -0
  18. package/skills/next-best-practices/font.md +245 -0
  19. package/skills/next-best-practices/functions.md +108 -0
  20. package/skills/next-best-practices/hydration-error.md +91 -0
  21. package/skills/next-best-practices/image.md +173 -0
  22. package/skills/next-best-practices/metadata.md +301 -0
  23. package/skills/next-best-practices/parallel-routes.md +287 -0
  24. package/skills/next-best-practices/route-handlers.md +146 -0
  25. package/skills/next-best-practices/rsc-boundaries.md +159 -0
  26. package/skills/next-best-practices/runtime-selection.md +39 -0
  27. package/skills/next-best-practices/scripts.md +141 -0
  28. package/skills/next-best-practices/self-hosting.md +371 -0
  29. package/skills/next-best-practices/suspense-boundaries.md +67 -0
  30. package/skills/next-cache-components/SKILL.md +411 -0
  31. package/skills/shadcn-ui/README.md +248 -0
  32. package/skills/shadcn-ui/SKILL.md +326 -0
  33. package/skills/shadcn-ui/examples/auth-layout.tsx +177 -0
  34. package/skills/shadcn-ui/examples/data-table.tsx +313 -0
  35. package/skills/shadcn-ui/examples/form-pattern.tsx +177 -0
  36. package/skills/shadcn-ui/resources/component-catalog.md +481 -0
  37. package/skills/shadcn-ui/resources/customization-guide.md +516 -0
  38. package/skills/shadcn-ui/resources/migration-guide.md +463 -0
  39. package/skills/shadcn-ui/resources/setup-guide.md +412 -0
  40. package/skills/shadcn-ui/scripts/verify-setup.sh +134 -0
  41. package/skills/supabase-postgres-best-practices/AGENTS.md +68 -0
  42. package/skills/supabase-postgres-best-practices/CLAUDE.md +68 -0
  43. package/skills/supabase-postgres-best-practices/README.md +116 -0
  44. package/skills/supabase-postgres-best-practices/SKILL.md +64 -0
  45. package/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -0
  46. package/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -0
  47. package/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -0
  48. package/skills/supabase-postgres-best-practices/references/conn-limits.md +44 -0
  49. package/skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -0
  50. package/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -0
  51. package/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -0
  52. package/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -0
  53. package/skills/supabase-postgres-best-practices/references/data-pagination.md +50 -0
  54. package/skills/supabase-postgres-best-practices/references/data-upsert.md +50 -0
  55. package/skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -0
  56. package/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -0
  57. package/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -0
  58. package/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -0
  59. package/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -0
  60. package/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -0
  61. package/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -0
  62. package/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -0
  63. package/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -0
  64. package/skills/supabase-postgres-best-practices/references/query-index-types.md +48 -0
  65. package/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -0
  66. package/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -0
  67. package/skills/supabase-postgres-best-practices/references/schema-constraints.md +80 -0
  68. package/skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -0
  69. package/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -0
  70. package/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -0
  71. package/skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -0
  72. package/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -0
  73. package/skills/supabase-postgres-best-practices/references/security-privileges.md +54 -0
  74. package/skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -0
  75. package/skills/supabase-postgres-best-practices/references/security-rls-performance.md +57 -0
  76. package/skills/tailwind-design-system/SKILL.md +874 -0
  77. package/skills/vercel-composition-patterns/AGENTS.md +946 -0
  78. package/skills/vercel-composition-patterns/README.md +60 -0
  79. package/skills/vercel-composition-patterns/SKILL.md +89 -0
  80. package/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
  81. package/skills/vercel-composition-patterns/rules/architecture-compound-components.md +112 -0
  82. package/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md +87 -0
  83. package/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md +100 -0
  84. package/skills/vercel-composition-patterns/rules/react19-no-forwardref.md +42 -0
  85. package/skills/vercel-composition-patterns/rules/state-context-interface.md +191 -0
  86. package/skills/vercel-composition-patterns/rules/state-decouple-implementation.md +113 -0
  87. package/skills/vercel-composition-patterns/rules/state-lift-state.md +125 -0
  88. package/skills/vercel-react-best-practices/AGENTS.md +2934 -0
  89. package/skills/vercel-react-best-practices/README.md +123 -0
  90. package/skills/vercel-react-best-practices/SKILL.md +136 -0
  91. package/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  92. package/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  93. package/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  94. package/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  95. package/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
  96. package/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  97. package/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  98. package/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  99. package/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
  100. package/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  101. package/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  102. package/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  103. package/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  104. package/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  105. package/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  106. package/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  107. package/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  108. package/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  109. package/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  110. package/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  111. package/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  112. package/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  113. package/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  114. package/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  115. package/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  116. package/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  117. package/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  118. package/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  119. package/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  120. package/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  121. package/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  122. package/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  123. package/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  124. package/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  125. package/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  126. package/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  127. package/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  128. package/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  129. package/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  130. package/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  131. package/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  132. package/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  133. package/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  134. package/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  135. package/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  136. package/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  137. package/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  138. package/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  139. package/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  140. package/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  141. package/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  142. package/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  143. package/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  144. package/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  145. package/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  146. package/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  147. package/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  148. package/skills/vercel-react-native-skills/AGENTS.md +2897 -0
  149. package/skills/vercel-react-native-skills/README.md +165 -0
  150. package/skills/vercel-react-native-skills/SKILL.md +121 -0
  151. package/skills/vercel-react-native-skills/rules/animation-derived-value.md +53 -0
  152. package/skills/vercel-react-native-skills/rules/animation-gesture-detector-press.md +95 -0
  153. package/skills/vercel-react-native-skills/rules/animation-gpu-properties.md +65 -0
  154. package/skills/vercel-react-native-skills/rules/design-system-compound-components.md +66 -0
  155. package/skills/vercel-react-native-skills/rules/fonts-config-plugin.md +71 -0
  156. package/skills/vercel-react-native-skills/rules/imports-design-system-folder.md +68 -0
  157. package/skills/vercel-react-native-skills/rules/js-hoist-intl.md +61 -0
  158. package/skills/vercel-react-native-skills/rules/list-performance-callbacks.md +44 -0
  159. package/skills/vercel-react-native-skills/rules/list-performance-function-references.md +132 -0
  160. package/skills/vercel-react-native-skills/rules/list-performance-images.md +53 -0
  161. package/skills/vercel-react-native-skills/rules/list-performance-inline-objects.md +97 -0
  162. package/skills/vercel-react-native-skills/rules/list-performance-item-expensive.md +94 -0
  163. package/skills/vercel-react-native-skills/rules/list-performance-item-memo.md +82 -0
  164. package/skills/vercel-react-native-skills/rules/list-performance-item-types.md +104 -0
  165. package/skills/vercel-react-native-skills/rules/list-performance-virtualize.md +67 -0
  166. package/skills/vercel-react-native-skills/rules/monorepo-native-deps-in-app.md +46 -0
  167. package/skills/vercel-react-native-skills/rules/monorepo-single-dependency-versions.md +63 -0
  168. package/skills/vercel-react-native-skills/rules/navigation-native-navigators.md +188 -0
  169. package/skills/vercel-react-native-skills/rules/react-compiler-destructure-functions.md +50 -0
  170. package/skills/vercel-react-native-skills/rules/react-compiler-reanimated-shared-values.md +48 -0
  171. package/skills/vercel-react-native-skills/rules/react-state-dispatcher.md +91 -0
  172. package/skills/vercel-react-native-skills/rules/react-state-fallback.md +56 -0
  173. package/skills/vercel-react-native-skills/rules/react-state-minimize.md +65 -0
  174. package/skills/vercel-react-native-skills/rules/rendering-no-falsy-and.md +74 -0
  175. package/skills/vercel-react-native-skills/rules/rendering-text-in-text-component.md +36 -0
  176. package/skills/vercel-react-native-skills/rules/scroll-position-no-state.md +82 -0
  177. package/skills/vercel-react-native-skills/rules/state-ground-truth.md +80 -0
  178. package/skills/vercel-react-native-skills/rules/ui-expo-image.md +66 -0
  179. package/skills/vercel-react-native-skills/rules/ui-image-gallery.md +104 -0
  180. package/skills/vercel-react-native-skills/rules/ui-measure-views.md +78 -0
  181. package/skills/vercel-react-native-skills/rules/ui-menus.md +174 -0
  182. package/skills/vercel-react-native-skills/rules/ui-native-modals.md +77 -0
  183. package/skills/vercel-react-native-skills/rules/ui-pressable.md +61 -0
  184. package/skills/vercel-react-native-skills/rules/ui-safe-area-scroll.md +65 -0
  185. package/skills/vercel-react-native-skills/rules/ui-scrollview-content-inset.md +45 -0
  186. package/skills/vercel-react-native-skills/rules/ui-styling.md +87 -0
  187. package/skills/web-design-guidelines/SKILL.md +39 -0
  188. package/templates/AGENTS.md +31 -0
  189. package/templates/CLAUDE.md +31 -0
@@ -0,0 +1,67 @@
1
+ ---
2
+ title: Use a List Virtualizer for Any List
3
+ impact: HIGH
4
+ impactDescription: reduced memory, faster mounts
5
+ tags: lists, performance, virtualization, scrollview
6
+ ---
7
+
8
+ ## Use a List Virtualizer for Any List
9
+
10
+ Use a list virtualizer like LegendList or FlashList instead of ScrollView with
11
+ mapped children—even for short lists. Virtualizers only render visible items,
12
+ reducing memory usage and mount time. ScrollView renders all children upfront,
13
+ which gets expensive quickly.
14
+
15
+ **Incorrect (ScrollView renders all items at once):**
16
+
17
+ ```tsx
18
+ function Feed({ items }: { items: Item[] }) {
19
+ return (
20
+ <ScrollView>
21
+ {items.map((item) => (
22
+ <ItemCard key={item.id} item={item} />
23
+ ))}
24
+ </ScrollView>
25
+ )
26
+ }
27
+ // 50 items = 50 components mounted, even if only 10 visible
28
+ ```
29
+
30
+ **Correct (virtualizer renders only visible items):**
31
+
32
+ ```tsx
33
+ import { LegendList } from '@legendapp/list'
34
+
35
+ function Feed({ items }: { items: Item[] }) {
36
+ return (
37
+ <LegendList
38
+ data={items}
39
+ // if you aren't using React Compiler, wrap these with useCallback
40
+ renderItem={({ item }) => <ItemCard item={item} />}
41
+ keyExtractor={(item) => item.id}
42
+ estimatedItemSize={80}
43
+ />
44
+ )
45
+ }
46
+ // Only ~10-15 visible items mounted at a time
47
+ ```
48
+
49
+ **Alternative (FlashList):**
50
+
51
+ ```tsx
52
+ import { FlashList } from '@shopify/flash-list'
53
+
54
+ function Feed({ items }: { items: Item[] }) {
55
+ return (
56
+ <FlashList
57
+ data={items}
58
+ // if you aren't using React Compiler, wrap these with useCallback
59
+ renderItem={({ item }) => <ItemCard item={item} />}
60
+ keyExtractor={(item) => item.id}
61
+ />
62
+ )
63
+ }
64
+ ```
65
+
66
+ Benefits apply to any screen with scrollable content—profiles, settings, feeds,
67
+ search results. Default to virtualization.
@@ -0,0 +1,46 @@
1
+ ---
2
+ title: Install Native Dependencies in App Directory
3
+ impact: CRITICAL
4
+ impactDescription: required for autolinking to work
5
+ tags: monorepo, native, autolinking, installation
6
+ ---
7
+
8
+ ## Install Native Dependencies in App Directory
9
+
10
+ In a monorepo, packages with native code must be installed in the native app's
11
+ directory directly. Autolinking only scans the app's `node_modules`—it won't
12
+ find native dependencies installed in other packages.
13
+
14
+ **Incorrect (native dep in shared package only):**
15
+
16
+ ```
17
+ packages/
18
+ ui/
19
+ package.json # has react-native-reanimated
20
+ app/
21
+ package.json # missing react-native-reanimated
22
+ ```
23
+
24
+ Autolinking fails—native code not linked.
25
+
26
+ **Correct (native dep in app directory):**
27
+
28
+ ```
29
+ packages/
30
+ ui/
31
+ package.json # has react-native-reanimated
32
+ app/
33
+ package.json # also has react-native-reanimated
34
+ ```
35
+
36
+ ```json
37
+ // packages/app/package.json
38
+ {
39
+ "dependencies": {
40
+ "react-native-reanimated": "3.16.1"
41
+ }
42
+ }
43
+ ```
44
+
45
+ Even if the shared package uses the native dependency, the app must also list it
46
+ for autolinking to detect and link the native code.
@@ -0,0 +1,63 @@
1
+ ---
2
+ title: Use Single Dependency Versions Across Monorepo
3
+ impact: MEDIUM
4
+ impactDescription: avoids duplicate bundles, version conflicts
5
+ tags: monorepo, dependencies, installation
6
+ ---
7
+
8
+ ## Use Single Dependency Versions Across Monorepo
9
+
10
+ Use a single version of each dependency across all packages in your monorepo.
11
+ Prefer exact versions over ranges. Multiple versions cause duplicate code in
12
+ bundles, runtime conflicts, and inconsistent behavior across packages.
13
+
14
+ Use a tool like syncpack to enforce this. As a last resort, use yarn resolutions
15
+ or npm overrides.
16
+
17
+ **Incorrect (version ranges, multiple versions):**
18
+
19
+ ```json
20
+ // packages/app/package.json
21
+ {
22
+ "dependencies": {
23
+ "react-native-reanimated": "^3.0.0"
24
+ }
25
+ }
26
+
27
+ // packages/ui/package.json
28
+ {
29
+ "dependencies": {
30
+ "react-native-reanimated": "^3.5.0"
31
+ }
32
+ }
33
+ ```
34
+
35
+ **Correct (exact versions, single source of truth):**
36
+
37
+ ```json
38
+ // package.json (root)
39
+ {
40
+ "pnpm": {
41
+ "overrides": {
42
+ "react-native-reanimated": "3.16.1"
43
+ }
44
+ }
45
+ }
46
+
47
+ // packages/app/package.json
48
+ {
49
+ "dependencies": {
50
+ "react-native-reanimated": "3.16.1"
51
+ }
52
+ }
53
+
54
+ // packages/ui/package.json
55
+ {
56
+ "dependencies": {
57
+ "react-native-reanimated": "3.16.1"
58
+ }
59
+ }
60
+ ```
61
+
62
+ Use your package manager's override/resolution feature to enforce versions at
63
+ the root. When adding dependencies, specify exact versions without `^` or `~`.
@@ -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)