Project Structure
If you open the new project in VSCode you will see the following structure:
Directoryfeatures ## feature-oriented modules
Directoryauth/
- login-screen.tsx
- use-auth-store.tsx
Directorycomponents/
- login-form.tsx
- login-form.test.tsx
Directoryfeed/
- feed-screen.tsx
- post-detail-screen.tsx
- add-post-screen.tsx
- api.ts
Directorycomponents/
- post-card.tsx
Directorysettings/
- settings-screen.tsx
Directorycomponents/
- settings-item.tsx
- settings-container.tsx
- language-item.tsx
- theme-item.tsx
Directoryonboarding/
- onboarding-screen.tsx
Directorycomponents/
- cover.tsx
Directorystyle-demo/
- style-screen.tsx
Directorycomponents/
- typography-demo.tsx
- colors-demo.tsx
- buttons-demo.tsx
- inputs-demo.tsx
- title.tsx
Directoryapp ## app routes and layouts (Expo Router)
Directory(app)/
- _layout.tsx
- index.tsx (re-exports FeedScreen)
- settings.tsx (re-exports SettingsScreen)
- style.tsx (re-exports StyleScreen)
Directoryfeed/
- [id].tsx (re-exports PostDetailScreen)
- add-post.tsx (re-exports AddPostScreen)
- _layout.tsx
- login.tsx (re-exports LoginScreen)
- onboarding.tsx (re-exports OnboardingScreen)
Directorycomponents ## design system and shared UI components
Directoryui/
- button.tsx
- checkbox.tsx
- colors.js
- focus-aware-status-bar.tsx
- form-utils.ts
Directoryicons/
- …
- image.tsx
- input.tsx
- list.tsx
- modal.tsx
- progress-bar.tsx
- select.tsx
- text.tsx
- use-theme-config.tsx
- utils.tsx
Directorylib ## core infrastructure and utilities
Directoryapi/
- index.ts
- client.tsx
- provider.tsx
- utils.tsx (includes PaginateQuery type)
Directoryauth/
- utils.tsx (token storage utilities)
Directoryhooks/
- use-is-first-time.tsx
- use-selected-theme.tsx
Directoryi18n/
- index.tsx
- resources.ts
- types.ts
- utils.tsx
- storage.tsx
- test-utils.tsx
- utils.ts
Directorytranslations ## translation resources files
- ar.json
- en.json
Architecture Overview
Section titled “Architecture Overview”The project follows a feature-oriented architecture where each feature is self-contained with its screens, components, API calls, and state management. This approach promotes:
- Feature isolation: Each feature has all related code in one place
- Better scalability: Easy to add new features without affecting existing ones
- Improved maintainability: Clear boundaries between features
- Team collaboration: Multiple developers can work on different features simultaneously
Key Folders
Section titled “Key Folders”features/
Section titled “features/”This is where all feature-specific code lives. Each feature folder follows a consistent pattern:
- Screens: Named with
-screen.tsxsuffix, placed in the feature root - components/: Feature-specific components that are only used within this feature
- api.ts: Feature-specific API calls and React Query hooks (optional)
- use-*-store.tsx: Feature-specific state management with Zustand (optional)
Example: The auth feature contains the login screen, login form component, and auth store all in one place.
Convention:
- ✅ Screens use
-screen.tsxsuffix - ✅ Only
components/subfolder is allowed - ✅ Use single files (
api.ts) not folders - ❌ No
index.tsbarrel exports (prevents fast refresh issues)
This folder contains the Expo Router file-based routing structure. Routes are thin re-export layers that import screens from features:
export { LoginScreen as default } from '@/features/auth/login-screen';This keeps routing configuration separate from feature logic while maintaining Expo Router’s file-based routing benefits.
components/ui/
Section titled “components/ui/”This is the design system containing reusable UI primitives and shared utilities:
- UI components (Button, Input, Text, etc.)
- Form utilities (
form-utils.ts) - Theme configuration (
use-theme-config.tsx) - Icon components
When to promote a component here: When it’s used in 2+ features and has no feature-specific logic.
Core infrastructure and cross-cutting concerns:
api/: Shared API client, React Query provider, and utilities- Includes
PaginateQuerytype used across features - Axios client configuration
- API helper functions
- Includes
auth/: Low-level token storage utilities (getToken, setToken, removeToken)hooks/: Global hooks (useIsFirstTime, useSelectedTheme)i18n/: Internationalization setup and utilities- Core utilities: Storage abstraction, environment config, test utilities
What stays here: Infrastructure that features depend on but don’t own.
translations/
Section titled “translations/”Contains i18n resource files. We recommend using translation files even if you only support one language initially, as it:
- Makes future multi-language support easier
- Centralizes all user-facing strings
- Facilitates copy changes without code modifications
Importing Files
Section titled “Importing Files”We use absolute imports with direct file paths (no barrel exports) to avoid fast refresh issues:
// ✅ CORRECT - Direct importsimport { Button, Input, Text } from '@/components/ui';import { LoginScreen } from '@/features/auth/login-screen';import { usePosts } from '@/features/feed/api';import { translate } from '@/lib/i18n';import { client } from '@/lib/api';
// ❌ WRONG - Barrel exports (causes fast refresh issues)import { LoginScreen } from '@/features/auth';import { usePosts } from '@/features/feed';Import Patterns
Section titled “Import Patterns”Within the same feature (use relative imports):
import { LoginForm } from './components/login-form';import { useAuthStore } from './use-auth-store';Cross-feature imports (use absolute with full path):
import { useAuthStore } from '@/features/auth/use-auth-store';import { PostCard } from '@/features/feed/components/post-card';From design system:
import { Button, Input, View } from '@/components/ui';import { getFieldError } from '@/components/ui/form-utils';import { useThemeConfig } from '@/components/ui/use-theme-config';From lib:
import { translate } from '@/lib/i18n';import { useIsFirstTime } from '@/lib/hooks/use-is-first-time';import { client, APIProvider } from '@/lib/api';Configuration
Section titled “Configuration”This absolute import pattern is enabled through Babel module resolver and TypeScript path mapping:
⚙️ Babel configuration
module.exports = function (api) { api.cache(true); return { presets: [ 'babel-preset-expo', ], plugins: [ [ 'module-resolver', { root: ['./'], alias: { '@': './src', '@env': './src/lib/env.js', }, extensions: [ '.ios.ts', '.android.ts', '.ts', '.ios.tsx', '.android.tsx', '.tsx', '.jsx', '.js', '.json', ], }, ], 'react-native-reanimated/plugin', ], };};⚙️ Typescript Config
{ "extends": "expo/tsconfig.base", "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"], "@env": ["env.ts"] }, "checkJs": true, "strict": true, "esModuleInterop": true }, "include": [ "**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts", "nativewind-env.d.ts", "env.ts" ], "exclude": [ "node_modules", "babel.config.js", "metro.config.js", "docs", "cli", "android", "ios", "lint-staged.config.js" ]}Adding a New Feature
Section titled “Adding a New Feature”To add a new feature, follow this template:
# Create feature structuremkdir -p src/features/my-feature/components
# Create screentouch src/features/my-feature/my-feature-screen.tsx
# Create route re-exportecho "export { MyFeatureScreen as default } from '@/features/my-feature/my-feature-screen';" > src/app/my-feature.tsxFor features with API:
mkdir -p src/features/my-feature/componentstouch src/features/my-feature/my-feature-screen.tsxtouch src/features/my-feature/api.tstouch src/features/my-feature/components/my-component.tsx