Instruction file imported from Tentzer/Memo_trip (
.cursor/rules/frontend/react.mdc). Copyright stays with the author.
Project Stack
- Expo 54 with expo-router (file-based routing in
app/) - React Native 0.81 + TypeScript 5.9
- NativeWind 4 (Tailwind CSS utility classes for React Native)
- Supabase for auth, database, and storage
- react-native-maps, react-native-reanimated, @gorhom/bottom-sheet
Component Patterns
- Use functional components exclusively
- Name components in PascalCase; file name matches the default export
- Keep components focused: one primary responsibility per file
- Extract reusable UI into
components/, screen-specific logic stays inapp/ - Destructure props; define prop shapes with TypeScript
interfaceortype
Hooks
- Prefer built-in hooks (
useState,useEffect,useCallback,useMemo,useRef) - Extract shared stateful logic into custom hooks under
hooks/ - Always specify dependency arrays; avoid missing or over-broad deps
- Use
useCallbackfor callbacks passed to child components or FlatList renderers
Styling (NativeWind)
- Use NativeWind
classNamestrings as the primary styling method - For dynamic or computed styles, use
styleprop with conditional Tailwind classes - Avoid raw
StyleSheet.createunless NativeWind cannot express the style - Keep Tailwind config in
tailwind.config.js; extend theme there, not inline
Navigation (expo-router)
- Screens live in
app/; layouts in_layout.tsxfiles - Use
<Link>androuter.push()/router.replace()for navigation - Group related screens with route groups
(group)/ - Use typed routes when available
Supabase Integration
- Access Supabase client through a shared singleton (
lib/supabase.tsor similar) - Handle auth state with Supabase listeners, not manual polling
- Always handle errors from Supabase calls; never silently ignore
.error - Keep row-level security (RLS) policies in Supabase; don't replicate authorization in app code
TypeScript
- Enable strict mode; avoid
anyandascasts unless truly necessary - Define types for API responses, navigation params, and shared data shapes
- Co-locate types with the module that owns them; shared types go in
types/
Lists & Performance
- Use
FlatListorSectionListfor dynamic lists, never.map()inside ScrollView - Provide stable
keyExtractorvalues; avoid array index as key - Memoize expensive list item renderers with
React.memo
Error Handling
- Wrap async operations in try/catch; surface errors to the user via alerts or toasts
- Use error boundaries for unexpected render failures
- Log errors with enough context for debugging (screen name, params)
File Organization
app/ Screens and layouts (expo-router)
components/ Reusable UI components
hooks/ Custom hooks
lib/ Utilities, Supabase client, helpers
types/ Shared TypeScript types
assets/ Images, fonts, Lottie animations
constants/ App-wide constants and config
