@mr.dj2u/knowledge 0.1.6 → 0.1.8

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 (74) hide show
  1. package/dist/content/checklists/push-merge-loop.md +17 -17
  2. package/dist/content/checklists/unified-agent-bundle-validation.md +9 -9
  3. package/dist/content/examples/push-merge-loop.md +14 -14
  4. package/dist/content/examples/unified-agent-bundle-bootstrap.md +8 -8
  5. package/dist/content/guides/animation-performance.md +31 -1
  6. package/dist/content/guides/post-create-onboarding.md +140 -140
  7. package/dist/content/patterns/animation/animation-motion-selection.md +155 -0
  8. package/dist/content/patterns/api/api-routes.md +313 -313
  9. package/dist/content/patterns/api/error-handling.md +310 -310
  10. package/dist/content/patterns/database/drizzle-schema.md +279 -279
  11. package/dist/content/patterns/database/migrations.md +364 -364
  12. package/dist/content/patterns/database/query-organization.md +536 -536
  13. package/dist/content/patterns/database/relations.md +449 -449
  14. package/dist/content/patterns/deployment/build-configuration.md +440 -440
  15. package/dist/content/patterns/deployment/ci-cd-patterns.md +447 -447
  16. package/dist/content/patterns/deployment/environment-config.md +379 -379
  17. package/dist/content/patterns/deployment/hosting-setup.md +424 -424
  18. package/dist/content/patterns/project/configuration-patterns.md +459 -459
  19. package/dist/content/patterns/project/documentation-org.md +506 -506
  20. package/dist/content/patterns/project/folder-structure.md +397 -397
  21. package/dist/content/patterns/project/library-exports.md +464 -464
  22. package/dist/content/patterns/project/monorepo-structure.md +500 -500
  23. package/dist/content/patterns/routing/dynamic-routes.md +220 -220
  24. package/dist/content/patterns/routing/file-based-routing.md +185 -185
  25. package/dist/content/patterns/routing/route-groups.md +428 -428
  26. package/dist/content/patterns/state/persistence-middleware.md +520 -520
  27. package/dist/content/patterns/state/selector-hooks.md +537 -537
  28. package/dist/content/patterns/state/store-organization.md +538 -538
  29. package/dist/content/patterns/state/zustand-patterns.md +347 -347
  30. package/dist/content/patterns/styling/component-styling.md +467 -467
  31. package/dist/content/patterns/styling/responsive-patterns.md +397 -397
  32. package/dist/content/patterns/styling/theme-configuration.md +425 -425
  33. package/dist/content/patterns/styling/uniwind-setup.md +411 -411
  34. package/dist/content/prompts/continue-development.md +35 -35
  35. package/dist/content/prompts/fix-seo.md +29 -29
  36. package/dist/content/prompts/onboard-new-expo-app.md +11 -11
  37. package/dist/content/prompts/prepare-deploy.md +29 -29
  38. package/dist/content/prompts/project-research-plan.md +29 -29
  39. package/dist/content/prompts/push-merge-loop.md +25 -25
  40. package/dist/content/prompts/review-expo-project.md +29 -29
  41. package/dist/content/prompts/review-motion.md +58 -0
  42. package/dist/content/prompts/run-doctor.md +38 -38
  43. package/dist/content/prompts/wrap-up.md +67 -67
  44. package/dist/content/reference/create-expo-stack-uniwind.md +29 -29
  45. package/dist/content/reference/mcp-sdk-transport.md +30 -30
  46. package/dist/content/reference/reference-repo-evacuation.md +31 -31
  47. package/dist/content/resource-index.json +3 -0
  48. package/dist/content/skills/animation-motion.md +68 -0
  49. package/dist/content/skills/api-routes.md +33 -33
  50. package/dist/content/skills/continue-development.md +32 -32
  51. package/dist/content/skills/debugging.md +32 -32
  52. package/dist/content/skills/deployment.md +32 -32
  53. package/dist/content/skills/dev-server-management.md +32 -32
  54. package/dist/content/skills/env-vars.md +32 -32
  55. package/dist/content/skills/expo-router-architecture.md +33 -33
  56. package/dist/content/skills/expo-ssr-safety.md +32 -32
  57. package/dist/content/skills/plugin-creation.md +41 -41
  58. package/dist/content/skills/production-server-patterns.md +31 -31
  59. package/dist/content/skills/project-onboarding.md +31 -31
  60. package/dist/content/skills/research-plan-intake.md +32 -32
  61. package/dist/content/skills/seo-metadata.md +31 -31
  62. package/dist/content/skills/super-stack-startup.md +34 -34
  63. package/dist/content/skills/uniwind-theming.md +32 -32
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +27 -1
  66. package/dist/index.js.map +1 -1
  67. package/dist/patterns/index.d.ts +9 -1
  68. package/dist/patterns/index.d.ts.map +1 -1
  69. package/dist/patterns/index.js +17 -0
  70. package/dist/patterns/index.js.map +1 -1
  71. package/dist/prompts/index.d.ts.map +1 -1
  72. package/dist/prompts/index.js +17 -0
  73. package/dist/prompts/index.js.map +1 -1
  74. package/package.json +6 -1
@@ -1,429 +1,429 @@
1
- # Route Groups Pattern
2
-
3
- ## Description
4
-
5
- Route groups use parentheses `(groupName)` to organize routes without adding URL segments. Groups enable shared layouts, nested navigation stacks, and logical route organization within Expo Router's file-based routing system.
6
-
7
- ## When to Use
8
-
9
- **Use route groups** for:
10
- - ✅ Shared layout wrapping multiple routes without URL changes
11
- - ✅ Tab navigation stacks (e.g., `(tabs)/home`, `(tabs)/explore`)
12
- - ✅ Authentication flow separation (`(auth)` vs main app)
13
- - ✅ Nested drawer navigation within groups
14
- - ✅ Organizing related features without URL hierarchy
15
-
16
- ## Code Example
17
-
18
- ### Basic Route Group with Shared Layout
19
-
20
- ```typescript
21
- // File: src/app/(drawer)/_layout.tsx
22
- import { Drawer } from 'expo-router/drawer';
23
- import { GestureHandlerRootView } from 'react-native-gesture-handler';
24
-
25
- export default function DrawerLayout() {
26
- return (
27
- <GestureHandlerRootView style={{ flex: 1 }}>
28
- <Drawer
29
- screenOptions={{
30
- headerShown: true,
31
- drawerType: 'slide',
32
- }}
33
- >
34
- <Drawer.Screen
35
- name="(tabs)"
36
- options={{
37
- title: 'Home',
38
- drawerIcon: ({ color }) => <HomeIcon color={color} />,
39
- }}
40
- />
41
- <Drawer.Screen
42
- name="settings"
43
- options={{
44
- title: 'Settings',
45
- drawerIcon: ({ color }) => <SettingsIcon color={color} />,
46
- }}
47
- />
48
- </Drawer>
49
- </GestureHandlerRootView>
50
- );
51
- }
52
- ```
53
-
54
- ```typescript
55
- // File: src/app/(drawer)/(tabs)/_layout.tsx
56
- import { Tabs } from 'expo-router';
57
- import { HomeIcon, ExploreIcon, ProfileIcon } from '@/components/Icons';
58
-
59
- export default function TabLayout() {
60
- return (
61
- <Tabs
62
- screenOptions={{
63
- headerShown: false,
64
- tabBarActiveTintColor: '#007AFF',
65
- }}
66
- >
67
- <Tabs.Screen
68
- name="index"
69
- options={{
70
- title: 'Home',
71
- tabBarIcon: ({ color }) => <HomeIcon color={color} />,
72
- }}
73
- />
74
- <Tabs.Screen
75
- name="explore"
76
- options={{
77
- title: 'Explore',
78
- tabBarIcon: ({ color }) => <ExploreIcon color={color} />,
79
- }}
80
- />
81
- <Tabs.Screen
82
- name="profile"
83
- options={{
84
- title: 'Profile',
85
- tabBarIcon: ({ color }) => <ProfileIcon color={color} />,
86
- }}
87
- />
88
- </Tabs>
89
- );
90
- }
91
- ```
92
-
93
- ```typescript
94
- // File: src/app/(drawer)/(tabs)/index.tsx
95
- import { View, Text } from 'react-native';
96
-
97
- export default function HomeScreen() {
98
- return (
99
- <View className="flex-1 items-center justify-center">
100
- <Text>Home Tab</Text>
101
- </View>
102
- );
103
- }
104
- // Route: /home (no "(tabs)" in URL)
105
- ```
106
-
107
- ### Multiple Nested Groups
108
-
109
- ```
110
- src/app/
111
- ├── _layout.tsx (root: Stack)
112
- ├── (drawer)/ (drawer group, no URL)
113
- │ ├── _layout.tsx (Drawer layout)
114
- │ ├── (tabs)/ (tabs group within drawer, no URL)
115
- │ │ ├── _layout.tsx (Tabs layout)
116
- │ │ ├── index.tsx → /
117
- │ │ ├── explore.tsx → /explore
118
- │ │ └── profile.tsx → /profile
119
- │ └── settings.tsx → /settings
120
- ├── (auth)/ (auth group, no URL)
121
- │ ├── _layout.tsx (Stack layout for auth flow)
122
- │ ├── sign-in.tsx → /sign-in
123
- │ └── sign-up.tsx → /sign-up
124
- └── +not-found.tsx (catch-all 404)
125
-
126
- // Key insight: Route groups "(drawer)" and "(tabs)" don't appear in URLs
127
- // Routes map: / (home), /explore, /profile, /settings, /sign-in, /sign-up
128
- ```
129
-
130
- ### Authentication Flow with Route Groups
131
-
132
- ```typescript
133
- // File: src/app/_layout.tsx (Root Layout)
134
- import { Stack } from 'expo-router';
135
- import { useAuthStore } from '@/store/authStore';
136
-
137
- export default function RootLayout() {
138
- const { isLoggedIn, loading } = useAuthStore();
139
-
140
- if (loading) {
141
- return <LoadingScreen />;
142
- }
143
-
144
- return (
145
- <Stack
146
- screenOptions={{
147
- headerShown: false,
148
- animationEnabled: true,
149
- }}
150
- >
151
- {isLoggedIn ? (
152
- // Main app routes (drawer + tabs)
153
- <Stack.Screen name="(drawer)" />
154
- ) : (
155
- // Auth routes (sign-in, sign-up)
156
- <Stack.Screen
157
- name="(auth)"
158
- options={{
159
- animationEnabled: false,
160
- }}
161
- />
162
- )}
163
- </Stack>
164
- );
165
- }
166
- ```
167
-
168
- ```typescript
169
- // File: src/app/(auth)/_layout.tsx
170
- import { Stack } from 'expo-router';
171
-
172
- export default function AuthLayout() {
173
- return (
174
- <Stack
175
- screenOptions={{
176
- headerShown: false,
177
- animationEnabled: true,
178
- }}
179
- >
180
- <Stack.Screen name="sign-in" />
181
- <Stack.Screen name="sign-up" />
182
- </Stack>
183
- );
184
- }
185
- ```
186
-
187
- ```typescript
188
- // File: src/app/(auth)/sign-in.tsx
189
- import { View, Text, Pressable } from 'react-native';
190
- import { router } from 'expo-router';
191
-
192
- export default function SignInScreen() {
193
- const handleSignIn = async () => {
194
- // Authentication logic
195
- await authenticate();
196
- // Replace entire stack with main app
197
- router.replace('/(drawer)/(tabs)/');
198
- };
199
-
200
- return (
201
- <View className="flex-1 justify-center items-center">
202
- <Text>Sign In</Text>
203
- <Pressable onPress={handleSignIn}>
204
- <Text>Login</Text>
205
- </Pressable>
206
- </View>
207
- );
208
- }
209
- // Route: /sign-in (not /(auth)/sign-in)
210
- ```
211
-
212
- ### Feature-Specific Groups
213
-
214
- ```
215
- src/app/
216
- ├── (drawer)/
217
- │ ├── _layout.tsx
218
- │ ├── (tabs)/
219
- │ │ ├── _layout.tsx
220
- │ │ ├── index.tsx
221
- │ │ └── explore.tsx
222
- │ └── (guides)/ (guides feature group)
223
- │ ├── _layout.tsx (guides layout/header)
224
- │ ├── index.tsx → /guides
225
- │ ├── [id].tsx → /guides/[id]
226
- │ └── search.tsx → /guides/search
227
- └── (modal)/ (modal overlay group)
228
- ├── _layout.tsx (modal presentation)
229
- ├── settings-modal.tsx → /settings-modal
230
- └── share-modal.tsx → /share-modal
231
-
232
- // Routes: /guides, /guides/123, /guides/search, /settings-modal, /share-modal
233
- ```
234
-
235
- ```typescript
236
- // File: src/app/(drawer)/(guides)/_layout.tsx
237
- import { Stack } from 'expo-router';
238
-
239
- export default function GuidesLayout() {
240
- return (
241
- <Stack
242
- screenOptions={{
243
- headerShown: true,
244
- headerTitle: 'Guides',
245
- headerBackVisible: true,
246
- }}
247
- >
248
- <Stack.Screen name="index" />
249
- <Stack.Screen name="[id]" />
250
- <Stack.Screen name="search" />
251
- </Stack>
252
- );
253
- }
254
- ```
255
-
256
- ### Modal Presentation with Route Groups
257
-
258
- ```typescript
259
- // File: src/app/_layout.tsx
260
- import { Stack } from 'expo-router';
261
-
262
- export default function RootLayout() {
263
- return (
264
- <Stack>
265
- {/* Main app */}
266
- <Stack.Screen name="(drawer)" />
267
-
268
- {/* Modal stack (presented on top) */}
269
- <Stack.Screen
270
- name="(modal)"
271
- options={{
272
- presentation: 'modal',
273
- headerShown: false,
274
- animationEnabled: true,
275
- }}
276
- />
277
- </Stack>
278
- );
279
- }
280
- ```
281
-
282
- ```typescript
283
- // File: src/app/(modal)/_layout.tsx
284
- import { Stack } from 'expo-router';
285
-
286
- export default function ModalLayout() {
287
- return (
288
- <Stack
289
- screenOptions={{
290
- presentation: 'modal',
291
- }}
292
- >
293
- <Stack.Screen name="settings-modal" />
294
- <Stack.Screen name="share-modal" />
295
- </Stack>
296
- );
297
- }
298
- ```
299
-
300
- ```typescript
301
- // File: src/app/(modal)/settings-modal.tsx
302
- import { View, Text, Pressable } from 'react-native';
303
- import { router } from 'expo-router';
304
-
305
- export default function SettingsModal() {
306
- return (
307
- <View className="flex-1 bg-white rounded-t-2xl p-4">
308
- <View className="flex-row justify-between items-center mb-4">
309
- <Text className="text-xl font-bold">Settings</Text>
310
- <Pressable onPress={() => router.back()}>
311
- <Text className="text-lg">✕</Text>
312
- </Pressable>
313
- </View>
314
-
315
- {/* Settings content */}
316
- </View>
317
- );
318
- }
319
- // Route: /settings-modal (presented as modal)
320
- // Navigate: router.push('/settings-modal')
321
- ```
322
-
323
- ## Route Group Naming Conventions
324
-
325
- | Pattern | Purpose | URL Impact |
326
- |---------|---------|-----------|
327
- | `(tabs)` | Tab navigation group | No URL segment |
328
- | `(drawer)` | Drawer navigation group | No URL segment |
329
- | `(auth)` | Authentication flow | No URL segment |
330
- | `(modal)` | Modal overlays | No URL segment |
331
- | `(feature-name)` | Feature-specific routes | No URL segment |
332
-
333
- ## Navigation Patterns
334
-
335
- ### Navigate Between Groups
336
-
337
- ```typescript
338
- import { router } from 'expo-router';
339
-
340
- // Navigate to route in different group
341
- router.push('/'); // Home in (tabs)
342
- router.push('/guides'); // Guides in (guides)
343
- router.push('/settings-modal'); // Modal in (modal)
344
-
345
- // Navigate with params
346
- router.push('/guides/123');
347
- router.push({
348
- pathname: '/guides/[id]',
349
- params: { id: '123' },
350
- });
351
-
352
- // Replace (clear stack)
353
- router.replace('/(drawer)/(tabs)/');
354
- router.replace('/(auth)/sign-in');
355
- ```
356
-
357
- ## Best Practices
358
-
359
- ### ✅ DO
360
-
361
- 1. **Use groups to organize related routes**
362
- ```
363
- (drawer)/ - Main app navigation
364
- (tabs)/ - Tab routes
365
- (auth)/ - Auth flow
366
- (guides)/ - Feature routes
367
- ```
368
-
369
- 2. **Keep _layout.tsx files focused** on navigation setup
370
- ```typescript
371
- export default function GuideLayout() {
372
- return (
373
- <Stack screenOptions={{ /* navigation options */ }}>
374
- <Stack.Screen name="index" />
375
- <Stack.Screen name="[id]" />
376
- </Stack>
377
- );
378
- }
379
- ```
380
-
381
- 3. **Use router.replace()** when changing auth states
382
- ```typescript
383
- // After login, replace auth stack with main app
384
- router.replace('/(drawer)/(tabs)/');
385
-
386
- // After logout, replace main app with auth
387
- router.replace('/(auth)/sign-in');
388
- ```
389
-
390
- ### ❌ DON'T
391
-
392
- 1. **Don't nest groups excessively**
393
- ```typescript
394
- // ❌ TOO DEEP
395
- (app)/(main)/(features)/(guides)/index.tsx
396
-
397
- // ✅ REASONABLE
398
- (drawer)/(guides)/index.tsx
399
- ```
400
-
401
- 2. **Don't duplicate layout logic**
402
- ```typescript
403
- // ❌ DUPLICATED
404
- // (drawer)/_layout.tsx - defines Drawer
405
- // (drawer)/(tabs)/_layout.tsx - defines Drawer again
406
-
407
- // ✅ COMPOSED
408
- // (drawer)/_layout.tsx - wraps (tabs) group
409
- // (drawer)/(tabs)/_layout.tsx - defines Tabs within drawer
410
- ```
411
-
412
- 3. **Don't forget router.replace()** for auth transitions
413
- ```typescript
414
- // ❌ LEAVES BACK BUTTON
415
- router.push('/(drawer)/(tabs)/');
416
-
417
- // ✅ CLEAR STACK
418
- router.replace('/(drawer)/(tabs)/');
419
- ```
420
-
421
- ## Related Patterns
422
-
423
- - [File-Based Routing](./file-based-routing.md) — Routing fundamentals
424
- - [Dynamic Routes](./dynamic-routes.md) — Dynamic segments
425
-
426
- ---
427
-
428
- *Pattern extracted from production repositories: core-monorepo, PokePages, DJsPortfolio*
1
+ # Route Groups Pattern
2
+
3
+ ## Description
4
+
5
+ Route groups use parentheses `(groupName)` to organize routes without adding URL segments. Groups enable shared layouts, nested navigation stacks, and logical route organization within Expo Router's file-based routing system.
6
+
7
+ ## When to Use
8
+
9
+ **Use route groups** for:
10
+ - ✅ Shared layout wrapping multiple routes without URL changes
11
+ - ✅ Tab navigation stacks (e.g., `(tabs)/home`, `(tabs)/explore`)
12
+ - ✅ Authentication flow separation (`(auth)` vs main app)
13
+ - ✅ Nested drawer navigation within groups
14
+ - ✅ Organizing related features without URL hierarchy
15
+
16
+ ## Code Example
17
+
18
+ ### Basic Route Group with Shared Layout
19
+
20
+ ```typescript
21
+ // File: src/app/(drawer)/_layout.tsx
22
+ import { Drawer } from 'expo-router/drawer';
23
+ import { GestureHandlerRootView } from 'react-native-gesture-handler';
24
+
25
+ export default function DrawerLayout() {
26
+ return (
27
+ <GestureHandlerRootView style={{ flex: 1 }}>
28
+ <Drawer
29
+ screenOptions={{
30
+ headerShown: true,
31
+ drawerType: 'slide',
32
+ }}
33
+ >
34
+ <Drawer.Screen
35
+ name="(tabs)"
36
+ options={{
37
+ title: 'Home',
38
+ drawerIcon: ({ color }) => <HomeIcon color={color} />,
39
+ }}
40
+ />
41
+ <Drawer.Screen
42
+ name="settings"
43
+ options={{
44
+ title: 'Settings',
45
+ drawerIcon: ({ color }) => <SettingsIcon color={color} />,
46
+ }}
47
+ />
48
+ </Drawer>
49
+ </GestureHandlerRootView>
50
+ );
51
+ }
52
+ ```
53
+
54
+ ```typescript
55
+ // File: src/app/(drawer)/(tabs)/_layout.tsx
56
+ import { Tabs } from 'expo-router';
57
+ import { HomeIcon, ExploreIcon, ProfileIcon } from '@/components/Icons';
58
+
59
+ export default function TabLayout() {
60
+ return (
61
+ <Tabs
62
+ screenOptions={{
63
+ headerShown: false,
64
+ tabBarActiveTintColor: '#007AFF',
65
+ }}
66
+ >
67
+ <Tabs.Screen
68
+ name="index"
69
+ options={{
70
+ title: 'Home',
71
+ tabBarIcon: ({ color }) => <HomeIcon color={color} />,
72
+ }}
73
+ />
74
+ <Tabs.Screen
75
+ name="explore"
76
+ options={{
77
+ title: 'Explore',
78
+ tabBarIcon: ({ color }) => <ExploreIcon color={color} />,
79
+ }}
80
+ />
81
+ <Tabs.Screen
82
+ name="profile"
83
+ options={{
84
+ title: 'Profile',
85
+ tabBarIcon: ({ color }) => <ProfileIcon color={color} />,
86
+ }}
87
+ />
88
+ </Tabs>
89
+ );
90
+ }
91
+ ```
92
+
93
+ ```typescript
94
+ // File: src/app/(drawer)/(tabs)/index.tsx
95
+ import { View, Text } from 'react-native';
96
+
97
+ export default function HomeScreen() {
98
+ return (
99
+ <View className="flex-1 items-center justify-center">
100
+ <Text>Home Tab</Text>
101
+ </View>
102
+ );
103
+ }
104
+ // Route: /home (no "(tabs)" in URL)
105
+ ```
106
+
107
+ ### Multiple Nested Groups
108
+
109
+ ```
110
+ src/app/
111
+ ├── _layout.tsx (root: Stack)
112
+ ├── (drawer)/ (drawer group, no URL)
113
+ │ ├── _layout.tsx (Drawer layout)
114
+ │ ├── (tabs)/ (tabs group within drawer, no URL)
115
+ │ │ ├── _layout.tsx (Tabs layout)
116
+ │ │ ├── index.tsx → /
117
+ │ │ ├── explore.tsx → /explore
118
+ │ │ └── profile.tsx → /profile
119
+ │ └── settings.tsx → /settings
120
+ ├── (auth)/ (auth group, no URL)
121
+ │ ├── _layout.tsx (Stack layout for auth flow)
122
+ │ ├── sign-in.tsx → /sign-in
123
+ │ └── sign-up.tsx → /sign-up
124
+ └── +not-found.tsx (catch-all 404)
125
+
126
+ // Key insight: Route groups "(drawer)" and "(tabs)" don't appear in URLs
127
+ // Routes map: / (home), /explore, /profile, /settings, /sign-in, /sign-up
128
+ ```
129
+
130
+ ### Authentication Flow with Route Groups
131
+
132
+ ```typescript
133
+ // File: src/app/_layout.tsx (Root Layout)
134
+ import { Stack } from 'expo-router';
135
+ import { useAuthStore } from '@/store/authStore';
136
+
137
+ export default function RootLayout() {
138
+ const { isLoggedIn, loading } = useAuthStore();
139
+
140
+ if (loading) {
141
+ return <LoadingScreen />;
142
+ }
143
+
144
+ return (
145
+ <Stack
146
+ screenOptions={{
147
+ headerShown: false,
148
+ animationEnabled: true,
149
+ }}
150
+ >
151
+ {isLoggedIn ? (
152
+ // Main app routes (drawer + tabs)
153
+ <Stack.Screen name="(drawer)" />
154
+ ) : (
155
+ // Auth routes (sign-in, sign-up)
156
+ <Stack.Screen
157
+ name="(auth)"
158
+ options={{
159
+ animationEnabled: false,
160
+ }}
161
+ />
162
+ )}
163
+ </Stack>
164
+ );
165
+ }
166
+ ```
167
+
168
+ ```typescript
169
+ // File: src/app/(auth)/_layout.tsx
170
+ import { Stack } from 'expo-router';
171
+
172
+ export default function AuthLayout() {
173
+ return (
174
+ <Stack
175
+ screenOptions={{
176
+ headerShown: false,
177
+ animationEnabled: true,
178
+ }}
179
+ >
180
+ <Stack.Screen name="sign-in" />
181
+ <Stack.Screen name="sign-up" />
182
+ </Stack>
183
+ );
184
+ }
185
+ ```
186
+
187
+ ```typescript
188
+ // File: src/app/(auth)/sign-in.tsx
189
+ import { View, Text, Pressable } from 'react-native';
190
+ import { router } from 'expo-router';
191
+
192
+ export default function SignInScreen() {
193
+ const handleSignIn = async () => {
194
+ // Authentication logic
195
+ await authenticate();
196
+ // Replace entire stack with main app
197
+ router.replace('/(drawer)/(tabs)/');
198
+ };
199
+
200
+ return (
201
+ <View className="flex-1 justify-center items-center">
202
+ <Text>Sign In</Text>
203
+ <Pressable onPress={handleSignIn}>
204
+ <Text>Login</Text>
205
+ </Pressable>
206
+ </View>
207
+ );
208
+ }
209
+ // Route: /sign-in (not /(auth)/sign-in)
210
+ ```
211
+
212
+ ### Feature-Specific Groups
213
+
214
+ ```
215
+ src/app/
216
+ ├── (drawer)/
217
+ │ ├── _layout.tsx
218
+ │ ├── (tabs)/
219
+ │ │ ├── _layout.tsx
220
+ │ │ ├── index.tsx
221
+ │ │ └── explore.tsx
222
+ │ └── (guides)/ (guides feature group)
223
+ │ ├── _layout.tsx (guides layout/header)
224
+ │ ├── index.tsx → /guides
225
+ │ ├── [id].tsx → /guides/[id]
226
+ │ └── search.tsx → /guides/search
227
+ └── (modal)/ (modal overlay group)
228
+ ├── _layout.tsx (modal presentation)
229
+ ├── settings-modal.tsx → /settings-modal
230
+ └── share-modal.tsx → /share-modal
231
+
232
+ // Routes: /guides, /guides/123, /guides/search, /settings-modal, /share-modal
233
+ ```
234
+
235
+ ```typescript
236
+ // File: src/app/(drawer)/(guides)/_layout.tsx
237
+ import { Stack } from 'expo-router';
238
+
239
+ export default function GuidesLayout() {
240
+ return (
241
+ <Stack
242
+ screenOptions={{
243
+ headerShown: true,
244
+ headerTitle: 'Guides',
245
+ headerBackVisible: true,
246
+ }}
247
+ >
248
+ <Stack.Screen name="index" />
249
+ <Stack.Screen name="[id]" />
250
+ <Stack.Screen name="search" />
251
+ </Stack>
252
+ );
253
+ }
254
+ ```
255
+
256
+ ### Modal Presentation with Route Groups
257
+
258
+ ```typescript
259
+ // File: src/app/_layout.tsx
260
+ import { Stack } from 'expo-router';
261
+
262
+ export default function RootLayout() {
263
+ return (
264
+ <Stack>
265
+ {/* Main app */}
266
+ <Stack.Screen name="(drawer)" />
267
+
268
+ {/* Modal stack (presented on top) */}
269
+ <Stack.Screen
270
+ name="(modal)"
271
+ options={{
272
+ presentation: 'modal',
273
+ headerShown: false,
274
+ animationEnabled: true,
275
+ }}
276
+ />
277
+ </Stack>
278
+ );
279
+ }
280
+ ```
281
+
282
+ ```typescript
283
+ // File: src/app/(modal)/_layout.tsx
284
+ import { Stack } from 'expo-router';
285
+
286
+ export default function ModalLayout() {
287
+ return (
288
+ <Stack
289
+ screenOptions={{
290
+ presentation: 'modal',
291
+ }}
292
+ >
293
+ <Stack.Screen name="settings-modal" />
294
+ <Stack.Screen name="share-modal" />
295
+ </Stack>
296
+ );
297
+ }
298
+ ```
299
+
300
+ ```typescript
301
+ // File: src/app/(modal)/settings-modal.tsx
302
+ import { View, Text, Pressable } from 'react-native';
303
+ import { router } from 'expo-router';
304
+
305
+ export default function SettingsModal() {
306
+ return (
307
+ <View className="flex-1 bg-white rounded-t-2xl p-4">
308
+ <View className="flex-row justify-between items-center mb-4">
309
+ <Text className="text-xl font-bold">Settings</Text>
310
+ <Pressable onPress={() => router.back()}>
311
+ <Text className="text-lg">✕</Text>
312
+ </Pressable>
313
+ </View>
314
+
315
+ {/* Settings content */}
316
+ </View>
317
+ );
318
+ }
319
+ // Route: /settings-modal (presented as modal)
320
+ // Navigate: router.push('/settings-modal')
321
+ ```
322
+
323
+ ## Route Group Naming Conventions
324
+
325
+ | Pattern | Purpose | URL Impact |
326
+ |---------|---------|-----------|
327
+ | `(tabs)` | Tab navigation group | No URL segment |
328
+ | `(drawer)` | Drawer navigation group | No URL segment |
329
+ | `(auth)` | Authentication flow | No URL segment |
330
+ | `(modal)` | Modal overlays | No URL segment |
331
+ | `(feature-name)` | Feature-specific routes | No URL segment |
332
+
333
+ ## Navigation Patterns
334
+
335
+ ### Navigate Between Groups
336
+
337
+ ```typescript
338
+ import { router } from 'expo-router';
339
+
340
+ // Navigate to route in different group
341
+ router.push('/'); // Home in (tabs)
342
+ router.push('/guides'); // Guides in (guides)
343
+ router.push('/settings-modal'); // Modal in (modal)
344
+
345
+ // Navigate with params
346
+ router.push('/guides/123');
347
+ router.push({
348
+ pathname: '/guides/[id]',
349
+ params: { id: '123' },
350
+ });
351
+
352
+ // Replace (clear stack)
353
+ router.replace('/(drawer)/(tabs)/');
354
+ router.replace('/(auth)/sign-in');
355
+ ```
356
+
357
+ ## Best Practices
358
+
359
+ ### ✅ DO
360
+
361
+ 1. **Use groups to organize related routes**
362
+ ```
363
+ (drawer)/ - Main app navigation
364
+ (tabs)/ - Tab routes
365
+ (auth)/ - Auth flow
366
+ (guides)/ - Feature routes
367
+ ```
368
+
369
+ 2. **Keep _layout.tsx files focused** on navigation setup
370
+ ```typescript
371
+ export default function GuideLayout() {
372
+ return (
373
+ <Stack screenOptions={{ /* navigation options */ }}>
374
+ <Stack.Screen name="index" />
375
+ <Stack.Screen name="[id]" />
376
+ </Stack>
377
+ );
378
+ }
379
+ ```
380
+
381
+ 3. **Use router.replace()** when changing auth states
382
+ ```typescript
383
+ // After login, replace auth stack with main app
384
+ router.replace('/(drawer)/(tabs)/');
385
+
386
+ // After logout, replace main app with auth
387
+ router.replace('/(auth)/sign-in');
388
+ ```
389
+
390
+ ### ❌ DON'T
391
+
392
+ 1. **Don't nest groups excessively**
393
+ ```typescript
394
+ // ❌ TOO DEEP
395
+ (app)/(main)/(features)/(guides)/index.tsx
396
+
397
+ // ✅ REASONABLE
398
+ (drawer)/(guides)/index.tsx
399
+ ```
400
+
401
+ 2. **Don't duplicate layout logic**
402
+ ```typescript
403
+ // ❌ DUPLICATED
404
+ // (drawer)/_layout.tsx - defines Drawer
405
+ // (drawer)/(tabs)/_layout.tsx - defines Drawer again
406
+
407
+ // ✅ COMPOSED
408
+ // (drawer)/_layout.tsx - wraps (tabs) group
409
+ // (drawer)/(tabs)/_layout.tsx - defines Tabs within drawer
410
+ ```
411
+
412
+ 3. **Don't forget router.replace()** for auth transitions
413
+ ```typescript
414
+ // ❌ LEAVES BACK BUTTON
415
+ router.push('/(drawer)/(tabs)/');
416
+
417
+ // ✅ CLEAR STACK
418
+ router.replace('/(drawer)/(tabs)/');
419
+ ```
420
+
421
+ ## Related Patterns
422
+
423
+ - [File-Based Routing](./file-based-routing.md) — Routing fundamentals
424
+ - [Dynamic Routes](./dynamic-routes.md) — Dynamic segments
425
+
426
+ ---
427
+
428
+ *Pattern extracted from production repositories: core-monorepo, PokePages, DJsPortfolio*
429
429
  *Files: src/app/ directory structures from Expo Router projects*