

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1# React Native + Expo + TypeScript — Cursor Rules2# Production mobile app patterns with React Native, Expo SDK, and TypeScript34# Project Context5You are building a cross-platform mobile application using React Native with Expo (SDK 50+)6and TypeScript. The app targets both iOS and Android from a single codebase. The project uses7Expo Router for navigation, React Query for server state, and follows React Native best8practices for performance and UX.910# Project Structure (Expo Router)11```12app/13 _layout.tsx # Root layout (providers, fonts, splash screen)14 (tabs)/15 _layout.tsx # Tab navigator layout16 index.tsx # Home tab17 explore.tsx # Explore tab18 profile.tsx # Profile tab19 (auth)/20 _layout.tsx # Auth stack layout21 login.tsx22 register.tsx23 [id].tsx # Dynamic route24 +not-found.tsx # 404 screen25src/26 components/27 ui/ # Reusable UI components28 screens/ # Screen-specific components29 hooks/ # Custom hooks30 services/ # API client and services31 stores/ # Zustand/Jotai stores32 types/ # TypeScript types33 utils/ # Utilities34 constants/ # Colors, spacing, config35 theme.ts36 layout.ts37```3839# Expo Router Navigation40- Use file-based routing in the `app/` directory (like Next.js for mobile).41- Group routes with parentheses: `(tabs)`, `(auth)`, `(modal)`.42- Use `_layout.tsx` files to define navigators (Stack, Tabs, Drawer).43- Navigate with typed routes:44```typescript45 import { router } from 'expo-router';46 router.push('/profile/123');47 router.replace('/(auth)/login');48 router.back();49```50- Use `<Link>` component for declarative navigation.51- Handle deep links by defining route patterns in app.json.52- Protect routes in layout files by checking auth state and redirecting.5354# Component Patterns55- Use `StyleSheet.create()` for all styles — never inline style objects:56```typescript57 const styles = StyleSheet.create({58 container: {59 flex: 1,60 padding: 16,61 backgroundColor: colors.background,62 },63 });64```65- Extract dimensions and colors into theme constants:66```typescript67 export const colors = { primary: '#007AFF', background: '#FFFFFF', text: '#000000' } as const;68 export const spacing = { xs: 4, sm: 8, md: 16, lg: 24, xl: 32 } as const;69```70- Use `Platform.select()` for platform-specific values:71```typescript72 const shadow = Platform.select({73 ios: { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1 },74 android: { elevation: 3 },75 });76```77- Use `<SafeAreaView>` or `useSafeAreaInsets()` for proper safe area handling.7879# Performance (Critical for Mobile)80- Use `FlatList` for long lists — never `ScrollView` with mapped items:81```typescript82 <FlatList83 data={items}84 keyExtractor={(item) => item.id}85 renderItem={({ item }) => <ItemCard item={item} />}86 getItemLayout={(_, index) => ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index })}87 initialNumToRender={10}88 maxToRenderPerBatch={5}89 windowSize={5}90 />91```92- Memoize list item components with `React.memo()`.93- Use `useCallback` for event handlers passed to list items.94- Use `Animated` API or `react-native-reanimated` for 60fps animations.95```typescript96 // Use reanimated for gesture-driven animations97 const translateX = useSharedValue(0);98 const animatedStyle = useAnimatedStyle(() => ({99 transform: [{ translateX: translateX.value }],100 }));101```102- Optimize images: use `expo-image` (not React Native's `<Image>`):103```typescript104 import { Image } from 'expo-image';105 <Image source={uri} contentFit="cover" placeholder={blurhash} transition={200} />106```107- DON'T: Use `console.log` in production — it causes performance issues on Android.108- DON'T: Create new style objects in render — use StyleSheet.create outside the component.109- DON'T: Use `ScrollView` for long dynamic lists — use `FlatList` or `FlashList`.110111# State Management112- Use React Query (TanStack Query) for server/API state.113- Use Zustand for client-side global state (lighter than Redux):114```typescript115 import { create } from 'zustand';116 interface AuthStore {117 user: User | null;118 setUser: (user: User | null) => void;119 logout: () => void;120 }121 export const useAuthStore = create<AuthStore>((set) => ({122 user: null,123 setUser: (user) => set({ user }),124 logout: () => set({ user: null }),125 }));126```127- Use `AsyncStorage` (via zustand `persist` middleware) for persisting state across app restarts.128- DON'T: Store server data in Zustand — use React Query for anything from an API.129130# API Integration131- Create a typed API client with interceptors:132```typescript133 const api = axios.create({ baseURL: process.env.EXPO_PUBLIC_API_URL });134 api.interceptors.request.use(async (config) => {135 const token = await SecureStore.getItemAsync('accessToken');136 if (token) config.headers.Authorization = `Bearer ${token}`;137 return config;138 });139```140- Use React Query for all data fetching:141```typescript142 export function useUser(id: string) {143 return useQuery({144 queryKey: ['user', id],145 queryFn: () => api.get<User>(`/users/${id}`).then(r => r.data),146 staleTime: 5 * 60 * 1000,147 });148 }149```150- Handle offline state: show cached data, queue mutations for retry.151- Use `useMutation` with `onMutate` for optimistic updates.152153# Authentication154- Store tokens in `expo-secure-store` (encrypted native storage), NOT AsyncStorage.155- Implement token refresh with axios interceptors.156- Check auth state in root layout and redirect to login if unauthenticated.157- Support biometric authentication with `expo-local-authentication`.158159# Form Handling160- Use `react-hook-form` with zod validation for forms:161```typescript162 const { control, handleSubmit } = useForm<LoginForm>({163 resolver: zodResolver(loginSchema),164 });165```166- Use `<Controller>` to wrap React Native `<TextInput>` components.167- Handle keyboard properly: use `<KeyboardAvoidingView>` or `react-native-keyboard-aware-scroll-view`.168- Dismiss keyboard on tap outside with `<TouchableWithoutFeedback>` + `Keyboard.dismiss()`.169170# Push Notifications171- Use `expo-notifications` for push notification setup.172- Register for push tokens on app start, send to your backend.173- Handle notification taps to navigate to relevant screens.174- Request notification permissions at a contextually appropriate moment (not on first launch).175176# Expo-Specific Patterns177- Use `expo-constants` for app config values.178- Use `expo-updates` for OTA (over-the-air) updates.179- Use `expo-splash-screen` to control splash screen visibility during asset loading.180- Configure app.json/app.config.ts properly for both platforms.181- Use EAS Build for production builds and EAS Submit for store submissions.182183# Testing184- Use Jest + React Native Testing Library for component tests.185- Test hooks with `renderHook` from testing library.186- Mock navigation: `jest.mock('expo-router')`.187- Mock native modules: `jest.mock('expo-secure-store')`.188- Use Detox or Maestro for E2E tests on real devices/simulators.189190# Common Mistakes to Avoid191- DON'T: Use web-specific APIs (window, document) — they don't exist in React Native.192- DON'T: Create styles inside render functions — extract to StyleSheet.create.193- DON'T: Use `TouchableOpacity` from React Native — use `Pressable` (more flexible).194- DON'T: Store sensitive data in AsyncStorage — use expo-secure-store.195- DON'T: Ignore platform differences — test on both iOS and Android.196- DON'T: Use pixel values for responsive layout — use flex, percentages, or Dimensions API.197- DON'T: Block the JS thread with heavy computation — use `InteractionManager` or offload to native.198
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| survivorforge/cursor-rulesrules/ai-ml-python/.cursorrules · 16 | .cursorrules | teststylearchdeployment+2 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/langchain-ai/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+4 | 84/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/aws-serverless/.cursorrules · 16 | .cursorrules | teststylearchtypes+6 | 73/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/tailwindcss/.cursorrules · 16 | .cursorrules | lint-formatstylearchui+3 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/mern-stack/.cursorrules · 16 | .cursorrules | setupteststylearch+6 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/api-design-rest/.cursorrules · 16 | .cursorrules | lint-formatstylesecurityapi+3 | 69/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/api-microservices/.cursorrules · 16 | .cursorrules | buildteststylearch+5 | 92/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/chrome-extension/.cursorrules · 16 | .cursorrules | teststylearchtesting-strategy+4 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/clean-code/.cursorrules · 16 | .cursorrules | styledo-notagent-behaviourdocs | 57/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/database-sql/.cursorrules · 16 | .cursorrules | styletypessecuritydatabase+3 | 65/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/devops-docker/.cursorrules · 16 | .cursorrules | setupbuildteststyle+4 | 93/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/devops-infrastructure/.cursorrules · 16 | .cursorrules | buildteststylesecurity+3 | 93/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/django-rest/.cursorrules · 16 | .cursorrules | buildteststylearch+5 | 84/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/docker-devops/.cursorrules · 16 | .cursorrules | setupteststylearch+6 | 85/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/flutter-dart/.cursorrules · 16 | .cursorrules | teststylearchtypes+5 | 89/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/fullstack-nextjs-prisma/.cursorrules · 16 | .cursorrules | teststylearchtypes+7 | 96/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/go-gin/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+5 | 84/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nextjs-14-app-router/.cursorrules · 16 | .cursorrules | teststyletypestesting-strategy+3 | 71/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nextjs-app-router/.cursorrules · 16 | .cursorrules | teststylearchtypes+5 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nextjs-typescript/.cursorrules · 16 | .cursorrules | teststylearchtypes+5 | 81/100 | 13 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/survivorforge-cursor-rules-rules-mobile-react-native-cursorrules)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.