@codyswann/lisa 2.111.0 → 2.112.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 (155) hide show
  1. package/package.json +1 -1
  2. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  3. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  4. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  5. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  6. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  7. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  8. package/plugins/lisa-expo/.mcp.json +3 -3
  9. package/plugins/lisa-expo/THIRD-PARTY-NOTICES.md +57 -0
  10. package/plugins/lisa-expo/skills/add-app-clip/SKILL.md +280 -0
  11. package/plugins/lisa-expo/skills/add-app-clip/agents/openai.yaml +4 -0
  12. package/plugins/lisa-expo/skills/add-app-clip/references/native-module.md +96 -0
  13. package/plugins/lisa-expo/skills/building-native-ui/SKILL.md +321 -0
  14. package/plugins/lisa-expo/skills/building-native-ui/agents/openai.yaml +4 -0
  15. package/plugins/lisa-expo/skills/building-native-ui/references/animations.md +220 -0
  16. package/plugins/lisa-expo/skills/building-native-ui/references/controls.md +272 -0
  17. package/plugins/lisa-expo/skills/building-native-ui/references/form-sheet.md +253 -0
  18. package/plugins/lisa-expo/skills/building-native-ui/references/gradients.md +106 -0
  19. package/plugins/lisa-expo/skills/building-native-ui/references/icons.md +213 -0
  20. package/plugins/lisa-expo/skills/building-native-ui/references/media.md +198 -0
  21. package/plugins/lisa-expo/skills/building-native-ui/references/route-structure.md +229 -0
  22. package/plugins/lisa-expo/skills/building-native-ui/references/search.md +248 -0
  23. package/plugins/lisa-expo/skills/building-native-ui/references/storage.md +121 -0
  24. package/plugins/lisa-expo/skills/building-native-ui/references/tabs.md +433 -0
  25. package/plugins/lisa-expo/skills/building-native-ui/references/toolbar-and-headers.md +284 -0
  26. package/plugins/lisa-expo/skills/building-native-ui/references/visual-effects.md +197 -0
  27. package/plugins/lisa-expo/skills/building-native-ui/references/webgpu-three.md +605 -0
  28. package/plugins/lisa-expo/skills/building-native-ui/references/zoom-transitions.md +158 -0
  29. package/plugins/lisa-expo/skills/eas-update-insights/SKILL.md +228 -0
  30. package/plugins/lisa-expo/skills/eas-update-insights/agents/openai.yaml +4 -0
  31. package/plugins/lisa-expo/skills/eas-update-insights/references/channel-insights-schema.md +47 -0
  32. package/plugins/lisa-expo/skills/eas-update-insights/references/update-insights-schema.md +69 -0
  33. package/plugins/lisa-expo/skills/expo-api-routes/SKILL.md +369 -0
  34. package/plugins/lisa-expo/skills/expo-api-routes/agents/openai.yaml +4 -0
  35. package/plugins/lisa-expo/skills/expo-brownfield/SKILL.md +54 -0
  36. package/plugins/lisa-expo/skills/expo-brownfield/agents/openai.yaml +4 -0
  37. package/plugins/lisa-expo/skills/expo-brownfield/references/brownfield-integrated.md +526 -0
  38. package/plugins/lisa-expo/skills/expo-brownfield/references/brownfield-isolated.md +402 -0
  39. package/plugins/lisa-expo/skills/expo-brownfield/references/comparison.md +63 -0
  40. package/plugins/lisa-expo/skills/expo-brownfield/references/troubleshooting.md +88 -0
  41. package/plugins/lisa-expo/skills/expo-cicd-workflows/SKILL.md +92 -0
  42. package/plugins/lisa-expo/skills/expo-cicd-workflows/agents/openai.yaml +4 -0
  43. package/plugins/lisa-expo/skills/expo-cicd-workflows/scripts/fetch.js +113 -0
  44. package/plugins/lisa-expo/skills/expo-cicd-workflows/scripts/package.json +11 -0
  45. package/plugins/lisa-expo/skills/expo-cicd-workflows/scripts/validate.js +85 -0
  46. package/plugins/lisa-expo/skills/expo-deployment/SKILL.md +190 -0
  47. package/plugins/lisa-expo/skills/expo-deployment/agents/openai.yaml +4 -0
  48. package/plugins/lisa-expo/skills/expo-deployment/references/app-store-metadata.md +479 -0
  49. package/plugins/lisa-expo/skills/expo-deployment/references/ios-app-store.md +355 -0
  50. package/plugins/lisa-expo/skills/expo-deployment/references/play-store.md +246 -0
  51. package/plugins/lisa-expo/skills/expo-deployment/references/testflight.md +58 -0
  52. package/plugins/lisa-expo/skills/expo-deployment/references/workflows.md +200 -0
  53. package/plugins/lisa-expo/skills/expo-dev-client/SKILL.md +164 -0
  54. package/plugins/lisa-expo/skills/expo-dev-client/agents/openai.yaml +4 -0
  55. package/plugins/lisa-expo/skills/expo-module/SKILL.md +141 -0
  56. package/plugins/lisa-expo/skills/expo-module/agents/openai.yaml +4 -0
  57. package/plugins/lisa-expo/skills/expo-module/references/config-plugin.md +90 -0
  58. package/plugins/lisa-expo/skills/expo-module/references/create-expo-module.md +206 -0
  59. package/plugins/lisa-expo/skills/expo-module/references/lifecycle.md +127 -0
  60. package/plugins/lisa-expo/skills/expo-module/references/module-config.md +48 -0
  61. package/plugins/lisa-expo/skills/expo-module/references/native-module.md +286 -0
  62. package/plugins/lisa-expo/skills/expo-module/references/native-view.md +171 -0
  63. package/plugins/lisa-expo/skills/expo-tailwind-setup/SKILL.md +480 -0
  64. package/plugins/lisa-expo/skills/expo-tailwind-setup/agents/openai.yaml +4 -0
  65. package/plugins/lisa-expo/skills/expo-ui-jetpack-compose/SKILL.md +40 -0
  66. package/plugins/lisa-expo/skills/expo-ui-jetpack-compose/agents/openai.yaml +4 -0
  67. package/plugins/lisa-expo/skills/expo-ui-swift-ui/SKILL.md +39 -0
  68. package/plugins/lisa-expo/skills/expo-ui-swift-ui/agents/openai.yaml +4 -0
  69. package/plugins/lisa-expo/skills/native-data-fetching/SKILL.md +507 -0
  70. package/plugins/lisa-expo/skills/native-data-fetching/agents/openai.yaml +4 -0
  71. package/plugins/lisa-expo/skills/native-data-fetching/references/expo-router-loaders.md +344 -0
  72. package/plugins/lisa-expo/skills/upgrading-expo/SKILL.md +134 -0
  73. package/plugins/lisa-expo/skills/upgrading-expo/agents/openai.yaml +4 -0
  74. package/plugins/lisa-expo/skills/upgrading-expo/references/expo-av-to-audio.md +132 -0
  75. package/plugins/lisa-expo/skills/upgrading-expo/references/expo-av-to-video.md +160 -0
  76. package/plugins/lisa-expo/skills/upgrading-expo/references/native-tabs.md +124 -0
  77. package/plugins/lisa-expo/skills/upgrading-expo/references/new-architecture.md +79 -0
  78. package/plugins/lisa-expo/skills/upgrading-expo/references/react-19.md +79 -0
  79. package/plugins/lisa-expo/skills/upgrading-expo/references/react-compiler.md +59 -0
  80. package/plugins/lisa-expo/skills/upgrading-expo/references/react-navigation-to-expo-router.md +61 -0
  81. package/plugins/lisa-expo/skills/use-dom/SKILL.md +417 -0
  82. package/plugins/lisa-expo/skills/use-dom/agents/openai.yaml +4 -0
  83. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  85. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  87. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  89. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  90. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  91. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  93. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  95. package/plugins/src/expo/.mcp.json +3 -3
  96. package/plugins/src/expo/THIRD-PARTY-NOTICES.md +57 -0
  97. package/plugins/src/expo/skills/add-app-clip/SKILL.md +280 -0
  98. package/plugins/src/expo/skills/add-app-clip/references/native-module.md +96 -0
  99. package/plugins/src/expo/skills/building-native-ui/SKILL.md +321 -0
  100. package/plugins/src/expo/skills/building-native-ui/references/animations.md +220 -0
  101. package/plugins/src/expo/skills/building-native-ui/references/controls.md +272 -0
  102. package/plugins/src/expo/skills/building-native-ui/references/form-sheet.md +253 -0
  103. package/plugins/src/expo/skills/building-native-ui/references/gradients.md +106 -0
  104. package/plugins/src/expo/skills/building-native-ui/references/icons.md +213 -0
  105. package/plugins/src/expo/skills/building-native-ui/references/media.md +198 -0
  106. package/plugins/src/expo/skills/building-native-ui/references/route-structure.md +229 -0
  107. package/plugins/src/expo/skills/building-native-ui/references/search.md +248 -0
  108. package/plugins/src/expo/skills/building-native-ui/references/storage.md +121 -0
  109. package/plugins/src/expo/skills/building-native-ui/references/tabs.md +433 -0
  110. package/plugins/src/expo/skills/building-native-ui/references/toolbar-and-headers.md +284 -0
  111. package/plugins/src/expo/skills/building-native-ui/references/visual-effects.md +197 -0
  112. package/plugins/src/expo/skills/building-native-ui/references/webgpu-three.md +605 -0
  113. package/plugins/src/expo/skills/building-native-ui/references/zoom-transitions.md +158 -0
  114. package/plugins/src/expo/skills/eas-update-insights/SKILL.md +228 -0
  115. package/plugins/src/expo/skills/eas-update-insights/references/channel-insights-schema.md +47 -0
  116. package/plugins/src/expo/skills/eas-update-insights/references/update-insights-schema.md +69 -0
  117. package/plugins/src/expo/skills/expo-api-routes/SKILL.md +369 -0
  118. package/plugins/src/expo/skills/expo-brownfield/SKILL.md +54 -0
  119. package/plugins/src/expo/skills/expo-brownfield/references/brownfield-integrated.md +526 -0
  120. package/plugins/src/expo/skills/expo-brownfield/references/brownfield-isolated.md +402 -0
  121. package/plugins/src/expo/skills/expo-brownfield/references/comparison.md +63 -0
  122. package/plugins/src/expo/skills/expo-brownfield/references/troubleshooting.md +88 -0
  123. package/plugins/src/expo/skills/expo-cicd-workflows/SKILL.md +92 -0
  124. package/plugins/src/expo/skills/expo-cicd-workflows/scripts/fetch.js +113 -0
  125. package/plugins/src/expo/skills/expo-cicd-workflows/scripts/package.json +11 -0
  126. package/plugins/src/expo/skills/expo-cicd-workflows/scripts/validate.js +85 -0
  127. package/plugins/src/expo/skills/expo-deployment/SKILL.md +190 -0
  128. package/plugins/src/expo/skills/expo-deployment/references/app-store-metadata.md +479 -0
  129. package/plugins/src/expo/skills/expo-deployment/references/ios-app-store.md +355 -0
  130. package/plugins/src/expo/skills/expo-deployment/references/play-store.md +246 -0
  131. package/plugins/src/expo/skills/expo-deployment/references/testflight.md +58 -0
  132. package/plugins/src/expo/skills/expo-deployment/references/workflows.md +200 -0
  133. package/plugins/src/expo/skills/expo-dev-client/SKILL.md +164 -0
  134. package/plugins/src/expo/skills/expo-module/SKILL.md +141 -0
  135. package/plugins/src/expo/skills/expo-module/references/config-plugin.md +90 -0
  136. package/plugins/src/expo/skills/expo-module/references/create-expo-module.md +206 -0
  137. package/plugins/src/expo/skills/expo-module/references/lifecycle.md +127 -0
  138. package/plugins/src/expo/skills/expo-module/references/module-config.md +48 -0
  139. package/plugins/src/expo/skills/expo-module/references/native-module.md +286 -0
  140. package/plugins/src/expo/skills/expo-module/references/native-view.md +171 -0
  141. package/plugins/src/expo/skills/expo-tailwind-setup/SKILL.md +480 -0
  142. package/plugins/src/expo/skills/expo-ui-jetpack-compose/SKILL.md +40 -0
  143. package/plugins/src/expo/skills/expo-ui-swift-ui/SKILL.md +39 -0
  144. package/plugins/src/expo/skills/native-data-fetching/SKILL.md +507 -0
  145. package/plugins/src/expo/skills/native-data-fetching/references/expo-router-loaders.md +344 -0
  146. package/plugins/src/expo/skills/upgrading-expo/SKILL.md +134 -0
  147. package/plugins/src/expo/skills/upgrading-expo/references/expo-av-to-audio.md +132 -0
  148. package/plugins/src/expo/skills/upgrading-expo/references/expo-av-to-video.md +160 -0
  149. package/plugins/src/expo/skills/upgrading-expo/references/native-tabs.md +124 -0
  150. package/plugins/src/expo/skills/upgrading-expo/references/new-architecture.md +79 -0
  151. package/plugins/src/expo/skills/upgrading-expo/references/react-19.md +79 -0
  152. package/plugins/src/expo/skills/upgrading-expo/references/react-compiler.md +59 -0
  153. package/plugins/src/expo/skills/upgrading-expo/references/react-navigation-to-expo-router.md +61 -0
  154. package/plugins/src/expo/skills/use-dom/SKILL.md +417 -0
  155. package/scripts/generate-codex-plugin-artifacts.mjs +7 -2
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: Expo UI SwiftUI
3
+ description: "`@expo/ui/swift-ui` package lets you use SwiftUI Views and modifiers in your app."
4
+ ---
5
+
6
+ > The instructions in this skill apply to SDK 55 only. For other SDK versions, refer to the Expo UI SwiftUI docs for that version for the most accurate information.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npx expo install @expo/ui
12
+ ```
13
+
14
+ A native rebuild is required after installation (`npx expo run:ios`).
15
+
16
+ ## Instructions
17
+
18
+ - Expo UI's API mirrors SwiftUI's API. Use SwiftUI knowledge to decide which components or modifiers to use.
19
+ - Components are imported from `@expo/ui/swift-ui`, modifiers from `@expo/ui/swift-ui/modifiers`.
20
+ - When about to use a component, fetch its docs to confirm the API - https://docs.expo.dev/versions/v55.0.0/sdk/ui/swift-ui/{component-name}/index.md
21
+ - When unsure about a modifier's API, refer to the docs - https://docs.expo.dev/versions/v55.0.0/sdk/ui/swift-ui/modifiers/index.md
22
+ - Every SwiftUI tree must be wrapped in `Host`.
23
+ - `RNHostView` is specifically for embedding RN components inside a SwiftUI tree. Example:
24
+
25
+ ```jsx
26
+ import { Host, VStack, RNHostView } from "@expo/ui/swift-ui";
27
+ import { Pressable } from "react-native";
28
+
29
+ <Host matchContents>
30
+ <VStack>
31
+ <RNHostView matchContents>
32
+ {/* Here, `Pressable` is an RN component so it is wrapped in `RNHostView`. */}
33
+ <Pressable />
34
+ </RNHostView>
35
+ </VStack>
36
+ </Host>;
37
+ ```
38
+
39
+ - If a required modifier or View is missing in Expo UI, it can be extended via a local Expo module. See: https://docs.expo.dev/guides/expo-ui-swift-ui/extending/index.md. Confirm with the user before extending.
@@ -0,0 +1,4 @@
1
+ display_name: "Expo UI SwiftUI"
2
+ short_description: "`@expo/ui/swift-ui` package lets you use SwiftUI Views and modifiers in your app"
3
+ default_prompt:
4
+ - "Use $expo-ui-swift-ui: `@expo/ui/swift-ui` package lets you use SwiftUI Views and modifiers in your app."
@@ -0,0 +1,507 @@
1
+ ---
2
+ name: native-data-fetching
3
+ description: Use when implementing or debugging ANY network request, API call, or data fetching. Covers fetch API, React Query, SWR, error handling, caching, offline support, and Expo Router data loaders (`useLoaderData`).
4
+ version: 1.0.0
5
+ license: MIT
6
+ ---
7
+
8
+ # Expo Networking
9
+
10
+ **You MUST use this skill for ANY networking work including API requests, data fetching, caching, or network debugging.**
11
+
12
+ ## References
13
+
14
+ Consult these resources as needed:
15
+
16
+ ```
17
+ references/
18
+ expo-router-loaders.md Route-level data loading with Expo Router loaders (web, SDK 55+)
19
+ ```
20
+
21
+ ## When to Use
22
+
23
+ Use this skill when:
24
+
25
+ - Implementing API requests
26
+ - Setting up data fetching (React Query, SWR)
27
+ - Using Expo Router data loaders (`useLoaderData`, web SDK 55+)
28
+ - Debugging network failures
29
+ - Implementing caching strategies
30
+ - Handling offline scenarios
31
+ - Authentication/token management
32
+ - Configuring API URLs and environment variables
33
+
34
+ ## Preferences
35
+
36
+ - Avoid axios, prefer expo/fetch
37
+
38
+ ## Common Issues & Solutions
39
+
40
+ ### 1. Basic Fetch Usage
41
+
42
+ **Simple GET request**:
43
+
44
+ ```tsx
45
+ const fetchUser = async (userId: string) => {
46
+ const response = await fetch(`https://api.example.com/users/${userId}`);
47
+
48
+ if (!response.ok) {
49
+ throw new Error(`HTTP error! status: ${response.status}`);
50
+ }
51
+
52
+ return response.json();
53
+ };
54
+ ```
55
+
56
+ **POST request with body**:
57
+
58
+ ```tsx
59
+ const createUser = async (userData: UserData) => {
60
+ const response = await fetch("https://api.example.com/users", {
61
+ method: "POST",
62
+ headers: {
63
+ "Content-Type": "application/json",
64
+ Authorization: `Bearer ${token}`,
65
+ },
66
+ body: JSON.stringify(userData),
67
+ });
68
+
69
+ if (!response.ok) {
70
+ const error = await response.json();
71
+ throw new Error(error.message);
72
+ }
73
+
74
+ return response.json();
75
+ };
76
+ ```
77
+
78
+ ---
79
+
80
+ ### 2. React Query (TanStack Query)
81
+
82
+ **Setup**:
83
+
84
+ ```tsx
85
+ // app/_layout.tsx
86
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
87
+
88
+ const queryClient = new QueryClient({
89
+ defaultOptions: {
90
+ queries: {
91
+ staleTime: 1000 * 60 * 5, // 5 minutes
92
+ retry: 2,
93
+ },
94
+ },
95
+ });
96
+
97
+ export default function RootLayout() {
98
+ return (
99
+ <QueryClientProvider client={queryClient}>
100
+ <Stack />
101
+ </QueryClientProvider>
102
+ );
103
+ }
104
+ ```
105
+
106
+ **Fetching data**:
107
+
108
+ ```tsx
109
+ import { useQuery } from "@tanstack/react-query";
110
+
111
+ function UserProfile({ userId }: { userId: string }) {
112
+ const { data, isLoading, error, refetch } = useQuery({
113
+ queryKey: ["user", userId],
114
+ queryFn: () => fetchUser(userId),
115
+ });
116
+
117
+ if (isLoading) return <Loading />;
118
+ if (error) return <Error message={error.message} />;
119
+
120
+ return <Profile user={data} />;
121
+ }
122
+ ```
123
+
124
+ **Mutations**:
125
+
126
+ ```tsx
127
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
128
+
129
+ function CreateUserForm() {
130
+ const queryClient = useQueryClient();
131
+
132
+ const mutation = useMutation({
133
+ mutationFn: createUser,
134
+ onSuccess: () => {
135
+ // Invalidate and refetch
136
+ queryClient.invalidateQueries({ queryKey: ["users"] });
137
+ },
138
+ });
139
+
140
+ const handleSubmit = (data: UserData) => {
141
+ mutation.mutate(data);
142
+ };
143
+
144
+ return <Form onSubmit={handleSubmit} isLoading={mutation.isPending} />;
145
+ }
146
+ ```
147
+
148
+ ---
149
+
150
+ ### 3. Error Handling
151
+
152
+ **Comprehensive error handling**:
153
+
154
+ ```tsx
155
+ class ApiError extends Error {
156
+ constructor(message: string, public status: number, public code?: string) {
157
+ super(message);
158
+ this.name = "ApiError";
159
+ }
160
+ }
161
+
162
+ const fetchWithErrorHandling = async (url: string, options?: RequestInit) => {
163
+ try {
164
+ const response = await fetch(url, options);
165
+
166
+ if (!response.ok) {
167
+ const error = await response.json().catch(() => ({}));
168
+ throw new ApiError(
169
+ error.message || "Request failed",
170
+ response.status,
171
+ error.code
172
+ );
173
+ }
174
+
175
+ return response.json();
176
+ } catch (error) {
177
+ if (error instanceof ApiError) {
178
+ throw error;
179
+ }
180
+ // Network error (no internet, timeout, etc.)
181
+ throw new ApiError("Network error", 0, "NETWORK_ERROR");
182
+ }
183
+ };
184
+ ```
185
+
186
+ **Retry logic**:
187
+
188
+ ```tsx
189
+ const fetchWithRetry = async (
190
+ url: string,
191
+ options?: RequestInit,
192
+ retries = 3
193
+ ) => {
194
+ for (let i = 0; i < retries; i++) {
195
+ try {
196
+ return await fetchWithErrorHandling(url, options);
197
+ } catch (error) {
198
+ if (i === retries - 1) throw error;
199
+ // Exponential backoff
200
+ await new Promise((r) => setTimeout(r, Math.pow(2, i) * 1000));
201
+ }
202
+ }
203
+ };
204
+ ```
205
+
206
+ ---
207
+
208
+ ### 4. Authentication
209
+
210
+ **Token management**:
211
+
212
+ ```tsx
213
+ import * as SecureStore from "expo-secure-store";
214
+
215
+ const TOKEN_KEY = "auth_token";
216
+
217
+ export const auth = {
218
+ getToken: () => SecureStore.getItemAsync(TOKEN_KEY),
219
+ setToken: (token: string) => SecureStore.setItemAsync(TOKEN_KEY, token),
220
+ removeToken: () => SecureStore.deleteItemAsync(TOKEN_KEY),
221
+ };
222
+
223
+ // Authenticated fetch wrapper
224
+ const authFetch = async (url: string, options: RequestInit = {}) => {
225
+ const token = await auth.getToken();
226
+
227
+ return fetch(url, {
228
+ ...options,
229
+ headers: {
230
+ ...options.headers,
231
+ Authorization: token ? `Bearer ${token}` : "",
232
+ },
233
+ });
234
+ };
235
+ ```
236
+
237
+ **Token refresh**:
238
+
239
+ ```tsx
240
+ let isRefreshing = false;
241
+ let refreshPromise: Promise<string> | null = null;
242
+
243
+ const getValidToken = async (): Promise<string> => {
244
+ const token = await auth.getToken();
245
+
246
+ if (!token || isTokenExpired(token)) {
247
+ if (!isRefreshing) {
248
+ isRefreshing = true;
249
+ refreshPromise = refreshToken().finally(() => {
250
+ isRefreshing = false;
251
+ refreshPromise = null;
252
+ });
253
+ }
254
+ return refreshPromise!;
255
+ }
256
+
257
+ return token;
258
+ };
259
+ ```
260
+
261
+ ---
262
+
263
+ ### 5. Offline Support
264
+
265
+ **Check network status**:
266
+
267
+ ```tsx
268
+ import NetInfo from "@react-native-community/netinfo";
269
+
270
+ // Hook for network status
271
+ function useNetworkStatus() {
272
+ const [isOnline, setIsOnline] = useState(true);
273
+
274
+ useEffect(() => {
275
+ return NetInfo.addEventListener((state) => {
276
+ setIsOnline(state.isConnected ?? true);
277
+ });
278
+ }, []);
279
+
280
+ return isOnline;
281
+ }
282
+ ```
283
+
284
+ **Offline-first with React Query**:
285
+
286
+ ```tsx
287
+ import { onlineManager } from "@tanstack/react-query";
288
+ import NetInfo from "@react-native-community/netinfo";
289
+
290
+ // Sync React Query with network status
291
+ onlineManager.setEventListener((setOnline) => {
292
+ return NetInfo.addEventListener((state) => {
293
+ setOnline(state.isConnected ?? true);
294
+ });
295
+ });
296
+
297
+ // Queries will pause when offline and resume when online
298
+ ```
299
+
300
+ ---
301
+
302
+ ### 6. Environment Variables
303
+
304
+ **Using environment variables for API configuration**:
305
+
306
+ Expo supports environment variables with the `EXPO_PUBLIC_` prefix. These are inlined at build time and available in your JavaScript code.
307
+
308
+ ```tsx
309
+ // .env
310
+ EXPO_PUBLIC_API_URL=https://api.example.com
311
+ EXPO_PUBLIC_API_VERSION=v1
312
+
313
+ // Usage in code
314
+ const API_URL = process.env.EXPO_PUBLIC_API_URL;
315
+
316
+ const fetchUsers = async () => {
317
+ const response = await fetch(`${API_URL}/users`);
318
+ return response.json();
319
+ };
320
+ ```
321
+
322
+ **Environment-specific configuration**:
323
+
324
+ ```tsx
325
+ // .env.development
326
+ EXPO_PUBLIC_API_URL=http://localhost:3000
327
+
328
+ // .env.production
329
+ EXPO_PUBLIC_API_URL=https://api.production.com
330
+ ```
331
+
332
+ **Creating an API client with environment config**:
333
+
334
+ ```tsx
335
+ // api/client.ts
336
+ const BASE_URL = process.env.EXPO_PUBLIC_API_URL;
337
+
338
+ if (!BASE_URL) {
339
+ throw new Error("EXPO_PUBLIC_API_URL is not defined");
340
+ }
341
+
342
+ export const apiClient = {
343
+ get: async <T,>(path: string): Promise<T> => {
344
+ const response = await fetch(`${BASE_URL}${path}`);
345
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
346
+ return response.json();
347
+ },
348
+
349
+ post: async <T,>(path: string, body: unknown): Promise<T> => {
350
+ const response = await fetch(`${BASE_URL}${path}`, {
351
+ method: "POST",
352
+ headers: { "Content-Type": "application/json" },
353
+ body: JSON.stringify(body),
354
+ });
355
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
356
+ return response.json();
357
+ },
358
+ };
359
+ ```
360
+
361
+ **Important notes**:
362
+
363
+ - Only variables prefixed with `EXPO_PUBLIC_` are exposed to the client bundle
364
+ - Never put secrets (API keys with write access, database passwords) in `EXPO_PUBLIC_` variables—they're visible in the built app
365
+ - Environment variables are inlined at **build time**, not runtime
366
+ - Restart the dev server after changing `.env` files
367
+ - For server-side secrets in API routes, use variables without the `EXPO_PUBLIC_` prefix
368
+
369
+ **TypeScript support**:
370
+
371
+ ```tsx
372
+ // types/env.d.ts
373
+ declare global {
374
+ namespace NodeJS {
375
+ interface ProcessEnv {
376
+ EXPO_PUBLIC_API_URL: string;
377
+ EXPO_PUBLIC_API_VERSION?: string;
378
+ }
379
+ }
380
+ }
381
+
382
+ export {};
383
+ ```
384
+
385
+ ---
386
+
387
+ ### 7. Request Cancellation
388
+
389
+ **Cancel on unmount**:
390
+
391
+ ```tsx
392
+ useEffect(() => {
393
+ const controller = new AbortController();
394
+
395
+ fetch(url, { signal: controller.signal })
396
+ .then((response) => response.json())
397
+ .then(setData)
398
+ .catch((error) => {
399
+ if (error.name !== "AbortError") {
400
+ setError(error);
401
+ }
402
+ });
403
+
404
+ return () => controller.abort();
405
+ }, [url]);
406
+ ```
407
+
408
+ **With React Query** (automatic):
409
+
410
+ ```tsx
411
+ // React Query automatically cancels requests when queries are invalidated
412
+ // or components unmount
413
+ ```
414
+
415
+ ---
416
+
417
+ ## Decision Tree
418
+
419
+ ```
420
+ User asks about networking
421
+ |-- Route-level data loading (web, SDK 55+)?
422
+ | \-- Expo Router loaders — see references/expo-router-loaders.md
423
+ |
424
+ |-- Basic fetch?
425
+ | \-- Use fetch API with error handling
426
+ |
427
+ |-- Need caching/state management?
428
+ | |-- Complex app -> React Query (TanStack Query)
429
+ | \-- Simpler needs -> SWR or custom hooks
430
+ |
431
+ |-- Authentication?
432
+ | |-- Token storage -> expo-secure-store
433
+ | \-- Token refresh -> Implement refresh flow
434
+ |
435
+ |-- Error handling?
436
+ | |-- Network errors -> Check connectivity first
437
+ | |-- HTTP errors -> Parse response, throw typed errors
438
+ | \-- Retries -> Exponential backoff
439
+ |
440
+ |-- Offline support?
441
+ | |-- Check status -> NetInfo
442
+ | \-- Queue requests -> React Query persistence
443
+ |
444
+ |-- Environment/API config?
445
+ | |-- Client-side URLs -> EXPO_PUBLIC_ prefix in .env
446
+ | |-- Server secrets -> Non-prefixed env vars (API routes only)
447
+ | \-- Multiple environments -> .env.development, .env.production
448
+ |
449
+ \-- Performance?
450
+ |-- Caching -> React Query with staleTime
451
+ |-- Deduplication -> React Query handles this
452
+ \-- Cancellation -> AbortController or React Query
453
+ ```
454
+
455
+ ## Common Mistakes
456
+
457
+ **Wrong: No error handling**
458
+
459
+ ```tsx
460
+ const data = await fetch(url).then((r) => r.json());
461
+ ```
462
+
463
+ **Right: Check response status**
464
+
465
+ ```tsx
466
+ const response = await fetch(url);
467
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
468
+ const data = await response.json();
469
+ ```
470
+
471
+ **Wrong: Storing tokens in AsyncStorage**
472
+
473
+ ```tsx
474
+ await AsyncStorage.setItem("token", token); // Not secure!
475
+ ```
476
+
477
+ **Right: Use SecureStore for sensitive data**
478
+
479
+ ```tsx
480
+ await SecureStore.setItemAsync("token", token);
481
+ ```
482
+
483
+ ## Example Invocations
484
+
485
+ User: "How do I make API calls in React Native?"
486
+ -> Use fetch, wrap with error handling
487
+
488
+ User: "Should I use React Query or SWR?"
489
+ -> React Query for complex apps, SWR for simpler needs
490
+
491
+ User: "My app needs to work offline"
492
+ -> Use NetInfo for status, React Query persistence for caching
493
+
494
+ User: "How do I handle authentication tokens?"
495
+ -> Store in expo-secure-store, implement refresh flow
496
+
497
+ User: "API calls are slow"
498
+ -> Check caching strategy, use React Query staleTime
499
+
500
+ User: "How do I configure different API URLs for dev and prod?"
501
+ -> Use EXPO_PUBLIC_ env vars with .env.development and .env.production files
502
+
503
+ User: "Where should I put my API key?"
504
+ -> Client-safe keys: EXPO_PUBLIC_ in .env. Secret keys: non-prefixed env vars in API routes only
505
+
506
+ User: "How do I load data for a page in Expo Router?"
507
+ -> See references/expo-router-loaders.md for route-level loaders (web, SDK 55+). For native, use React Query or fetch.
@@ -0,0 +1,4 @@
1
+ display_name: "Native Data Fetching"
2
+ short_description: "implementing or debugging ANY network request, API call, or data fetching"
3
+ default_prompt:
4
+ - "Use $native-data-fetching: implementing or debugging ANY network request, API call, or data fetching."