@neyugn/agent-kits 0.1.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.
- package/LICENSE +21 -0
- package/README.md +514 -0
- package/README.vi.md +410 -0
- package/README.zh.md +410 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +422 -0
- package/kits/coder/ARCHITECTURE.md +289 -0
- package/kits/coder/agents/ai-engineer.md +344 -0
- package/kits/coder/agents/backend-specialist.md +270 -0
- package/kits/coder/agents/cloud-architect.md +363 -0
- package/kits/coder/agents/code-reviewer.md +284 -0
- package/kits/coder/agents/data-engineer.md +401 -0
- package/kits/coder/agents/database-specialist.md +251 -0
- package/kits/coder/agents/debugger.md +209 -0
- package/kits/coder/agents/devops-engineer.md +281 -0
- package/kits/coder/agents/documentation-writer.md +296 -0
- package/kits/coder/agents/frontend-specialist.md +298 -0
- package/kits/coder/agents/i18n-specialist.md +348 -0
- package/kits/coder/agents/integration-specialist.md +314 -0
- package/kits/coder/agents/mobile-developer.md +271 -0
- package/kits/coder/agents/multi-tenant-architect.md +281 -0
- package/kits/coder/agents/orchestrator.md +263 -0
- package/kits/coder/agents/performance-analyst.md +327 -0
- package/kits/coder/agents/project-planner.md +277 -0
- package/kits/coder/agents/queue-specialist.md +282 -0
- package/kits/coder/agents/realtime-specialist.md +267 -0
- package/kits/coder/agents/security-auditor.md +253 -0
- package/kits/coder/agents/test-engineer.md +315 -0
- package/kits/coder/agents/ux-researcher.md +388 -0
- package/kits/coder/rules/.cursorrules +287 -0
- package/kits/coder/rules/CLAUDE.md +287 -0
- package/kits/coder/rules/CODEX.md +287 -0
- package/kits/coder/rules/GEMINI.md +287 -0
- package/kits/coder/scripts/checklist.py +318 -0
- package/kits/coder/scripts/kit_status.py +292 -0
- package/kits/coder/scripts/skills_manager.py +243 -0
- package/kits/coder/scripts/verify_all.py +391 -0
- package/kits/coder/skills/accessibility-patterns/SKILL.md +372 -0
- package/kits/coder/skills/accessibility-patterns/scripts/a11y_checker.py +211 -0
- package/kits/coder/skills/ai-rag-patterns/SKILL.md +444 -0
- package/kits/coder/skills/api-patterns/SKILL.md +316 -0
- package/kits/coder/skills/api-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/api-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/api-patterns/scripts/api_validator.py +253 -0
- package/kits/coder/skills/api-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/auth-patterns/SKILL.md +267 -0
- package/kits/coder/skills/aws-patterns/SKILL.md +576 -0
- package/kits/coder/skills/brainstorming/SKILL.md +370 -0
- package/kits/coder/skills/brainstorming/assets/.gitkeep +1 -0
- package/kits/coder/skills/brainstorming/references/deep-dive.md +21 -0
- package/kits/coder/skills/brainstorming/scripts/validate.py +56 -0
- package/kits/coder/skills/clean-code/SKILL.md +240 -0
- package/kits/coder/skills/clean-code/assets/.gitkeep +1 -0
- package/kits/coder/skills/clean-code/references/deep-dive.md +21 -0
- package/kits/coder/skills/clean-code/scripts/lint_runner.py +186 -0
- package/kits/coder/skills/clean-code/scripts/validate.py +56 -0
- package/kits/coder/skills/database-design/SKILL.md +255 -0
- package/kits/coder/skills/database-design/assets/.gitkeep +1 -0
- package/kits/coder/skills/database-design/references/deep-dive.md +21 -0
- package/kits/coder/skills/database-design/scripts/schema_validator.py +272 -0
- package/kits/coder/skills/database-design/scripts/validate.py +56 -0
- package/kits/coder/skills/docker-patterns/SKILL.md +240 -0
- package/kits/coder/skills/documentation-templates/SKILL.md +441 -0
- package/kits/coder/skills/e2e-testing/SKILL.md +457 -0
- package/kits/coder/skills/flutter-patterns/SKILL.md +330 -0
- package/kits/coder/skills/frontend-design/SKILL.md +127 -0
- package/kits/coder/skills/github-actions/SKILL.md +349 -0
- package/kits/coder/skills/gitlab-ci-patterns/SKILL.md +466 -0
- package/kits/coder/skills/graphql-patterns/SKILL.md +558 -0
- package/kits/coder/skills/i18n-localization/SKILL.md +345 -0
- package/kits/coder/skills/i18n-localization/scripts/i18n_checker.py +267 -0
- package/kits/coder/skills/kubernetes-patterns/SKILL.md +357 -0
- package/kits/coder/skills/mermaid-diagrams/SKILL.md +351 -0
- package/kits/coder/skills/mobile-design/SKILL.md +305 -0
- package/kits/coder/skills/monitoring-observability/SKILL.md +458 -0
- package/kits/coder/skills/multi-tenancy/SKILL.md +317 -0
- package/kits/coder/skills/multi-tenancy/assets/.gitkeep +1 -0
- package/kits/coder/skills/multi-tenancy/references/deep-dive.md +21 -0
- package/kits/coder/skills/multi-tenancy/scripts/validate.py +56 -0
- package/kits/coder/skills/nodejs-best-practices/SKILL.md +220 -0
- package/kits/coder/skills/performance-profiling/SKILL.md +333 -0
- package/kits/coder/skills/performance-profiling/assets/.gitkeep +1 -0
- package/kits/coder/skills/performance-profiling/references/deep-dive.md +21 -0
- package/kits/coder/skills/performance-profiling/scripts/validate.py +56 -0
- package/kits/coder/skills/plan-writing/SKILL.md +360 -0
- package/kits/coder/skills/plan-writing/assets/.gitkeep +1 -0
- package/kits/coder/skills/plan-writing/references/deep-dive.md +21 -0
- package/kits/coder/skills/plan-writing/scripts/validate.py +56 -0
- package/kits/coder/skills/postgres-patterns/SKILL.md +361 -0
- package/kits/coder/skills/prompt-engineering/SKILL.md +277 -0
- package/kits/coder/skills/queue-patterns/SKILL.md +359 -0
- package/kits/coder/skills/queue-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/queue-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/queue-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/react-native-patterns/SKILL.md +393 -0
- package/kits/coder/skills/react-patterns/SKILL.md +319 -0
- package/kits/coder/skills/realtime-patterns/SKILL.md +506 -0
- package/kits/coder/skills/realtime-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/realtime-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/realtime-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/redis-patterns/SKILL.md +484 -0
- package/kits/coder/skills/security-fundamentals/SKILL.md +363 -0
- package/kits/coder/skills/security-fundamentals/assets/.gitkeep +1 -0
- package/kits/coder/skills/security-fundamentals/references/deep-dive.md +21 -0
- package/kits/coder/skills/security-fundamentals/scripts/security_scan.py +326 -0
- package/kits/coder/skills/security-fundamentals/scripts/validate.py +56 -0
- package/kits/coder/skills/seo-patterns/SKILL.md +262 -0
- package/kits/coder/skills/seo-patterns/scripts/seo_checker.py +211 -0
- package/kits/coder/skills/systematic-debugging/SKILL.md +478 -0
- package/kits/coder/skills/systematic-debugging/assets/.gitkeep +1 -0
- package/kits/coder/skills/systematic-debugging/references/deep-dive.md +21 -0
- package/kits/coder/skills/systematic-debugging/scripts/validate.py +56 -0
- package/kits/coder/skills/tailwind-patterns/SKILL.md +395 -0
- package/kits/coder/skills/terraform-patterns/SKILL.md +470 -0
- package/kits/coder/skills/testing-patterns/SKILL.md +285 -0
- package/kits/coder/skills/testing-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/testing-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/testing-patterns/scripts/test_runner.py +219 -0
- package/kits/coder/skills/testing-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/typescript-patterns/SKILL.md +417 -0
- package/kits/coder/skills/ui-ux-pro-max/SKILL.md +364 -0
- package/kits/coder/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/kits/coder/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/kits/coder/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/kits/coder/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/kits/coder/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/kits/coder/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/kits/coder/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/kits/coder/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/kits/coder/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/kits/coder/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/kits/coder/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/kits/coder/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/core.py +257 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/design_system.py +488 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/search.py +76 -0
- package/kits/coder/workflows/.gitkeep +20 -0
- package/kits/coder/workflows/create.md +152 -0
- package/kits/coder/workflows/debug.md +223 -0
- package/kits/coder/workflows/deploy.md +283 -0
- package/kits/coder/workflows/orchestrate.md +243 -0
- package/kits/coder/workflows/plan.md +134 -0
- package/kits/coder/workflows/test.md +237 -0
- package/kits/coder/workflows/ui-ux-pro-max.md +109 -0
- package/package.json +49 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: react-native-patterns
|
|
3
|
+
description: React Native with Expo development patterns. Use when building mobile apps with React Native, implementing navigation, native modules, or offline-first architecture. Covers Expo Router, EAS Build, and performance.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash
|
|
5
|
+
version: 1.0
|
|
6
|
+
priority: MEDIUM
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# React Native Patterns - Mobile Excellence with Expo
|
|
10
|
+
|
|
11
|
+
> **Philosophy:** Use Expo unless you have a very specific reason not to. OTA updates, managed native code, and faster development are worth the trade-offs.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🎯 Core Principles
|
|
16
|
+
|
|
17
|
+
| Principle | Rule |
|
|
18
|
+
| ------------------ | ----------------------------------------------------- |
|
|
19
|
+
| **Expo First** | Start with Expo, eject only when absolutely necessary |
|
|
20
|
+
| **Platform Aware** | One codebase, platform-specific polish |
|
|
21
|
+
| **Offline Ready** | Assume network is unreliable |
|
|
22
|
+
| **Performance** | FlashList, memoization, native thread animations |
|
|
23
|
+
| **Type Safe** | TypeScript is mandatory |
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
❌ WRONG: Bare React Native for simple apps
|
|
27
|
+
✅ CORRECT: Expo with EAS Build, eject later if needed
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 📁 Project Structure
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
src/
|
|
36
|
+
├── app/ # Expo Router screens
|
|
37
|
+
│ ├── (auth)/ # Auth group
|
|
38
|
+
│ │ ├── login.tsx
|
|
39
|
+
│ │ └── register.tsx
|
|
40
|
+
│ ├── (tabs)/ # Tab navigation
|
|
41
|
+
│ │ ├── _layout.tsx
|
|
42
|
+
│ │ ├── index.tsx
|
|
43
|
+
│ │ └── profile.tsx
|
|
44
|
+
│ └── _layout.tsx # Root layout
|
|
45
|
+
├── components/
|
|
46
|
+
│ ├── ui/ # Reusable UI components
|
|
47
|
+
│ └── features/ # Feature-specific components
|
|
48
|
+
├── hooks/ # Custom hooks
|
|
49
|
+
├── services/ # API and native services
|
|
50
|
+
├── stores/ # State management
|
|
51
|
+
├── utils/ # Utilities
|
|
52
|
+
└── types/ # TypeScript types
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 🔀 Expo vs Bare React Native
|
|
58
|
+
|
|
59
|
+
| Feature | Expo | Bare RN |
|
|
60
|
+
| ------------------ | -------------- | -------------- |
|
|
61
|
+
| Setup complexity | Low | High |
|
|
62
|
+
| Native modules | EAS Build | Manual linking |
|
|
63
|
+
| OTA updates | Built-in | Manual setup |
|
|
64
|
+
| Build service | EAS | Custom CI |
|
|
65
|
+
| Custom native code | Config plugins | Direct access |
|
|
66
|
+
| Time to MVP | Fast | Slow |
|
|
67
|
+
|
|
68
|
+
### When to Use Bare React Native
|
|
69
|
+
|
|
70
|
+
- Need custom native modules not available in Expo
|
|
71
|
+
- Existing native app integration
|
|
72
|
+
- Very specific native build requirements
|
|
73
|
+
- Corporate restrictions on cloud build services
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 🚀 Quick Start
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Create new Expo project
|
|
81
|
+
npx create-expo-app@latest my-app -t expo-template-blank-typescript
|
|
82
|
+
|
|
83
|
+
# Install essential dependencies
|
|
84
|
+
npx expo install expo-router expo-status-bar react-native-safe-area-context
|
|
85
|
+
npx expo install @react-native-async-storage/async-storage
|
|
86
|
+
npx expo install expo-secure-store expo-haptics
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 🧭 Expo Router Navigation
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
// app/_layout.tsx
|
|
95
|
+
import { Stack } from 'expo-router'
|
|
96
|
+
|
|
97
|
+
export default function RootLayout() {
|
|
98
|
+
return (
|
|
99
|
+
<Stack screenOptions={{ headerShown: false }}>
|
|
100
|
+
<Stack.Screen name="(tabs)" />
|
|
101
|
+
<Stack.Screen name="(auth)" />
|
|
102
|
+
<Stack.Screen name="modal" options={{ presentation: 'modal' }} />
|
|
103
|
+
</Stack>
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// app/(tabs)/_layout.tsx
|
|
108
|
+
import { Tabs } from 'expo-router'
|
|
109
|
+
import { Home, User } from 'lucide-react-native'
|
|
110
|
+
|
|
111
|
+
export default function TabLayout() {
|
|
112
|
+
return (
|
|
113
|
+
<Tabs>
|
|
114
|
+
<Tabs.Screen
|
|
115
|
+
name="index"
|
|
116
|
+
options={{
|
|
117
|
+
title: 'Home',
|
|
118
|
+
tabBarIcon: ({ color, size }) => <Home size={size} color={color} />,
|
|
119
|
+
}}
|
|
120
|
+
/>
|
|
121
|
+
<Tabs.Screen
|
|
122
|
+
name="profile"
|
|
123
|
+
options={{
|
|
124
|
+
title: 'Profile',
|
|
125
|
+
tabBarIcon: ({ color, size }) => <User size={size} color={color} />,
|
|
126
|
+
}}
|
|
127
|
+
/>
|
|
128
|
+
</Tabs>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Programmatic Navigation
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { router } from "expo-router";
|
|
137
|
+
|
|
138
|
+
// Navigate
|
|
139
|
+
router.push("/profile/123");
|
|
140
|
+
router.replace("/login");
|
|
141
|
+
router.back();
|
|
142
|
+
|
|
143
|
+
// With params
|
|
144
|
+
router.push({
|
|
145
|
+
pathname: "/product/[id]",
|
|
146
|
+
params: { id: "123", referrer: "home" },
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 💾 Offline-First with React Query
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// providers/QueryProvider.tsx
|
|
156
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
157
|
+
import { createAsyncStoragePersister } from "@tanstack/query-async-storage-persister";
|
|
158
|
+
import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client";
|
|
159
|
+
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
160
|
+
import NetInfo from "@react-native-community/netinfo";
|
|
161
|
+
import { onlineManager } from "@tanstack/react-query";
|
|
162
|
+
|
|
163
|
+
// Sync online status
|
|
164
|
+
onlineManager.setEventListener((setOnline) => {
|
|
165
|
+
return NetInfo.addEventListener((state) => {
|
|
166
|
+
setOnline(!!state.isConnected);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const queryClient = new QueryClient({
|
|
171
|
+
defaultOptions: {
|
|
172
|
+
queries: {
|
|
173
|
+
gcTime: 1000 * 60 * 60 * 24, // 24 hours
|
|
174
|
+
staleTime: 1000 * 60 * 5, // 5 minutes
|
|
175
|
+
networkMode: "offlineFirst",
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
const persister = createAsyncStoragePersister({
|
|
181
|
+
storage: AsyncStorage,
|
|
182
|
+
key: "REACT_QUERY_CACHE",
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## ⚡ Performance Patterns
|
|
189
|
+
|
|
190
|
+
### FlashList over FlatList
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
import { FlashList } from '@shopify/flash-list'
|
|
194
|
+
import { memo, useCallback } from 'react'
|
|
195
|
+
|
|
196
|
+
const ProductItem = memo(function ProductItem({ item, onPress }) {
|
|
197
|
+
const handlePress = useCallback(() => onPress(item.id), [item.id, onPress])
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<Pressable onPress={handlePress}>
|
|
201
|
+
<FastImage source={{ uri: item.image }} />
|
|
202
|
+
<Text>{item.name}</Text>
|
|
203
|
+
</Pressable>
|
|
204
|
+
)
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
export function ProductList({ products, onProductPress }) {
|
|
208
|
+
const renderItem = useCallback(
|
|
209
|
+
({ item }) => <ProductItem item={item} onPress={onProductPress} />,
|
|
210
|
+
[onProductPress]
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
return (
|
|
214
|
+
<FlashList
|
|
215
|
+
data={products}
|
|
216
|
+
renderItem={renderItem}
|
|
217
|
+
estimatedItemSize={100}
|
|
218
|
+
removeClippedSubviews={true}
|
|
219
|
+
/>
|
|
220
|
+
)
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Reanimated for 60fps Animations
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
import Animated, {
|
|
228
|
+
useAnimatedStyle,
|
|
229
|
+
useSharedValue,
|
|
230
|
+
withSpring,
|
|
231
|
+
} from 'react-native-reanimated'
|
|
232
|
+
|
|
233
|
+
function AnimatedButton({ onPress, children }) {
|
|
234
|
+
const scale = useSharedValue(1)
|
|
235
|
+
|
|
236
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
237
|
+
transform: [{ scale: scale.value }],
|
|
238
|
+
}))
|
|
239
|
+
|
|
240
|
+
const handlePressIn = () => {
|
|
241
|
+
scale.value = withSpring(0.95)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const handlePressOut = () => {
|
|
245
|
+
scale.value = withSpring(1)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return (
|
|
249
|
+
<Animated.View style={animatedStyle}>
|
|
250
|
+
<Pressable
|
|
251
|
+
onPress={onPress}
|
|
252
|
+
onPressIn={handlePressIn}
|
|
253
|
+
onPressOut={handlePressOut}
|
|
254
|
+
>
|
|
255
|
+
{children}
|
|
256
|
+
</Pressable>
|
|
257
|
+
</Animated.View>
|
|
258
|
+
)
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## 📱 Platform-Specific Code
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
import { Platform, StyleSheet } from "react-native";
|
|
268
|
+
|
|
269
|
+
const styles = StyleSheet.create({
|
|
270
|
+
shadow: Platform.select({
|
|
271
|
+
ios: {
|
|
272
|
+
shadowColor: "#000",
|
|
273
|
+
shadowOffset: { width: 0, height: 2 },
|
|
274
|
+
shadowOpacity: 0.1,
|
|
275
|
+
shadowRadius: 4,
|
|
276
|
+
},
|
|
277
|
+
android: {
|
|
278
|
+
elevation: 4,
|
|
279
|
+
},
|
|
280
|
+
}),
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// Or use file-based separation
|
|
284
|
+
// Button.ios.tsx
|
|
285
|
+
// Button.android.tsx
|
|
286
|
+
// Button.web.tsx
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## 🔐 Native Services
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
// Haptics
|
|
295
|
+
import * as Haptics from "expo-haptics";
|
|
296
|
+
|
|
297
|
+
if (Platform.OS !== "web") {
|
|
298
|
+
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Secure Storage
|
|
302
|
+
import * as SecureStore from "expo-secure-store";
|
|
303
|
+
|
|
304
|
+
await SecureStore.setItemAsync("token", authToken);
|
|
305
|
+
const token = await SecureStore.getItemAsync("token");
|
|
306
|
+
|
|
307
|
+
// Biometrics
|
|
308
|
+
import * as LocalAuthentication from "expo-local-authentication";
|
|
309
|
+
|
|
310
|
+
const result = await LocalAuthentication.authenticateAsync({
|
|
311
|
+
promptMessage: "Authenticate",
|
|
312
|
+
});
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## 📦 EAS Build & Submit
|
|
318
|
+
|
|
319
|
+
```json
|
|
320
|
+
// eas.json
|
|
321
|
+
{
|
|
322
|
+
"build": {
|
|
323
|
+
"development": {
|
|
324
|
+
"developmentClient": true,
|
|
325
|
+
"distribution": "internal"
|
|
326
|
+
},
|
|
327
|
+
"preview": {
|
|
328
|
+
"distribution": "internal",
|
|
329
|
+
"android": { "buildType": "apk" }
|
|
330
|
+
},
|
|
331
|
+
"production": {
|
|
332
|
+
"autoIncrement": true
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
# Build commands
|
|
340
|
+
eas build --platform ios --profile production
|
|
341
|
+
eas build --platform android --profile production
|
|
342
|
+
|
|
343
|
+
# Submit to stores
|
|
344
|
+
eas submit --platform ios
|
|
345
|
+
eas submit --platform android
|
|
346
|
+
|
|
347
|
+
# OTA updates
|
|
348
|
+
eas update --branch production --message "Bug fixes"
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## 🚨 Anti-Patterns
|
|
354
|
+
|
|
355
|
+
| ❌ Don't | ✅ Do |
|
|
356
|
+
| ---------------------------- | ------------------------------------ |
|
|
357
|
+
| Use FlatList for large lists | Use FlashList |
|
|
358
|
+
| Inline styles | Use StyleSheet.create |
|
|
359
|
+
| Fetch in render | Use useEffect or React Query |
|
|
360
|
+
| Ignore platform differences | Test on both iOS and Android |
|
|
361
|
+
| Store secrets in code | Use environment variables |
|
|
362
|
+
| Skip error boundaries | Handle crashes gracefully |
|
|
363
|
+
| Animate on JS thread | Use Reanimated for native animations |
|
|
364
|
+
| Forget offline handling | Implement offline-first |
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## ✅ Self-Check Before Completing
|
|
369
|
+
|
|
370
|
+
| Check | Question |
|
|
371
|
+
| ------------------- | ---------------------------------------- |
|
|
372
|
+
| ✅ **Expo?** | Using Expo unless specifically required? |
|
|
373
|
+
| ✅ **TypeScript?** | Full type coverage? |
|
|
374
|
+
| ✅ **Offline?** | Handles offline state gracefully? |
|
|
375
|
+
| ✅ **Platform?** | Tested on both iOS and Android? |
|
|
376
|
+
| ✅ **Performance?** | FlashList, memoization, Reanimated? |
|
|
377
|
+
| ✅ **Secure?** | Tokens in SecureStore, not AsyncStorage? |
|
|
378
|
+
| ✅ **Navigation?** | Expo Router properly configured? |
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## 🔗 Related Skills
|
|
383
|
+
|
|
384
|
+
| Need | Skill |
|
|
385
|
+
| ------------------ | ------------------ |
|
|
386
|
+
| Flutter comparison | `flutter-patterns` |
|
|
387
|
+
| Mobile design | `mobile-design` |
|
|
388
|
+
| React patterns | `react-patterns` |
|
|
389
|
+
| Testing | `testing-patterns` |
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
> **Remember:** Mobile users expect instant responses, offline capability, and native feel. Every millisecond of loading time matters.
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: react-patterns
|
|
3
|
+
description: React and Next.js performance optimization and design patterns. Use when building React components, optimizing performance, eliminating waterfalls, reducing bundle size, or implementing server/client-side optimizations. Covers hooks, composition, state management, React 19 features, and Vercel best practices.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Glob, Grep
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# React Patterns
|
|
8
|
+
|
|
9
|
+
> **Philosophy:** Measure first, optimize second. React is about composition - build small, combine thoughtfully.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 📑 Content Map
|
|
14
|
+
|
|
15
|
+
| File | When to Read |
|
|
16
|
+
| ------------------------------- | ----------------------------- |
|
|
17
|
+
| `references/hook-patterns.md` | Advanced custom hooks |
|
|
18
|
+
| `references/performance.md` | Deep performance optimization |
|
|
19
|
+
| `references/nextjs-patterns.md` | Next.js App Router specific |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 1. Component Design Principles
|
|
24
|
+
|
|
25
|
+
### Component Types
|
|
26
|
+
|
|
27
|
+
| Type | Use | State | Example |
|
|
28
|
+
| ------------------ | --------------------- | ----------------- | ------------------------ |
|
|
29
|
+
| **Server** | Data fetching, static | None | Page layouts, data grids |
|
|
30
|
+
| **Client** | Interactivity | useState, effects | Forms, modals, dropdowns |
|
|
31
|
+
| **Presentational** | UI display | Props only | Button, Card, Avatar |
|
|
32
|
+
| **Container** | Logic/state | Heavy state | UserProfileContainer |
|
|
33
|
+
|
|
34
|
+
### Design Rules
|
|
35
|
+
|
|
36
|
+
| Rule | Rationale |
|
|
37
|
+
| ---------------------------- | -------------------------------- |
|
|
38
|
+
| One responsibility | Easier testing, reuse |
|
|
39
|
+
| Props down, events up | Predictable data flow |
|
|
40
|
+
| Composition over inheritance | Flexibility, avoid prop drilling |
|
|
41
|
+
| Small, focused components | Better tree shaking, readability |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 2. Hook Patterns
|
|
46
|
+
|
|
47
|
+
### When to Extract Custom Hooks
|
|
48
|
+
|
|
49
|
+
| Pattern | Extract When |
|
|
50
|
+
| ----------------- | -------------------------------------- |
|
|
51
|
+
| `useLocalStorage` | Same storage logic needed |
|
|
52
|
+
| `useDebounce` | Multiple debounced values |
|
|
53
|
+
| `useFetch` | Repeated fetch patterns |
|
|
54
|
+
| `useForm` | Complex form state |
|
|
55
|
+
| `useClickOutside` | Multiple modal/dropdown components |
|
|
56
|
+
| `usePrevious` | Need previous value in multiple places |
|
|
57
|
+
|
|
58
|
+
### Hook Rules (CRITICAL)
|
|
59
|
+
|
|
60
|
+
| Rule | Violation Consequence |
|
|
61
|
+
| ----------------------- | -------------------------------- |
|
|
62
|
+
| Top level only | Inconsistent state |
|
|
63
|
+
| Same order every render | React loses track of state |
|
|
64
|
+
| Prefix with "use" | Lint error, convention violation |
|
|
65
|
+
| Clean up effects | Memory leaks, stale closures |
|
|
66
|
+
|
|
67
|
+
### React 19 New Hooks
|
|
68
|
+
|
|
69
|
+
| Hook | Purpose | Example Use Case |
|
|
70
|
+
| ---------------- | ------------------------ | ------------------------------ |
|
|
71
|
+
| `useActionState` | Form submission state | Server Actions with pending UI |
|
|
72
|
+
| `useOptimistic` | Optimistic UI updates | Like button, comment posting |
|
|
73
|
+
| `use` | Read resources in render | Reading promises, context |
|
|
74
|
+
| `useFormStatus` | Form submission status | Submit button loading state |
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 3. State Management Selection
|
|
79
|
+
|
|
80
|
+
### Decision Tree
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
State scope?
|
|
84
|
+
│
|
|
85
|
+
├── Single component → useState
|
|
86
|
+
│
|
|
87
|
+
├── Parent-child (1-2 levels) → Lift state up
|
|
88
|
+
│
|
|
89
|
+
├── Subtree (3+ levels) → Context
|
|
90
|
+
│
|
|
91
|
+
├── Server state → React Query / SWR
|
|
92
|
+
│
|
|
93
|
+
└── Complex global → Zustand / Redux Toolkit
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### State Placement Guide
|
|
97
|
+
|
|
98
|
+
| Scope | Solution | When to Use |
|
|
99
|
+
| ---------------- | ----------------- | ------------------------- |
|
|
100
|
+
| Single component | `useState` | Form inputs, toggles |
|
|
101
|
+
| Parent-child | Props + callbacks | Controlled components |
|
|
102
|
+
| Subtree | Context | Theme, auth, locale |
|
|
103
|
+
| Server state | React Query | API data, caching |
|
|
104
|
+
| Complex global | Zustand | Cart, filters, multi-step |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 4. Performance Optimization (Priority Order)
|
|
109
|
+
|
|
110
|
+
### 🔴 CRITICAL: Eliminating Waterfalls
|
|
111
|
+
|
|
112
|
+
| Pattern | Problem | Solution |
|
|
113
|
+
| ------------------- | ---------------------------- | ----------------------------------- |
|
|
114
|
+
| `async-defer-await` | Blocking unrelated code | Move await into branches where used |
|
|
115
|
+
| `async-parallel` | Sequential independent calls | `Promise.all()` for independent ops |
|
|
116
|
+
| `async-suspense` | Waiting for all data | Use Suspense to stream content |
|
|
117
|
+
|
|
118
|
+
### 🔴 CRITICAL: Bundle Size
|
|
119
|
+
|
|
120
|
+
| Pattern | Problem | Solution |
|
|
121
|
+
| ----------------------- | ------------------------- | ------------------------------ |
|
|
122
|
+
| `bundle-barrel-imports` | Importing entire library | Import directly from module |
|
|
123
|
+
| `bundle-dynamic` | Loading unused code | `next/dynamic` for heavy comps |
|
|
124
|
+
| `bundle-defer-third` | Analytics blocking render | Load after hydration |
|
|
125
|
+
|
|
126
|
+
### 🟡 HIGH: Server-Side Performance
|
|
127
|
+
|
|
128
|
+
| Pattern | Problem | Solution |
|
|
129
|
+
| ---------------------- | --------------------- | ------------------------------ |
|
|
130
|
+
| `server-cache-react` | Duplicate requests | `React.cache()` per-request |
|
|
131
|
+
| `server-serialization` | Large client payloads | Minimize data passed to client |
|
|
132
|
+
| `server-parallel` | Sequential fetching | Restructure for parallel |
|
|
133
|
+
|
|
134
|
+
### 🟢 MEDIUM: Re-render Optimization
|
|
135
|
+
|
|
136
|
+
| Pattern | Problem | Solution |
|
|
137
|
+
| ------------------------ | ---------------------------- | ----------------------------- |
|
|
138
|
+
| `rerender-memo` | Expensive child re-renders | Extract to memoized component |
|
|
139
|
+
| `rerender-dependencies` | Unstable effect dependencies | Use primitive dependencies |
|
|
140
|
+
| `rerender-derived-state` | Subscribing to raw values | Subscribe to derived booleans |
|
|
141
|
+
| `rerender-lazy-init` | Expensive initial state | Pass function to useState |
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 5. Composition Patterns
|
|
146
|
+
|
|
147
|
+
### Compound Components
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
// ✅ Flexible composition
|
|
151
|
+
<Tabs defaultValue="tab1">
|
|
152
|
+
<Tabs.List>
|
|
153
|
+
<Tabs.Trigger value="tab1">Tab 1</Tabs.Trigger>
|
|
154
|
+
<Tabs.Trigger value="tab2">Tab 2</Tabs.Trigger>
|
|
155
|
+
</Tabs.List>
|
|
156
|
+
<Tabs.Content value="tab1">Content 1</Tabs.Content>
|
|
157
|
+
<Tabs.Content value="tab2">Content 2</Tabs.Content>
|
|
158
|
+
</Tabs>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Use for:** Tabs, Accordion, Dropdown, Modal, Dialog
|
|
162
|
+
|
|
163
|
+
### Render Props vs Hooks
|
|
164
|
+
|
|
165
|
+
| Use Case | Prefer This | Why |
|
|
166
|
+
| ------------------ | ------------ | ------------------------ |
|
|
167
|
+
| Reusable logic | Custom hook | Cleaner, easier to test |
|
|
168
|
+
| Render flexibility | Render props | Consumer controls UI |
|
|
169
|
+
| Cross-cutting | HOC | Auth, logging, analytics |
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 6. Error Handling
|
|
174
|
+
|
|
175
|
+
### Error Boundary Strategy
|
|
176
|
+
|
|
177
|
+
| Scope | Placement | Fallback |
|
|
178
|
+
| --------- | ---------------------- | --------------------------- |
|
|
179
|
+
| App-wide | Root level | "Something went wrong" page |
|
|
180
|
+
| Feature | Route/feature level | Feature-specific message |
|
|
181
|
+
| Component | Around risky component | Graceful degradation |
|
|
182
|
+
|
|
183
|
+
### Recovery Pattern
|
|
184
|
+
|
|
185
|
+
| Step | Action |
|
|
186
|
+
| ---- | ------------------------------ |
|
|
187
|
+
| 1 | Show fallback UI |
|
|
188
|
+
| 2 | Log error (Sentry, DataDog) |
|
|
189
|
+
| 3 | Offer retry option |
|
|
190
|
+
| 4 | Preserve user data if possible |
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 7. TypeScript Integration
|
|
195
|
+
|
|
196
|
+
### Props Typing
|
|
197
|
+
|
|
198
|
+
| Pattern | Use For | Example |
|
|
199
|
+
| --------- | --------------------- | ----------------------------- |
|
|
200
|
+
| Interface | Component props | `interface ButtonProps {}` |
|
|
201
|
+
| Type | Unions, complex types | `type Status = 'on' \| 'off'` |
|
|
202
|
+
| Generic | Reusable components | `<DataTable<T>>` |
|
|
203
|
+
|
|
204
|
+
### Essential Types
|
|
205
|
+
|
|
206
|
+
| Need | Type |
|
|
207
|
+
| ------------- | ------------------------ |
|
|
208
|
+
| Children | `ReactNode` |
|
|
209
|
+
| Event handler | `MouseEventHandler<T>` |
|
|
210
|
+
| Ref | `RefObject<Element>` |
|
|
211
|
+
| Component ref | `ComponentRef<typeof X>` |
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## 8. Testing Priorities
|
|
216
|
+
|
|
217
|
+
### Test Pyramid for React
|
|
218
|
+
|
|
219
|
+
| Level | What to Test | Tools |
|
|
220
|
+
| ----------- | -------------------------------- | ------------------- |
|
|
221
|
+
| Unit | Pure functions, hooks logic | Vitest, Jest |
|
|
222
|
+
| Integration | Component behavior, interactions | React Testing Lib |
|
|
223
|
+
| E2E | Critical user flows | Playwright, Cypress |
|
|
224
|
+
|
|
225
|
+
### Focus Areas
|
|
226
|
+
|
|
227
|
+
- [ ] User-visible behavior (not implementation)
|
|
228
|
+
- [ ] Edge cases (empty states, loading, errors)
|
|
229
|
+
- [ ] Accessibility assertions
|
|
230
|
+
- [ ] Form validation scenarios
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 9. Anti-Patterns
|
|
235
|
+
|
|
236
|
+
| ❌ Don't | ✅ Do | Why |
|
|
237
|
+
| ----------------------------- | ----------------------------- | --------------------------- |
|
|
238
|
+
| `'use client'` everywhere | Server Components by default | Smaller bundle, better SEO |
|
|
239
|
+
| Prop drilling (5+ levels) | Context or state management | Maintainability |
|
|
240
|
+
| Index as key | Stable unique ID | Correct reconciliation |
|
|
241
|
+
| `useEffect` for everything | Server Components for data | Avoid waterfalls |
|
|
242
|
+
| Premature optimization | Profile first | Don't guess, measure |
|
|
243
|
+
| Giant components (500+ lines) | Split into smaller pieces | Testing, reuse, readability |
|
|
244
|
+
| Inline function in render | `useCallback` for stable refs | Performance (when needed) |
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## 10. Next.js App Router Specifics
|
|
249
|
+
|
|
250
|
+
### Server vs Client Decision
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
Does component need...?
|
|
254
|
+
│
|
|
255
|
+
├── useState, useEffect, event handlers → 'use client'
|
|
256
|
+
│
|
|
257
|
+
├── Direct data fetching, no interactivity → Server (default)
|
|
258
|
+
│
|
|
259
|
+
└── Both? → Split: Server parent + Client child
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### File Conventions
|
|
263
|
+
|
|
264
|
+
| File | Purpose |
|
|
265
|
+
| --------------- | ---------------- |
|
|
266
|
+
| `page.tsx` | Route UI |
|
|
267
|
+
| `layout.tsx` | Shared layout |
|
|
268
|
+
| `loading.tsx` | Loading skeleton |
|
|
269
|
+
| `error.tsx` | Error boundary |
|
|
270
|
+
| `not-found.tsx` | 404 page |
|
|
271
|
+
|
|
272
|
+
### Caching Strategy
|
|
273
|
+
|
|
274
|
+
| Layer | Control | Use Case |
|
|
275
|
+
| ---------- | --------------- | ---------------------- |
|
|
276
|
+
| Request | fetch options | Per-request caching |
|
|
277
|
+
| Data | revalidate/tags | ISR, on-demand refresh |
|
|
278
|
+
| Full route | route config | Static pages |
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## 11. Quick Decision Trees
|
|
283
|
+
|
|
284
|
+
### "Which state solution?"
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
Server data? → React Query
|
|
288
|
+
Form state? → React Hook Form
|
|
289
|
+
Global UI? → Zustand
|
|
290
|
+
Theme/Auth? → Context
|
|
291
|
+
Simple local? → useState
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### "Why is it slow?"
|
|
295
|
+
|
|
296
|
+
```
|
|
297
|
+
1. Profile with React DevTools
|
|
298
|
+
2. Check for:
|
|
299
|
+
- Unnecessary re-renders → React.memo, useMemo
|
|
300
|
+
- Large bundles → Dynamic imports, barrel avoidance
|
|
301
|
+
- Network waterfalls → Parallel fetching, suspense
|
|
302
|
+
- Memory leaks → Effect cleanup
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Related Skills
|
|
308
|
+
|
|
309
|
+
| Need | Skill |
|
|
310
|
+
| --------------------- | ----------------------- |
|
|
311
|
+
| Styling | `tailwind-patterns` |
|
|
312
|
+
| Testing | `testing-patterns` |
|
|
313
|
+
| API integration | `api-patterns` |
|
|
314
|
+
| TypeScript advanced | `typescript-patterns` |
|
|
315
|
+
| Performance deep-dive | `performance-profiling` |
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
> **Remember:** React 19+ with Server Components changes everything. Start server-side, add client only when needed.
|