@ranimontagna/agent-toolkit 0.1.5 → 0.1.7

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 (60) hide show
  1. package/README.md +68 -14
  2. package/package.json +1 -1
  3. package/skills/backend/go/golang-patterns/LICENSE +21 -0
  4. package/skills/backend/go/golang-patterns/NOTICE.md +10 -0
  5. package/skills/backend/go/golang-patterns/SKILL.md +674 -0
  6. package/skills/backend/go/golang-testing/LICENSE +21 -0
  7. package/skills/backend/go/golang-testing/NOTICE.md +10 -0
  8. package/skills/backend/go/golang-testing/SKILL.md +329 -0
  9. package/skills/backend/java/java-coding-standards/LICENSE +21 -0
  10. package/skills/backend/java/java-coding-standards/NOTICE.md +10 -0
  11. package/skills/backend/java/java-coding-standards/SKILL.md +383 -0
  12. package/skills/backend/java/java-junit/LICENSE +21 -0
  13. package/skills/backend/java/java-junit/NOTICE.md +10 -0
  14. package/skills/backend/java/java-junit/SKILL.md +64 -0
  15. package/skills/frontend/react/react-patterns/LICENSE +21 -0
  16. package/skills/frontend/react/react-patterns/NOTICE.md +11 -0
  17. package/skills/frontend/react/react-patterns/SKILL.md +341 -0
  18. package/skills/frontend/react/react-patterns/rules/react/LICENSE +21 -0
  19. package/skills/frontend/react/react-patterns/rules/react/NOTICE.md +11 -0
  20. package/skills/frontend/react/react-patterns/rules/react/coding-style.md +109 -0
  21. package/skills/frontend/react/react-patterns/rules/react/hooks.md +187 -0
  22. package/skills/frontend/react/react-patterns/rules/react/patterns.md +194 -0
  23. package/skills/frontend/react/react-patterns/rules/react/security.md +180 -0
  24. package/skills/frontend/react/react-patterns/rules/react/testing.md +208 -0
  25. package/skills/frontend/react/react-performance/LICENSE +21 -0
  26. package/skills/frontend/react/react-performance/NOTICE.md +11 -0
  27. package/skills/frontend/react/react-performance/SKILL.md +574 -0
  28. package/skills/frontend/react/react-performance/rules/react/LICENSE +21 -0
  29. package/skills/frontend/react/react-performance/rules/react/NOTICE.md +11 -0
  30. package/skills/frontend/react/react-performance/rules/react/coding-style.md +109 -0
  31. package/skills/frontend/react/react-performance/rules/react/hooks.md +187 -0
  32. package/skills/frontend/react/react-performance/rules/react/patterns.md +194 -0
  33. package/skills/frontend/react/react-performance/rules/react/security.md +180 -0
  34. package/skills/frontend/react/react-performance/rules/react/testing.md +208 -0
  35. package/skills/frontend/react/react-testing/LICENSE +21 -0
  36. package/skills/frontend/react/react-testing/NOTICE.md +11 -0
  37. package/skills/frontend/react/react-testing/SKILL.md +423 -0
  38. package/skills/frontend/react/react-testing/rules/react/LICENSE +21 -0
  39. package/skills/frontend/react/react-testing/rules/react/NOTICE.md +11 -0
  40. package/skills/frontend/react/react-testing/rules/react/coding-style.md +109 -0
  41. package/skills/frontend/react/react-testing/rules/react/hooks.md +187 -0
  42. package/skills/frontend/react/react-testing/rules/react/patterns.md +194 -0
  43. package/skills/frontend/react/react-testing/rules/react/security.md +180 -0
  44. package/skills/frontend/react/react-testing/rules/react/testing.md +208 -0
  45. package/skills/frontend/react-native/react-native-expert/LICENSE +21 -0
  46. package/skills/frontend/react-native/react-native-expert/NOTICE.md +11 -0
  47. package/skills/frontend/react-native/react-native-expert/SKILL.md +187 -0
  48. package/skills/frontend/react-native/react-native-expert/references/expo-router.md +187 -0
  49. package/skills/frontend/react-native/react-native-expert/references/list-optimization.md +204 -0
  50. package/skills/frontend/react-native/react-native-expert/references/platform-handling.md +188 -0
  51. package/skills/frontend/react-native/react-native-expert/references/project-structure.md +171 -0
  52. package/skills/frontend/react-native/react-native-expert/references/storage-hooks.md +173 -0
  53. package/skills/frontend/react-native/react-native-unistyles-v3/LICENSE +21 -0
  54. package/skills/frontend/react-native/react-native-unistyles-v3/NOTICE.md +11 -0
  55. package/skills/frontend/react-native/react-native-unistyles-v3/SKILL.md +159 -0
  56. package/skills/frontend/react-native/react-native-unistyles-v3/references/api-reference.md +495 -0
  57. package/skills/frontend/react-native/react-native-unistyles-v3/references/common-issues.md +389 -0
  58. package/skills/frontend/react-native/react-native-unistyles-v3/references/setup-guide.md +217 -0
  59. package/skills/frontend/react-native/react-native-unistyles-v3/references/styling-patterns.md +705 -0
  60. package/skills/frontend/react-native/react-native-unistyles-v3/references/third-party-integration.md +318 -0
@@ -0,0 +1,208 @@
1
+ ---
2
+ paths:
3
+ - "**/*.test.tsx"
4
+ - "**/*.test.jsx"
5
+ - "**/*.spec.tsx"
6
+ - "**/*.spec.jsx"
7
+ - "**/__tests__/**/*.ts"
8
+ - "**/__tests__/**/*.tsx"
9
+ ---
10
+ # React Testing
11
+
12
+ > This file extends the upstream `typescript/testing.md` and `common/testing.md` rules with React specific content.
13
+
14
+ ## Library Choice
15
+
16
+ - **React Testing Library (RTL)** — the standard for component testing. Tests behavior through the rendered DOM.
17
+ - **Vitest** — preferred runner for new Vite-based projects. Faster than Jest, native ESM, same API.
18
+ - **Jest** — still the default for Next.js / CRA projects. RTL works identically.
19
+ - **Playwright Component Testing** — when component tests need a real browser engine (animation, layout, complex events)
20
+ - **Cypress Component Testing** — alternative real-browser component runner
21
+
22
+ Pick one component test runner per project — do not mix RTL + Playwright CT in the same repo.
23
+
24
+ ## Core Principle
25
+
26
+ Test what the user sees and does, not implementation details.
27
+
28
+ - Query by accessible role first, then label, then text — fall back to `data-testid` only when nothing else fits
29
+ - Never assert on internal state, props passed to children, or which hooks were called
30
+ - Refactor without breaking tests = the test was testing behavior; that is the goal
31
+
32
+ ## Query Priority
33
+
34
+ RTL exposes queries in three families. Use this priority order top-down:
35
+
36
+ 1. **Accessible to everyone**
37
+ - `getByRole(role, { name })` — primary choice
38
+ - `getByLabelText` — for form inputs
39
+ - `getByPlaceholderText` — when no label is available (and add a label)
40
+ - `getByText` — for non-interactive text
41
+ - `getByDisplayValue` — for form fields with a current value
42
+
43
+ 2. **Semantic queries**
44
+ - `getByAltText` — for images
45
+ - `getByTitle` — last resort, low accessibility value
46
+
47
+ 3. **Test IDs**
48
+ - `getByTestId("some-id")` — escape hatch only, when none of the above work
49
+
50
+ `getBy*` throws when no match. `queryBy*` returns null (use for asserting absence). `findBy*` returns a promise (use for async).
51
+
52
+ ## User Interaction
53
+
54
+ Prefer `userEvent` over `fireEvent`. `userEvent` simulates real browser sequences (focus, keydown, beforeinput, input, keyup) — `fireEvent` dispatches a single synthetic event.
55
+
56
+ ```tsx
57
+ import userEvent from "@testing-library/user-event";
58
+
59
+ test("submits the form", async () => {
60
+ const user = userEvent.setup();
61
+ render(<UserForm onSubmit={handleSubmit} />);
62
+
63
+ await user.type(screen.getByLabelText("Email"), "user@example.com");
64
+ await user.click(screen.getByRole("button", { name: /save/i }));
65
+
66
+ expect(handleSubmit).toHaveBeenCalledWith({ email: "user@example.com" });
67
+ });
68
+ ```
69
+
70
+ - Always `await` `userEvent` calls — they are async
71
+ - Call `userEvent.setup()` once at the top of each test, then reuse the returned `user`
72
+
73
+ ## Async Assertions
74
+
75
+ ```tsx
76
+ // WRONG: synchronous query for async-rendered content
77
+ expect(screen.getByText("Loaded")).toBeInTheDocument(); // throws — not in DOM yet
78
+
79
+ // CORRECT: findBy* (returns a promise, retries)
80
+ expect(await screen.findByText("Loaded")).toBeInTheDocument();
81
+
82
+ // CORRECT: waitFor for non-element assertions
83
+ await waitFor(() => expect(saveSpy).toHaveBeenCalled());
84
+ ```
85
+
86
+ - `findBy*` for async element appearance
87
+ - `waitFor` for async expectations on side effects or other matchers
88
+ - Never `setTimeout` + assertion — flaky
89
+
90
+ ## Network Mocking with MSW
91
+
92
+ Use Mock Service Worker for any test that hits a network boundary. MSW runs at the network layer, so the component, hooks, and fetch library all behave as in production.
93
+
94
+ ```tsx
95
+ // test setup
96
+ import { setupServer } from "msw/node";
97
+ import { http, HttpResponse } from "msw";
98
+
99
+ const server = setupServer(
100
+ http.get("/api/users/:id", ({ params }) =>
101
+ HttpResponse.json({ id: params.id, name: "Alice" }),
102
+ ),
103
+ );
104
+
105
+ beforeAll(() => server.listen());
106
+ afterEach(() => server.resetHandlers());
107
+ afterAll(() => server.close());
108
+ ```
109
+
110
+ Per-test override:
111
+
112
+ ```tsx
113
+ test("renders error on 500", async () => {
114
+ server.use(http.get("/api/users/:id", () => new HttpResponse(null, { status: 500 })));
115
+ render(<UserPage id="1" />);
116
+ expect(await screen.findByText(/something went wrong/i)).toBeInTheDocument();
117
+ });
118
+ ```
119
+
120
+ ## Avoid Snapshot Tests for Components
121
+
122
+ Snapshots of rendered output are brittle, hard to review, and rubber-stamped by reviewers. Use them only for:
123
+
124
+ - Pure data serialization (e.g., a transformer that produces a stable string)
125
+ - Catching unintended regressions in non-visual output
126
+
127
+ For component visual regression, use Playwright / Cypress / Percy screenshots — actual visual diffs, not DOM diffs.
128
+
129
+ ## Test Setup Helpers
130
+
131
+ Wrap providers once:
132
+
133
+ ```tsx
134
+ function renderWithProviders(ui: React.ReactElement) {
135
+ return render(
136
+ <QueryClientProvider client={new QueryClient()}>
137
+ <ThemeProvider theme={lightTheme}>
138
+ <Router>{ui}</Router>
139
+ </ThemeProvider>
140
+ </QueryClientProvider>,
141
+ );
142
+ }
143
+ ```
144
+
145
+ Export from `test-utils.tsx` and use everywhere.
146
+
147
+ ## Custom Hook Testing
148
+
149
+ Use `renderHook` from RTL:
150
+
151
+ ```tsx
152
+ import { renderHook, act } from "@testing-library/react";
153
+
154
+ test("useCounter increments", () => {
155
+ const { result } = renderHook(() => useCounter());
156
+ act(() => result.current.increment());
157
+ expect(result.current.count).toBe(1);
158
+ });
159
+ ```
160
+
161
+ - Always wrap state-changing calls in `act`
162
+ - Always test through the public hook API, not internal implementation
163
+
164
+ ## Accessibility Assertions
165
+
166
+ ```tsx
167
+ import { axe } from "vitest-axe"; // or jest-axe
168
+
169
+ test("UserCard has no a11y violations", async () => {
170
+ const { container } = render(<UserCard user={mockUser} />);
171
+ expect(await axe(container)).toHaveNoViolations();
172
+ });
173
+ ```
174
+
175
+ Run axe assertions in component tests — catches missing labels, ARIA misuse, color contrast (limited).
176
+
177
+ ## When to Reach for Playwright / Cypress
178
+
179
+ Component test with RTL + JSDOM cannot:
180
+
181
+ - Test real layout (flexbox, grid, viewport-dependent rendering)
182
+ - Test scrolling, drag-and-drop, paste from clipboard
183
+ - Test browser-native animation, CSS transitions
184
+ - Test cross-frame interactions (iframes, popups)
185
+
186
+ For those, use Playwright Component Testing or end-to-end Playwright/Cypress runs. See the e2e-testing skill when it is installed.
187
+
188
+ ## Coverage Targets
189
+
190
+ | Layer | Target |
191
+ |---|---|
192
+ | Pure utility functions | ≥90% |
193
+ | Custom hooks | ≥85% |
194
+ | Components (presentational) | ≥80% — behavior, not lines |
195
+ | Container components | ≥70% — golden paths + error states |
196
+ | Pages (E2E covered separately) | Smoke test per route minimum |
197
+
198
+ ## Anti-Patterns
199
+
200
+ - Asserting on `container.querySelector` — bypasses accessibility queries
201
+ - Asserting on number of renders — implementation detail
202
+ - Mocking React hooks (`jest.mock("react", ...)`) — refactor the component instead
203
+ - Mocking child components by default — tests the integration, not the parent in isolation
204
+ - Manual `act()` warnings ignored — they indicate real bugs
205
+
206
+ ## Skill Reference
207
+
208
+ See `skills/react-testing/SKILL.md` for end-to-end test examples, MSW patterns, and accessibility test scaffolding.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,11 @@
1
+ # Attribution
2
+
3
+ This skill is copied from Jeffallan's public `Jeffallan/claude-skills` repository.
4
+
5
+ - Source: https://github.com/Jeffallan/claude-skills/tree/main/skills/react-native-expert
6
+ - Imported from commit: `e8be415bc94d8d6ebddc2fb50e5d03c6e27d4319`
7
+ - Upstream skill name: `react-native-expert`
8
+ - License: MIT
9
+ - Copyright: Copyright (c) 2025
10
+
11
+ The upstream MIT license text is preserved in `LICENSE`.
@@ -0,0 +1,187 @@
1
+ ---
2
+ name: react-native-expert
3
+ description: Builds, optimizes, and debugs cross-platform mobile applications with React Native and Expo. Implements navigation hierarchies (tabs, stacks, drawers), configures native modules, optimizes FlatList rendering with memo and useCallback, and handles platform-specific code for iOS and Android. Use when building a React Native or Expo mobile app, setting up navigation, integrating native modules, improving scroll performance, handling SafeArea or keyboard input, or configuring Expo SDK projects.
4
+ license: MIT
5
+ metadata:
6
+ author: https://github.com/Jeffallan
7
+ version: "1.1.0"
8
+ domain: frontend
9
+ triggers: React Native, Expo, mobile app, iOS, Android, cross-platform, native module
10
+ role: specialist
11
+ scope: implementation
12
+ output-format: code
13
+ related-skills: react-expert, flutter-expert, test-master
14
+ ---
15
+
16
+ # React Native Expert
17
+
18
+ Senior mobile engineer building production-ready cross-platform applications with React Native and Expo.
19
+
20
+ ## Core Workflow
21
+
22
+ 1. **Setup** — Expo Router or React Navigation, TypeScript config → _run `npx expo doctor` to verify environment and SDK compatibility; fix any reported issues before proceeding_
23
+ 2. **Structure** — Feature-based organization
24
+ 3. **Implement** — Components with platform handling → _verify on iOS simulator and Android emulator; check Metro bundler output for errors before moving on_
25
+ 4. **Optimize** — FlatList, images, memory → _profile with Flipper or React DevTools_
26
+ 5. **Test** — Both platforms, real devices
27
+
28
+ ### Error Recovery
29
+ - **Metro bundler errors** → clear cache with `npx expo start --clear`, then restart
30
+ - **iOS build fails** → check Xcode logs → resolve native dependency or provisioning issue → rebuild with `npx expo run:ios`
31
+ - **Android build fails** → check `adb logcat` or Gradle output → resolve SDK/NDK version mismatch → rebuild with `npx expo run:android`
32
+ - **Native module not found** → run `npx expo install <module>` to ensure compatible version, then rebuild native layers
33
+
34
+ ## Reference Guide
35
+
36
+ Load detailed guidance based on context:
37
+
38
+ | Topic | Reference | Load When |
39
+ |-------|-----------|-----------|
40
+ | Navigation | `references/expo-router.md` | Expo Router, tabs, stacks, deep linking |
41
+ | Platform | `references/platform-handling.md` | iOS/Android code, SafeArea, keyboard |
42
+ | Lists | `references/list-optimization.md` | FlatList, performance, memo |
43
+ | Storage | `references/storage-hooks.md` | AsyncStorage, MMKV, persistence |
44
+ | Structure | `references/project-structure.md` | Project setup, architecture |
45
+
46
+ ## Constraints
47
+
48
+ ### MUST DO
49
+ - Use FlatList/SectionList for lists (not ScrollView)
50
+ - Implement memo + useCallback for list items
51
+ - Handle SafeAreaView for notches
52
+ - Test on both iOS and Android real devices
53
+ - Use KeyboardAvoidingView for forms
54
+ - Handle Android back button in navigation
55
+
56
+ ### MUST NOT DO
57
+ - Use ScrollView for large lists
58
+ - Use inline styles extensively (creates new objects)
59
+ - Hardcode dimensions (use Dimensions API or flex)
60
+ - Ignore memory leaks from subscriptions
61
+ - Skip platform-specific testing
62
+ - Use waitFor/setTimeout for animations (use Reanimated)
63
+
64
+ ## Code Examples
65
+
66
+ ### Optimized FlatList with memo + useCallback
67
+
68
+ ```tsx
69
+ import React, { memo, useCallback } from 'react';
70
+ import { FlatList, View, Text, StyleSheet } from 'react-native';
71
+
72
+ type Item = { id: string; title: string };
73
+
74
+ const ListItem = memo(({ title, onPress }: { title: string; onPress: () => void }) => (
75
+ <View style={styles.item}>
76
+ <Text onPress={onPress}>{title}</Text>
77
+ </View>
78
+ ));
79
+
80
+ export function ItemList({ data }: { data: Item[] }) {
81
+ const handlePress = useCallback((id: string) => {
82
+ console.log('pressed', id);
83
+ }, []);
84
+
85
+ const renderItem = useCallback(
86
+ ({ item }: { item: Item }) => (
87
+ <ListItem title={item.title} onPress={() => handlePress(item.id)} />
88
+ ),
89
+ [handlePress]
90
+ );
91
+
92
+ return (
93
+ <FlatList
94
+ data={data}
95
+ keyExtractor={(item) => item.id}
96
+ renderItem={renderItem}
97
+ removeClippedSubviews
98
+ maxToRenderPerBatch={10}
99
+ windowSize={5}
100
+ />
101
+ );
102
+ }
103
+
104
+ const styles = StyleSheet.create({
105
+ item: { padding: 16, borderBottomWidth: StyleSheet.hairlineWidth },
106
+ });
107
+ ```
108
+
109
+ ### KeyboardAvoidingView Form
110
+
111
+ ```tsx
112
+ import React from 'react';
113
+ import {
114
+ KeyboardAvoidingView,
115
+ Platform,
116
+ ScrollView,
117
+ TextInput,
118
+ StyleSheet,
119
+ SafeAreaView,
120
+ } from 'react-native';
121
+
122
+ export function LoginForm() {
123
+ return (
124
+ <SafeAreaView style={styles.safe}>
125
+ <KeyboardAvoidingView
126
+ style={styles.flex}
127
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
128
+ >
129
+ <ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps="handled">
130
+ <TextInput style={styles.input} placeholder="Email" autoCapitalize="none" />
131
+ <TextInput style={styles.input} placeholder="Password" secureTextEntry />
132
+ </ScrollView>
133
+ </KeyboardAvoidingView>
134
+ </SafeAreaView>
135
+ );
136
+ }
137
+
138
+ const styles = StyleSheet.create({
139
+ safe: { flex: 1 },
140
+ flex: { flex: 1 },
141
+ content: { padding: 16, gap: 12 },
142
+ input: { borderWidth: 1, borderRadius: 8, padding: 12, fontSize: 16 },
143
+ });
144
+ ```
145
+
146
+ ### Platform-Specific Component
147
+
148
+ ```tsx
149
+ import { Platform, StyleSheet, View, Text } from 'react-native';
150
+
151
+ export function StatusChip({ label }: { label: string }) {
152
+ return (
153
+ <View style={styles.chip}>
154
+ <Text style={styles.label}>{label}</Text>
155
+ </View>
156
+ );
157
+ }
158
+
159
+ const styles = StyleSheet.create({
160
+ chip: {
161
+ paddingHorizontal: 12,
162
+ paddingVertical: 4,
163
+ borderRadius: 999,
164
+ backgroundColor: '#0a7ea4',
165
+ // Platform-specific shadow
166
+ ...Platform.select({
167
+ ios: { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.2, shadowRadius: 4 },
168
+ android: { elevation: 3 },
169
+ }),
170
+ },
171
+ label: { color: '#fff', fontSize: 13, fontWeight: '600' },
172
+ });
173
+ ```
174
+
175
+ ## Output Format
176
+
177
+ When implementing React Native features, deliver:
178
+ 1. **Component code** — TypeScript, with prop types defined
179
+ 2. **Platform handling** — `Platform.select` or `.ios.tsx` / `.android.tsx` splits as needed
180
+ 3. **Navigation integration** — route params typed, back-button handling included
181
+ 4. **Performance notes** — memo boundaries, key extractor strategy, image caching
182
+
183
+ ## Knowledge Reference
184
+
185
+ React Native 0.73+, Expo SDK 50+, Expo Router, React Navigation 7, Reanimated 3, Gesture Handler, AsyncStorage, MMKV, React Query, Zustand
186
+
187
+ [Documentation](https://jeffallan.github.io/claude-skills/skills/frontend/react-native-expert/)
@@ -0,0 +1,187 @@
1
+ # Expo Router
2
+
3
+ ## Project Structure
4
+
5
+ ```
6
+ app/
7
+ ├── _layout.tsx # Root layout
8
+ ├── index.tsx # Home (/)
9
+ ├── +not-found.tsx # 404 page
10
+ ├── (tabs)/ # Tab group
11
+ │ ├── _layout.tsx # Tab bar config
12
+ │ ├── index.tsx # First tab
13
+ │ └── profile.tsx # Profile tab
14
+ ├── (auth)/ # Auth group (no tabs)
15
+ │ ├── _layout.tsx
16
+ │ ├── login.tsx
17
+ │ └── register.tsx
18
+ ├── settings/
19
+ │ ├── _layout.tsx # Stack layout
20
+ │ ├── index.tsx # Settings main
21
+ │ └── notifications.tsx
22
+ └── details/[id].tsx # Dynamic route
23
+ ```
24
+
25
+ ## Root Layout
26
+
27
+ ```typescript
28
+ // app/_layout.tsx
29
+ import { Stack } from 'expo-router';
30
+ import { ThemeProvider } from '@react-navigation/native';
31
+
32
+ export default function RootLayout() {
33
+ return (
34
+ <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
35
+ <Stack screenOptions={{ headerShown: false }}>
36
+ <Stack.Screen name="(tabs)" />
37
+ <Stack.Screen name="(auth)" />
38
+ <Stack.Screen
39
+ name="details/[id]"
40
+ options={{ presentation: 'modal' }}
41
+ />
42
+ </Stack>
43
+ </ThemeProvider>
44
+ );
45
+ }
46
+ ```
47
+
48
+ ## Tab Layout
49
+
50
+ ```typescript
51
+ // app/(tabs)/_layout.tsx
52
+ import { Tabs } from 'expo-router';
53
+ import { Ionicons } from '@expo/vector-icons';
54
+
55
+ export default function TabLayout() {
56
+ return (
57
+ <Tabs
58
+ screenOptions={{
59
+ tabBarActiveTintColor: '#007AFF',
60
+ headerShown: true,
61
+ }}
62
+ >
63
+ <Tabs.Screen
64
+ name="index"
65
+ options={{
66
+ title: 'Home',
67
+ tabBarIcon: ({ color, size }) => (
68
+ <Ionicons name="home" color={color} size={size} />
69
+ ),
70
+ }}
71
+ />
72
+ <Tabs.Screen
73
+ name="profile"
74
+ options={{
75
+ title: 'Profile',
76
+ tabBarIcon: ({ color, size }) => (
77
+ <Ionicons name="person" color={color} size={size} />
78
+ ),
79
+ }}
80
+ />
81
+ </Tabs>
82
+ );
83
+ }
84
+ ```
85
+
86
+ ## Navigation
87
+
88
+ ```typescript
89
+ import { router, useLocalSearchParams, Link } from 'expo-router';
90
+
91
+ // Programmatic navigation
92
+ router.push('/details/123'); // Push to stack
93
+ router.replace('/home'); // Replace current
94
+ router.back(); // Go back
95
+ router.canGoBack(); // Check if can go back
96
+
97
+ // With params
98
+ router.push({
99
+ pathname: '/details/[id]',
100
+ params: { id: '123', title: 'Item' },
101
+ });
102
+
103
+ // Link component
104
+ <Link href="/profile" asChild>
105
+ <Pressable>
106
+ <Text>Go to Profile</Text>
107
+ </Pressable>
108
+ </Link>
109
+
110
+ // Reading params
111
+ function DetailsScreen() {
112
+ const { id, title } = useLocalSearchParams<{ id: string; title?: string }>();
113
+ return <Text>Details for {id}</Text>;
114
+ }
115
+ ```
116
+
117
+ ## Protected Routes
118
+
119
+ ```typescript
120
+ // app/(auth)/_layout.tsx
121
+ import { Redirect, Stack } from 'expo-router';
122
+ import { useAuth } from '@/hooks/useAuth';
123
+
124
+ export default function AuthLayout() {
125
+ const { user, isLoading } = useAuth();
126
+
127
+ if (isLoading) {
128
+ return <LoadingScreen />;
129
+ }
130
+
131
+ if (user) {
132
+ return <Redirect href="/(tabs)" />;
133
+ }
134
+
135
+ return <Stack screenOptions={{ headerShown: false }} />;
136
+ }
137
+
138
+ // app/(tabs)/_layout.tsx
139
+ export default function TabLayout() {
140
+ const { user, isLoading } = useAuth();
141
+
142
+ if (isLoading) {
143
+ return <LoadingScreen />;
144
+ }
145
+
146
+ if (!user) {
147
+ return <Redirect href="/(auth)/login" />;
148
+ }
149
+
150
+ return <Tabs>...</Tabs>;
151
+ }
152
+ ```
153
+
154
+ ## Deep Linking
155
+
156
+ ```json
157
+ // app.json
158
+ {
159
+ "expo": {
160
+ "scheme": "myapp",
161
+ "web": {
162
+ "bundler": "metro"
163
+ }
164
+ }
165
+ }
166
+ ```
167
+
168
+ ```typescript
169
+ // Handle: myapp://details/123
170
+ // app/details/[id].tsx handles automatically
171
+ ```
172
+
173
+ ## Quick Reference
174
+
175
+ | Component | Purpose |
176
+ |-----------|---------|
177
+ | `<Stack>` | Stack navigator |
178
+ | `<Tabs>` | Tab navigator |
179
+ | `<Drawer>` | Drawer navigator |
180
+ | `<Link>` | Declarative navigation |
181
+
182
+ | router method | Behavior |
183
+ |---------------|----------|
184
+ | `push()` | Add to stack |
185
+ | `replace()` | Replace current |
186
+ | `back()` | Go back |
187
+ | `dismissAll()` | Dismiss modals |