@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,61 @@
1
+ ---
2
+ title: Hoist Intl Formatter Creation
3
+ impact: LOW-MEDIUM
4
+ impactDescription: avoids expensive object recreation
5
+ tags: javascript, intl, optimization, memoization
6
+ ---
7
+
8
+ ## Hoist Intl Formatter Creation
9
+
10
+ Don't create `Intl.DateTimeFormat`, `Intl.NumberFormat`, or
11
+ `Intl.RelativeTimeFormat` inside render or loops. These are expensive to
12
+ instantiate. Hoist to module scope when the locale/options are static.
13
+
14
+ **Incorrect (new formatter every render):**
15
+
16
+ ```tsx
17
+ function Price({ amount }: { amount: number }) {
18
+ const formatter = new Intl.NumberFormat('en-US', {
19
+ style: 'currency',
20
+ currency: 'USD',
21
+ })
22
+ return <Text>{formatter.format(amount)}</Text>
23
+ }
24
+ ```
25
+
26
+ **Correct (hoisted to module scope):**
27
+
28
+ ```tsx
29
+ const currencyFormatter = new Intl.NumberFormat('en-US', {
30
+ style: 'currency',
31
+ currency: 'USD',
32
+ })
33
+
34
+ function Price({ amount }: { amount: number }) {
35
+ return <Text>{currencyFormatter.format(amount)}</Text>
36
+ }
37
+ ```
38
+
39
+ **For dynamic locales, memoize:**
40
+
41
+ ```tsx
42
+ const dateFormatter = useMemo(
43
+ () => new Intl.DateTimeFormat(locale, { dateStyle: 'medium' }),
44
+ [locale]
45
+ )
46
+ ```
47
+
48
+ **Common formatters to hoist:**
49
+
50
+ ```tsx
51
+ // Module-level formatters
52
+ const dateFormatter = new Intl.DateTimeFormat('en-US', { dateStyle: 'medium' })
53
+ const timeFormatter = new Intl.DateTimeFormat('en-US', { timeStyle: 'short' })
54
+ const percentFormatter = new Intl.NumberFormat('en-US', { style: 'percent' })
55
+ const relativeFormatter = new Intl.RelativeTimeFormat('en-US', {
56
+ numeric: 'auto',
57
+ })
58
+ ```
59
+
60
+ Creating `Intl` objects is significantly more expensive than `RegExp` or plain
61
+ objects—each instantiation parses locale data and builds internal lookup tables.
@@ -0,0 +1,44 @@
1
+ ---
2
+ title: Hoist callbacks to the root of lists
3
+ impact: MEDIUM
4
+ impactDescription: Fewer re-renders and faster lists
5
+ tags: tag1, tag2
6
+ ---
7
+
8
+ ## List performance callbacks
9
+
10
+ **Impact: HIGH (Fewer re-renders and faster lists)**
11
+
12
+ When passing callback functions to list items, create a single instance of the
13
+ callback at the root of the list. Items should then call it with a unique
14
+ identifier.
15
+
16
+ **Incorrect (creates a new callback on each render):**
17
+
18
+ ```typescript
19
+ return (
20
+ <LegendList
21
+ renderItem={({ item }) => {
22
+ // bad: creates a new callback on each render
23
+ const onPress = () => handlePress(item.id)
24
+ return <Item key={item.id} item={item} onPress={onPress} />
25
+ }}
26
+ />
27
+ )
28
+ ```
29
+
30
+ **Correct (a single function instance passed to each item):**
31
+
32
+ ```typescript
33
+ const onPress = useCallback(() => handlePress(item.id), [handlePress, item.id])
34
+
35
+ return (
36
+ <LegendList
37
+ renderItem={({ item }) => (
38
+ <Item key={item.id} item={item} onPress={onPress} />
39
+ )}
40
+ />
41
+ )
42
+ ```
43
+
44
+ Reference: [Link to documentation or resource](https://example.com)
@@ -0,0 +1,132 @@
1
+ ---
2
+ title: Optimize List Performance with Stable Object References
3
+ impact: CRITICAL
4
+ impactDescription: virtualization relies on reference stability
5
+ tags: lists, performance, flatlist, virtualization
6
+ ---
7
+
8
+ ## Optimize List Performance with Stable Object References
9
+
10
+ Don't map or filter data before passing to virtualized lists. Virtualization
11
+ relies on object reference stability to know what changed—new references cause
12
+ full re-renders of all visible items. Attempt to prevent frequent renders at the
13
+ list-parent level.
14
+
15
+ Where needed, use context selectors within list items.
16
+
17
+ **Incorrect (creates new object references on every keystroke):**
18
+
19
+ ```tsx
20
+ function DomainSearch() {
21
+ const { keyword, setKeyword } = useKeywordZustandState()
22
+ const { data: tlds } = useTlds()
23
+
24
+ // Bad: creates new objects on every render, reparenting the entire list on every keystroke
25
+ const domains = tlds.map((tld) => ({
26
+ domain: `${keyword}.${tld.name}`,
27
+ tld: tld.name,
28
+ price: tld.price,
29
+ }))
30
+
31
+ return (
32
+ <>
33
+ <TextInput value={keyword} onChangeText={setKeyword} />
34
+ <LegendList
35
+ data={domains}
36
+ renderItem={({ item }) => <DomainItem item={item} keyword={keyword} />}
37
+ />
38
+ </>
39
+ )
40
+ }
41
+ ```
42
+
43
+ **Correct (stable references, transform inside items):**
44
+
45
+ ```tsx
46
+ const renderItem = ({ item }) => <DomainItem tld={item} />
47
+
48
+ function DomainSearch() {
49
+ const { data: tlds } = useTlds()
50
+
51
+ return (
52
+ <LegendList
53
+ // good: as long as the data is stable, LegendList will not re-render the entire list
54
+ data={tlds}
55
+ renderItem={renderItem}
56
+ />
57
+ )
58
+ }
59
+
60
+ function DomainItem({ tld }: { tld: Tld }) {
61
+ // good: transform within items, and don't pass the dynamic data as a prop
62
+ // good: use a selector function from zustand to receive a stable string back
63
+ const domain = useKeywordZustandState((s) => s.keyword + '.' + tld.name)
64
+ return <Text>{domain}</Text>
65
+ }
66
+ ```
67
+
68
+ **Updating parent array reference:**
69
+
70
+ Creating a new array instance can be okay, as long as its inner object
71
+ references are stable. For instance, if you sort a list of objects:
72
+
73
+ ```tsx
74
+ // good: creates a new array instance without mutating the inner objects
75
+ // good: parent array reference is unaffected by typing and updating "keyword"
76
+ const sortedTlds = tlds.toSorted((a, b) => a.name.localeCompare(b.name))
77
+
78
+ return <LegendList data={sortedTlds} renderItem={renderItem} />
79
+ ```
80
+
81
+ Even though this creates a new array instance `sortedTlds`, the inner object
82
+ references are stable.
83
+
84
+ **With zustand for dynamic data (avoids parent re-renders):**
85
+
86
+ ```tsx
87
+ const useSearchStore = create<{ keyword: string }>(() => ({ keyword: '' }))
88
+
89
+ function DomainSearch() {
90
+ const { data: tlds } = useTlds()
91
+
92
+ return (
93
+ <>
94
+ <SearchInput />
95
+ <LegendList
96
+ data={tlds}
97
+ // if you aren't using React Compiler, wrap renderItem with useCallback
98
+ renderItem={({ item }) => <DomainItem tld={item} />}
99
+ />
100
+ </>
101
+ )
102
+ }
103
+
104
+ function DomainItem({ tld }: { tld: Tld }) {
105
+ // Select only what you need—component only re-renders when keyword changes
106
+ const keyword = useSearchStore((s) => s.keyword)
107
+ const domain = `${keyword}.${tld.name}`
108
+ return <Text>{domain}</Text>
109
+ }
110
+ ```
111
+
112
+ Virtualization can now skip items that haven't changed when typing. Only visible
113
+ items (~20) re-render on keystroke, rather than the parent.
114
+
115
+ **Deriving state within list items based on parent data (avoids parent
116
+ re-renders):**
117
+
118
+ For components where the data is conditional based on the parent state, this
119
+ pattern is even more important. For example, if you are checking if an item is
120
+ favorited, toggling favorites only re-renders one component if the item itself
121
+ is in charge of accessing the state rather than the parent:
122
+
123
+ ```tsx
124
+ function DomainItemFavoriteButton({ tld }: { tld: Tld }) {
125
+ const isFavorited = useFavoritesStore((s) => s.favorites.has(tld.id))
126
+ return <TldFavoriteButton isFavorited={isFavorited} />
127
+ }
128
+ ```
129
+
130
+ Note: if you're using the React Compiler, you can read React Context values
131
+ directly within list items. Although this is slightly slower than using a
132
+ Zustand selector in most cases, the effect may be negligible.
@@ -0,0 +1,53 @@
1
+ ---
2
+ title: Use Compressed Images in Lists
3
+ impact: HIGH
4
+ impactDescription: faster load times, less memory
5
+ tags: lists, images, performance, optimization
6
+ ---
7
+
8
+ ## Use Compressed Images in Lists
9
+
10
+ Always load compressed, appropriately-sized images in lists. Full-resolution
11
+ images consume excessive memory and cause scroll jank. Request thumbnails from
12
+ your server or use an image CDN with resize parameters.
13
+
14
+ **Incorrect (full-resolution images):**
15
+
16
+ ```tsx
17
+ function ProductItem({ product }: { product: Product }) {
18
+ return (
19
+ <View>
20
+ {/* 4000x3000 image loaded for a 100x100 thumbnail */}
21
+ <Image
22
+ source={{ uri: product.imageUrl }}
23
+ style={{ width: 100, height: 100 }}
24
+ />
25
+ <Text>{product.name}</Text>
26
+ </View>
27
+ )
28
+ }
29
+ ```
30
+
31
+ **Correct (request appropriately-sized image):**
32
+
33
+ ```tsx
34
+ function ProductItem({ product }: { product: Product }) {
35
+ // Request a 200x200 image (2x for retina)
36
+ const thumbnailUrl = `${product.imageUrl}?w=200&h=200&fit=cover`
37
+
38
+ return (
39
+ <View>
40
+ <Image
41
+ source={{ uri: thumbnailUrl }}
42
+ style={{ width: 100, height: 100 }}
43
+ contentFit='cover'
44
+ />
45
+ <Text>{product.name}</Text>
46
+ </View>
47
+ )
48
+ }
49
+ ```
50
+
51
+ Use an optimized image component with built-in caching and placeholder support,
52
+ such as `expo-image` or `SolitoImage` (which uses `expo-image` under the hood).
53
+ Request images at 2x the display size for retina screens.
@@ -0,0 +1,97 @@
1
+ ---
2
+ title: Avoid Inline Objects in renderItem
3
+ impact: HIGH
4
+ impactDescription: prevents unnecessary re-renders of memoized list items
5
+ tags: lists, performance, flatlist, virtualization, memo
6
+ ---
7
+
8
+ ## Avoid Inline Objects in renderItem
9
+
10
+ Don't create new objects inside `renderItem` to pass as props. Inline objects
11
+ create new references on every render, breaking memoization. Pass primitive
12
+ values directly from `item` instead.
13
+
14
+ **Incorrect (inline object breaks memoization):**
15
+
16
+ ```tsx
17
+ function UserList({ users }: { users: User[] }) {
18
+ return (
19
+ <LegendList
20
+ data={users}
21
+ renderItem={({ item }) => (
22
+ <UserRow
23
+ // Bad: new object on every render
24
+ user={{ id: item.id, name: item.name, avatar: item.avatar }}
25
+ />
26
+ )}
27
+ />
28
+ )
29
+ }
30
+ ```
31
+
32
+ **Incorrect (inline style object):**
33
+
34
+ ```tsx
35
+ renderItem={({ item }) => (
36
+ <UserRow
37
+ name={item.name}
38
+ // Bad: new style object on every render
39
+ style={{ backgroundColor: item.isActive ? 'green' : 'gray' }}
40
+ />
41
+ )}
42
+ ```
43
+
44
+ **Correct (pass item directly or primitives):**
45
+
46
+ ```tsx
47
+ function UserList({ users }: { users: User[] }) {
48
+ return (
49
+ <LegendList
50
+ data={users}
51
+ renderItem={({ item }) => (
52
+ // Good: pass the item directly
53
+ <UserRow user={item} />
54
+ )}
55
+ />
56
+ )
57
+ }
58
+ ```
59
+
60
+ **Correct (pass primitives, derive inside child):**
61
+
62
+ ```tsx
63
+ renderItem={({ item }) => (
64
+ <UserRow
65
+ id={item.id}
66
+ name={item.name}
67
+ isActive={item.isActive}
68
+ />
69
+ )}
70
+
71
+ const UserRow = memo(function UserRow({ id, name, isActive }: Props) {
72
+ // Good: derive style inside memoized component
73
+ const backgroundColor = isActive ? 'green' : 'gray'
74
+ return <View style={[styles.row, { backgroundColor }]}>{/* ... */}</View>
75
+ })
76
+ ```
77
+
78
+ **Correct (hoist static styles in module scope):**
79
+
80
+ ```tsx
81
+ const activeStyle = { backgroundColor: 'green' }
82
+ const inactiveStyle = { backgroundColor: 'gray' }
83
+
84
+ renderItem={({ item }) => (
85
+ <UserRow
86
+ name={item.name}
87
+ // Good: stable references
88
+ style={item.isActive ? activeStyle : inactiveStyle}
89
+ />
90
+ )}
91
+ ```
92
+
93
+ Passing primitives or stable references allows `memo()` to skip re-renders when
94
+ the actual values haven't changed.
95
+
96
+ **Note:** If you have the React Compiler enabled, it handles memoization
97
+ automatically and these manual optimizations become less critical.
@@ -0,0 +1,94 @@
1
+ ---
2
+ title: Keep List Items Lightweight
3
+ impact: HIGH
4
+ impactDescription: reduces render time for visible items during scroll
5
+ tags: lists, performance, virtualization, hooks
6
+ ---
7
+
8
+ ## Keep List Items Lightweight
9
+
10
+ List items should be as inexpensive as possible to render. Minimize hooks, avoid
11
+ queries, and limit React Context access. Virtualized lists render many items
12
+ during scroll—expensive items cause jank.
13
+
14
+ **Incorrect (heavy list item):**
15
+
16
+ ```tsx
17
+ function ProductRow({ id }: { id: string }) {
18
+ // Bad: query inside list item
19
+ const { data: product } = useQuery(['product', id], () => fetchProduct(id))
20
+ // Bad: multiple context accesses
21
+ const theme = useContext(ThemeContext)
22
+ const user = useContext(UserContext)
23
+ const cart = useContext(CartContext)
24
+ // Bad: expensive computation
25
+ const recommendations = useMemo(
26
+ () => computeRecommendations(product),
27
+ [product]
28
+ )
29
+
30
+ return <View>{/* ... */}</View>
31
+ }
32
+ ```
33
+
34
+ **Correct (lightweight list item):**
35
+
36
+ ```tsx
37
+ function ProductRow({ name, price, imageUrl }: Props) {
38
+ // Good: receives only primitives, minimal hooks
39
+ return (
40
+ <View>
41
+ <Image source={{ uri: imageUrl }} />
42
+ <Text>{name}</Text>
43
+ <Text>{price}</Text>
44
+ </View>
45
+ )
46
+ }
47
+ ```
48
+
49
+ **Move data fetching to parent:**
50
+
51
+ ```tsx
52
+ // Parent fetches all data once
53
+ function ProductList() {
54
+ const { data: products } = useQuery(['products'], fetchProducts)
55
+
56
+ return (
57
+ <LegendList
58
+ data={products}
59
+ renderItem={({ item }) => (
60
+ <ProductRow name={item.name} price={item.price} imageUrl={item.image} />
61
+ )}
62
+ />
63
+ )
64
+ }
65
+ ```
66
+
67
+ **For shared values, use Zustand selectors instead of Context:**
68
+
69
+ ```tsx
70
+ // Incorrect: Context causes re-render when any cart value changes
71
+ function ProductRow({ id, name }: Props) {
72
+ const { items } = useContext(CartContext)
73
+ const inCart = items.includes(id)
74
+ // ...
75
+ }
76
+
77
+ // Correct: Zustand selector only re-renders when this specific value changes
78
+ function ProductRow({ id, name }: Props) {
79
+ // use Set.has (created once at the root) instead of Array.includes()
80
+ const inCart = useCartStore((s) => s.items.has(id))
81
+ // ...
82
+ }
83
+ ```
84
+
85
+ **Guidelines for list items:**
86
+
87
+ - No queries or data fetching
88
+ - No expensive computations (move to parent or memoize at parent level)
89
+ - Prefer Zustand selectors over React Context
90
+ - Minimize useState/useEffect hooks
91
+ - Pass pre-computed values as props
92
+
93
+ The goal: list items should be simple rendering functions that take props and
94
+ return JSX.
@@ -0,0 +1,82 @@
1
+ ---
2
+ title: Pass Primitives to List Items for Memoization
3
+ impact: HIGH
4
+ impactDescription: enables effective memo() comparison
5
+ tags: lists, performance, memo, primitives
6
+ ---
7
+
8
+ ## Pass Primitives to List Items for Memoization
9
+
10
+ When possible, pass only primitive values (strings, numbers, booleans) as props
11
+ to list item components. Primitives enable shallow comparison in `memo()` to
12
+ work correctly, skipping re-renders when values haven't changed.
13
+
14
+ **Incorrect (object prop requires deep comparison):**
15
+
16
+ ```tsx
17
+ type User = { id: string; name: string; email: string; avatar: string }
18
+
19
+ const UserRow = memo(function UserRow({ user }: { user: User }) {
20
+ // memo() compares user by reference, not value
21
+ // If parent creates new user object, this re-renders even if data is same
22
+ return <Text>{user.name}</Text>
23
+ })
24
+
25
+ renderItem={({ item }) => <UserRow user={item} />}
26
+ ```
27
+
28
+ This can still be optimized, but it is harder to memoize properly.
29
+
30
+ **Correct (primitive props enable shallow comparison):**
31
+
32
+ ```tsx
33
+ const UserRow = memo(function UserRow({
34
+ id,
35
+ name,
36
+ email,
37
+ }: {
38
+ id: string
39
+ name: string
40
+ email: string
41
+ }) {
42
+ // memo() compares each primitive directly
43
+ // Re-renders only if id, name, or email actually changed
44
+ return <Text>{name}</Text>
45
+ })
46
+
47
+ renderItem={({ item }) => (
48
+ <UserRow id={item.id} name={item.name} email={item.email} />
49
+ )}
50
+ ```
51
+
52
+ **Pass only what you need:**
53
+
54
+ ```tsx
55
+ // Incorrect: passing entire item when you only need name
56
+ <UserRow user={item} />
57
+
58
+ // Correct: pass only the fields the component uses
59
+ <UserRow name={item.name} avatarUrl={item.avatar} />
60
+ ```
61
+
62
+ **For callbacks, hoist or use item ID:**
63
+
64
+ ```tsx
65
+ // Incorrect: inline function creates new reference
66
+ <UserRow name={item.name} onPress={() => handlePress(item.id)} />
67
+
68
+ // Correct: pass ID, handle in child
69
+ <UserRow id={item.id} name={item.name} />
70
+
71
+ const UserRow = memo(function UserRow({ id, name }: Props) {
72
+ const handlePress = useCallback(() => {
73
+ // use id here
74
+ }, [id])
75
+ return <Pressable onPress={handlePress}><Text>{name}</Text></Pressable>
76
+ })
77
+ ```
78
+
79
+ Primitive props make memoization predictable and effective.
80
+
81
+ **Note:** If you have the React Compiler enabled, you do not need to use
82
+ `memo()` or `useCallback()`, but the object references still apply.
@@ -0,0 +1,104 @@
1
+ ---
2
+ title: Use Item Types for Heterogeneous Lists
3
+ impact: HIGH
4
+ impactDescription: efficient recycling, less layout thrashing
5
+ tags: list, performance, recycling, heterogeneous, LegendList
6
+ ---
7
+
8
+ ## Use Item Types for Heterogeneous Lists
9
+
10
+ When a list has different item layouts (messages, images, headers, etc.), use a
11
+ `type` field on each item and provide `getItemType` to the list. This puts items
12
+ into separate recycling pools so a message component never gets recycled into an
13
+ image component.
14
+
15
+ **Incorrect (single component with conditionals):**
16
+
17
+ ```tsx
18
+ type Item = { id: string; text?: string; imageUrl?: string; isHeader?: boolean }
19
+
20
+ function ListItem({ item }: { item: Item }) {
21
+ if (item.isHeader) {
22
+ return <HeaderItem title={item.text} />
23
+ }
24
+ if (item.imageUrl) {
25
+ return <ImageItem url={item.imageUrl} />
26
+ }
27
+ return <MessageItem text={item.text} />
28
+ }
29
+
30
+ function Feed({ items }: { items: Item[] }) {
31
+ return (
32
+ <LegendList
33
+ data={items}
34
+ renderItem={({ item }) => <ListItem item={item} />}
35
+ recycleItems
36
+ />
37
+ )
38
+ }
39
+ ```
40
+
41
+ **Correct (typed items with separate components):**
42
+
43
+ ```tsx
44
+ type HeaderItem = { id: string; type: 'header'; title: string }
45
+ type MessageItem = { id: string; type: 'message'; text: string }
46
+ type ImageItem = { id: string; type: 'image'; url: string }
47
+ type FeedItem = HeaderItem | MessageItem | ImageItem
48
+
49
+ function Feed({ items }: { items: FeedItem[] }) {
50
+ return (
51
+ <LegendList
52
+ data={items}
53
+ keyExtractor={(item) => item.id}
54
+ getItemType={(item) => item.type}
55
+ renderItem={({ item }) => {
56
+ switch (item.type) {
57
+ case 'header':
58
+ return <SectionHeader title={item.title} />
59
+ case 'message':
60
+ return <MessageRow text={item.text} />
61
+ case 'image':
62
+ return <ImageRow url={item.url} />
63
+ }
64
+ }}
65
+ recycleItems
66
+ />
67
+ )
68
+ }
69
+ ```
70
+
71
+ **Why this matters:**
72
+
73
+ - **Recycling efficiency**: Items with the same type share a recycling pool
74
+ - **No layout thrashing**: A header never recycles into an image cell
75
+ - **Type safety**: TypeScript can narrow the item type in each branch
76
+ - **Better size estimation**: Use `getEstimatedItemSize` with `itemType` for
77
+ accurate estimates per type
78
+
79
+ ```tsx
80
+ <LegendList
81
+ data={items}
82
+ keyExtractor={(item) => item.id}
83
+ getItemType={(item) => item.type}
84
+ getEstimatedItemSize={(index, item, itemType) => {
85
+ switch (itemType) {
86
+ case 'header':
87
+ return 48
88
+ case 'message':
89
+ return 72
90
+ case 'image':
91
+ return 300
92
+ default:
93
+ return 72
94
+ }
95
+ }}
96
+ renderItem={({ item }) => {
97
+ /* ... */
98
+ }}
99
+ recycleItems
100
+ />
101
+ ```
102
+
103
+ Reference:
104
+ [LegendList getItemType](https://legendapp.com/open-source/list/api/props/#getitemtype-v2)