@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,191 @@
1
+ ---
2
+ title: Define Generic Context Interfaces for Dependency Injection
3
+ impact: HIGH
4
+ impactDescription: enables dependency-injectable state across use-cases
5
+ tags: composition, context, state, typescript, dependency-injection
6
+ ---
7
+
8
+ ## Define Generic Context Interfaces for Dependency Injection
9
+
10
+ Define a **generic interface** for your component context with three parts:
11
+ `state`, `actions`, and `meta`. This interface is a contract that any provider
12
+ can implement—enabling the same UI components to work with completely different
13
+ state implementations.
14
+
15
+ **Core principle:** Lift state, compose internals, make state
16
+ dependency-injectable.
17
+
18
+ **Incorrect (UI coupled to specific state implementation):**
19
+
20
+ ```tsx
21
+ function ComposerInput() {
22
+ // Tightly coupled to a specific hook
23
+ const { input, setInput } = useChannelComposerState()
24
+ return <TextInput value={input} onChangeText={setInput} />
25
+ }
26
+ ```
27
+
28
+ **Correct (generic interface enables dependency injection):**
29
+
30
+ ```tsx
31
+ // Define a GENERIC interface that any provider can implement
32
+ interface ComposerState {
33
+ input: string
34
+ attachments: Attachment[]
35
+ isSubmitting: boolean
36
+ }
37
+
38
+ interface ComposerActions {
39
+ update: (updater: (state: ComposerState) => ComposerState) => void
40
+ submit: () => void
41
+ }
42
+
43
+ interface ComposerMeta {
44
+ inputRef: React.RefObject<TextInput>
45
+ }
46
+
47
+ interface ComposerContextValue {
48
+ state: ComposerState
49
+ actions: ComposerActions
50
+ meta: ComposerMeta
51
+ }
52
+
53
+ const ComposerContext = createContext<ComposerContextValue | null>(null)
54
+ ```
55
+
56
+ **UI components consume the interface, not the implementation:**
57
+
58
+ ```tsx
59
+ function ComposerInput() {
60
+ const {
61
+ state,
62
+ actions: { update },
63
+ meta,
64
+ } = use(ComposerContext)
65
+
66
+ // This component works with ANY provider that implements the interface
67
+ return (
68
+ <TextInput
69
+ ref={meta.inputRef}
70
+ value={state.input}
71
+ onChangeText={(text) => update((s) => ({ ...s, input: text }))}
72
+ />
73
+ )
74
+ }
75
+ ```
76
+
77
+ **Different providers implement the same interface:**
78
+
79
+ ```tsx
80
+ // Provider A: Local state for ephemeral forms
81
+ function ForwardMessageProvider({ children }: { children: React.ReactNode }) {
82
+ const [state, setState] = useState(initialState)
83
+ const inputRef = useRef(null)
84
+ const submit = useForwardMessage()
85
+
86
+ return (
87
+ <ComposerContext
88
+ value={{
89
+ state,
90
+ actions: { update: setState, submit },
91
+ meta: { inputRef },
92
+ }}
93
+ >
94
+ {children}
95
+ </ComposerContext>
96
+ )
97
+ }
98
+
99
+ // Provider B: Global synced state for channels
100
+ function ChannelProvider({ channelId, children }: Props) {
101
+ const { state, update, submit } = useGlobalChannel(channelId)
102
+ const inputRef = useRef(null)
103
+
104
+ return (
105
+ <ComposerContext
106
+ value={{
107
+ state,
108
+ actions: { update, submit },
109
+ meta: { inputRef },
110
+ }}
111
+ >
112
+ {children}
113
+ </ComposerContext>
114
+ )
115
+ }
116
+ ```
117
+
118
+ **The same composed UI works with both:**
119
+
120
+ ```tsx
121
+ // Works with ForwardMessageProvider (local state)
122
+ <ForwardMessageProvider>
123
+ <Composer.Frame>
124
+ <Composer.Input />
125
+ <Composer.Submit />
126
+ </Composer.Frame>
127
+ </ForwardMessageProvider>
128
+
129
+ // Works with ChannelProvider (global synced state)
130
+ <ChannelProvider channelId="abc">
131
+ <Composer.Frame>
132
+ <Composer.Input />
133
+ <Composer.Submit />
134
+ </Composer.Frame>
135
+ </ChannelProvider>
136
+ ```
137
+
138
+ **Custom UI outside the component can access state and actions:**
139
+
140
+ The provider boundary is what matters—not the visual nesting. Components that
141
+ need shared state don't have to be inside the `Composer.Frame`. They just need
142
+ to be within the provider.
143
+
144
+ ```tsx
145
+ function ForwardMessageDialog() {
146
+ return (
147
+ <ForwardMessageProvider>
148
+ <Dialog>
149
+ {/* The composer UI */}
150
+ <Composer.Frame>
151
+ <Composer.Input placeholder="Add a message, if you'd like." />
152
+ <Composer.Footer>
153
+ <Composer.Formatting />
154
+ <Composer.Emojis />
155
+ </Composer.Footer>
156
+ </Composer.Frame>
157
+
158
+ {/* Custom UI OUTSIDE the composer, but INSIDE the provider */}
159
+ <MessagePreview />
160
+
161
+ {/* Actions at the bottom of the dialog */}
162
+ <DialogActions>
163
+ <CancelButton />
164
+ <ForwardButton />
165
+ </DialogActions>
166
+ </Dialog>
167
+ </ForwardMessageProvider>
168
+ )
169
+ }
170
+
171
+ // This button lives OUTSIDE Composer.Frame but can still submit based on its context!
172
+ function ForwardButton() {
173
+ const {
174
+ actions: { submit },
175
+ } = use(ComposerContext)
176
+ return <Button onPress={submit}>Forward</Button>
177
+ }
178
+
179
+ // This preview lives OUTSIDE Composer.Frame but can read composer's state!
180
+ function MessagePreview() {
181
+ const { state } = use(ComposerContext)
182
+ return <Preview message={state.input} attachments={state.attachments} />
183
+ }
184
+ ```
185
+
186
+ The `ForwardButton` and `MessagePreview` are not visually inside the composer
187
+ box, but they can still access its state and actions. This is the power of
188
+ lifting state into providers.
189
+
190
+ The UI is reusable bits you compose together. The state is dependency-injected
191
+ by the provider. Swap the provider, keep the UI.
@@ -0,0 +1,113 @@
1
+ ---
2
+ title: Decouple State Management from UI
3
+ impact: MEDIUM
4
+ impactDescription: enables swapping state implementations without changing UI
5
+ tags: composition, state, architecture
6
+ ---
7
+
8
+ ## Decouple State Management from UI
9
+
10
+ The provider component should be the only place that knows how state is managed.
11
+ UI components consume the context interface—they don't know if state comes from
12
+ useState, Zustand, or a server sync.
13
+
14
+ **Incorrect (UI coupled to state implementation):**
15
+
16
+ ```tsx
17
+ function ChannelComposer({ channelId }: { channelId: string }) {
18
+ // UI component knows about global state implementation
19
+ const state = useGlobalChannelState(channelId)
20
+ const { submit, updateInput } = useChannelSync(channelId)
21
+
22
+ return (
23
+ <Composer.Frame>
24
+ <Composer.Input
25
+ value={state.input}
26
+ onChange={(text) => sync.updateInput(text)}
27
+ />
28
+ <Composer.Submit onPress={() => sync.submit()} />
29
+ </Composer.Frame>
30
+ )
31
+ }
32
+ ```
33
+
34
+ **Correct (state management isolated in provider):**
35
+
36
+ ```tsx
37
+ // Provider handles all state management details
38
+ function ChannelProvider({
39
+ channelId,
40
+ children,
41
+ }: {
42
+ channelId: string
43
+ children: React.ReactNode
44
+ }) {
45
+ const { state, update, submit } = useGlobalChannel(channelId)
46
+ const inputRef = useRef(null)
47
+
48
+ return (
49
+ <Composer.Provider
50
+ state={state}
51
+ actions={{ update, submit }}
52
+ meta={{ inputRef }}
53
+ >
54
+ {children}
55
+ </Composer.Provider>
56
+ )
57
+ }
58
+
59
+ // UI component only knows about the context interface
60
+ function ChannelComposer() {
61
+ return (
62
+ <Composer.Frame>
63
+ <Composer.Header />
64
+ <Composer.Input />
65
+ <Composer.Footer>
66
+ <Composer.Submit />
67
+ </Composer.Footer>
68
+ </Composer.Frame>
69
+ )
70
+ }
71
+
72
+ // Usage
73
+ function Channel({ channelId }: { channelId: string }) {
74
+ return (
75
+ <ChannelProvider channelId={channelId}>
76
+ <ChannelComposer />
77
+ </ChannelProvider>
78
+ )
79
+ }
80
+ ```
81
+
82
+ **Different providers, same UI:**
83
+
84
+ ```tsx
85
+ // Local state for ephemeral forms
86
+ function ForwardMessageProvider({ children }) {
87
+ const [state, setState] = useState(initialState)
88
+ const forwardMessage = useForwardMessage()
89
+
90
+ return (
91
+ <Composer.Provider
92
+ state={state}
93
+ actions={{ update: setState, submit: forwardMessage }}
94
+ >
95
+ {children}
96
+ </Composer.Provider>
97
+ )
98
+ }
99
+
100
+ // Global synced state for channels
101
+ function ChannelProvider({ channelId, children }) {
102
+ const { state, update, submit } = useGlobalChannel(channelId)
103
+
104
+ return (
105
+ <Composer.Provider state={state} actions={{ update, submit }}>
106
+ {children}
107
+ </Composer.Provider>
108
+ )
109
+ }
110
+ ```
111
+
112
+ The same `Composer.Input` component works with both providers because it only
113
+ depends on the context interface, not the implementation.
@@ -0,0 +1,125 @@
1
+ ---
2
+ title: Lift State into Provider Components
3
+ impact: HIGH
4
+ impactDescription: enables state sharing outside component boundaries
5
+ tags: composition, state, context, providers
6
+ ---
7
+
8
+ ## Lift State into Provider Components
9
+
10
+ Move state management into dedicated provider components. This allows sibling
11
+ components outside the main UI to access and modify state without prop drilling
12
+ or awkward refs.
13
+
14
+ **Incorrect (state trapped inside component):**
15
+
16
+ ```tsx
17
+ function ForwardMessageComposer() {
18
+ const [state, setState] = useState(initialState)
19
+ const forwardMessage = useForwardMessage()
20
+
21
+ return (
22
+ <Composer.Frame>
23
+ <Composer.Input />
24
+ <Composer.Footer />
25
+ </Composer.Frame>
26
+ )
27
+ }
28
+
29
+ // Problem: How does this button access composer state?
30
+ function ForwardMessageDialog() {
31
+ return (
32
+ <Dialog>
33
+ <ForwardMessageComposer />
34
+ <MessagePreview /> {/* Needs composer state */}
35
+ <DialogActions>
36
+ <CancelButton />
37
+ <ForwardButton /> {/* Needs to call submit */}
38
+ </DialogActions>
39
+ </Dialog>
40
+ )
41
+ }
42
+ ```
43
+
44
+ **Incorrect (useEffect to sync state up):**
45
+
46
+ ```tsx
47
+ function ForwardMessageDialog() {
48
+ const [input, setInput] = useState('')
49
+ return (
50
+ <Dialog>
51
+ <ForwardMessageComposer onInputChange={setInput} />
52
+ <MessagePreview input={input} />
53
+ </Dialog>
54
+ )
55
+ }
56
+
57
+ function ForwardMessageComposer({ onInputChange }) {
58
+ const [state, setState] = useState(initialState)
59
+ useEffect(() => {
60
+ onInputChange(state.input) // Sync on every change 😬
61
+ }, [state.input])
62
+ }
63
+ ```
64
+
65
+ **Incorrect (reading state from ref on submit):**
66
+
67
+ ```tsx
68
+ function ForwardMessageDialog() {
69
+ const stateRef = useRef(null)
70
+ return (
71
+ <Dialog>
72
+ <ForwardMessageComposer stateRef={stateRef} />
73
+ <ForwardButton onPress={() => submit(stateRef.current)} />
74
+ </Dialog>
75
+ )
76
+ }
77
+ ```
78
+
79
+ **Correct (state lifted to provider):**
80
+
81
+ ```tsx
82
+ function ForwardMessageProvider({ children }: { children: React.ReactNode }) {
83
+ const [state, setState] = useState(initialState)
84
+ const forwardMessage = useForwardMessage()
85
+ const inputRef = useRef(null)
86
+
87
+ return (
88
+ <Composer.Provider
89
+ state={state}
90
+ actions={{ update: setState, submit: forwardMessage }}
91
+ meta={{ inputRef }}
92
+ >
93
+ {children}
94
+ </Composer.Provider>
95
+ )
96
+ }
97
+
98
+ function ForwardMessageDialog() {
99
+ return (
100
+ <ForwardMessageProvider>
101
+ <Dialog>
102
+ <ForwardMessageComposer />
103
+ <MessagePreview /> {/* Custom components can access state and actions */}
104
+ <DialogActions>
105
+ <CancelButton />
106
+ <ForwardButton /> {/* Custom components can access state and actions */}
107
+ </DialogActions>
108
+ </Dialog>
109
+ </ForwardMessageProvider>
110
+ )
111
+ }
112
+
113
+ function ForwardButton() {
114
+ const { actions } = use(Composer.Context)
115
+ return <Button onPress={actions.submit}>Forward</Button>
116
+ }
117
+ ```
118
+
119
+ The ForwardButton lives outside the Composer.Frame but still has access to the
120
+ submit action because it's within the provider. Even though it's a one-off
121
+ component, it can still access the composer's state and actions from outside the
122
+ UI itself.
123
+
124
+ **Key insight:** Components that need shared state don't have to be visually
125
+ nested inside each other—they just need to be within the same provider.