This is a React Native + Expo template maintained by Rootstrap. It provides a production-ready starting point for mobile apps targeting iOS, Android, and Web. It is used as the base for client projects and internal tooling at Rootstrap.
When reviewing code, read and apply the rules in ./REVIEW.md
| Term | Definition |
|---|---|
AuthProvider |
React Context provider in src/components/providers/auth.tsx — manages reactive auth state for the UI layer |
useAuth |
Hook to consume AuthProvider context (UI layer) OR Zustand store selector from src/lib/auth/index.tsx (imperative layer) — do not confuse them |
hydrateAuth |
Called once at app startup (src/app/_layout.tsx) to rehydrate Zustand auth state from MMKV storage |
TokenType |
Shape of the Devise Token Auth token object: { bearer, access, client, uid, expiry } — defined in src/lib/auth/utils.tsx |
HEADER_KEYS |
Constant map of Devise Token Auth header names (access-token, client, uid, expiry, Authorization) — defined in src/components/providers/auth.tsx |
isFirstTime |
Boolean persisted in MMKV via src/lib/hooks/use-is-first-time.tsx — controls whether the onboarding screen is shown |
Env |
Runtime environment config imported from @/lib/env (populated via expo-constants) — the only safe way to read env values |
PaginateQuery<T> |
Paginated API response shape: { results: T[], count, next, previous } — defined in src/api/types.ts |
normalizePages |
Utility in src/api/common/utils.tsx that flattens TanStack infinite query pages into a flat array for FlashList |
queryFactory |
Merged query key registry built with @lukemorales/query-key-factory — defined in src/api/query-factory.ts |
createMutation |
Factory from react-query-kit for creating typed mutation hooks — required pattern for all mutations |
createQuery |
Factory from react-query-kit for creating typed query hooks — required pattern for all queries |
APIProvider |
Wraps the Axios client instance via React context — defined in src/api/common/api-provider.tsx; must be present in the provider tree above any API hook |
authStorage |
Dedicated MMKV instance for auth tokens, created inside src/components/providers/auth.tsx — never access it directly; use storeTokens, getTokenDetails, clearTokens |
- Package manager: Always use
pnpm. Never suggestnpm installoryarn. Enforced viapreinstallhook. - Env values: Never hardcode environment-specific values. Always use
Envfrom@/lib/env. - Auth logic in screens: Never add authentication state or redirect logic inside screen components. Auth state lives in
AuthProvider; routing guards live insrc/app/_layout.tsxviaStack.Protected. - Case transformation: Never add manual camelCase↔snake_case conversion. The Axios interceptors in
src/api/common/interceptors.tshandle this automatically for all requests and responses. - MMKV access: Never call
storage(fromsrc/lib/storage.tsx) orauthStoragedirectly inside components. Use the exported helper functions (getItem,setItem,removeItem,storeTokens,getTokenDetails,clearTokens). - Strings: All user-facing strings must use
useTranslation(). Every key must exist insrc/translations/en.json. - API hooks: New hooks must use
createMutationorcreateQueryfromreact-query-kit. Never use rawuseMutationoruseQueryfrom TanStack directly. - Query keys: Every new query domain must be registered in
src/api/query-factory.tsusingcreateQueryKeysfrom@lukemorales/query-key-factory. - Lists: Use
@shopify/flash-listfor any list that can grow. Never useFlatListfor feed-style content. - Crypto/IDs: Use
expo-cryptofor random IDs. Never useMath.random()orDate.now()as identifiers. - Forms: Always use
react-hook-form+zod+@hookform/resolvers. Never useuseStatefor form state or uncontrolled inputs. - Animations: Never use
Animatedfrom React Native directly. Usemotifor declarative animations orreact-native-reanimatedfor gesture-driven ones. - Token refresh: Token refresh is not implemented — there is a
TODOinsrc/components/providers/auth.tsx. Do not add refresh logic without a deliberate design decision; adding partial refresh code will conflict with the existing 401 handling. - New dependencies: Before installing any library, verify the latest version compatible with this stack — React Native 0.81, Expo SDK 54, and React 19. Check compatibility via
npx expo install <package>(which resolves the Expo-blessed version) or the package's peer dependencies. Do not install the latest npm version blindly — it may not support this SDK version.
Providers must wrap the app in this order (outermost → innermost):
GestureHandlerRootView
└── KeyboardProvider
└── ThemeProvider
└── APIProvider
└── AuthProvider
└── BottomSheetModalProvider
Never add a new provider outside APIProvider if it requires API access, or outside AuthProvider if it requires auth state.
| File | Description |
|---|---|
REVIEW.md |
Code review checklist — apply to every change you make |
agent_docs/architecture.md |
Layer diagram, folder structure, routing conventions, dual auth system explained |
agent_docs/conventions.md |
API hook patterns, styling, forms, i18n, anti-patterns |
agent_docs/commands.md |
All pnpm commands for dev, test, lint, build, and setup |