A React Native boilerplate with Expo Router, TanStack Query, Zustand, NativeWind, i18n, and more
npm install phl-rn-boilerplate

A modern, production-ready React Native boilerplate built with Expo SDK 54, MVVM architecture, and mobile development best practices.
``bash`
npx create-expo-app my-app -t phl-rn-boilerplate
cd my-app
`bash`
git clone https://github.com/pedrohbl03/phl-rn-boilerplate.git my-app
cd my-app
yarn install
This template was created to accelerate React Native app development, providing a solid foundation with well-defined architecture, state management, internationalization, and modern styling.
Package ID: com.phlstart.app
| Technology | Version | Description |
|------------|---------|-------------|
| Expo | SDK 54 | React Native development framework |
| React Native | 0.81.5 | Cross-platform mobile framework |
| TypeScript | 5.9 | JavaScript with static typing |
| Expo Router | 6.x | File-based navigation |
| NativeWind | 4.x | Tailwind CSS for React Native |
| Zustand | 5.x | Global state management |
| React Query | 5.x | Server state management |
| i18next | 25.x | Internationalization |
| MMKV | 4.x | High-performance storage |
| Zod | 3.x | Schema validation |
| React Hook Form | 7.x | Form management |
The boilerplate implements the Model-View-ViewModel (MVVM) pattern, which clearly separates application responsibilities into three layers:
Represents the data and business logic of the application.
``
src/
āāā domain/ # Entities and business rules
ā āāā entities/ # Domain types and interfaces
ā āāā schemas/ # Validation schemas (Zod)
āāā data/ # Data layer
āāā api/ # HTTP client and interfaces
āāā storage/ # Local persistence (MMKV)
The user interface. Pure React components that only render the UI and delegate actions to the ViewModel.
``
src/
āāā app/ # Routes (Expo Router)
ā āāā (tabs)/ # Tab Navigator
āāā presentation/
āāā screens/ # Application screens
āāā HomeScreen.tsx
āāā ArchScreen.tsx
āāā SettingsScreen.tsx
View Characteristics:
- Contains no business logic
- Receives formatted data from ViewModel
- Calls actions exposed by ViewModel
- Responsible only for rendering
The bridge between Model and View. Contains presentation logic, manages screen state, and exposes data and actions to the View.
``
src/
āāā presentation/
āāā viewmodels/
āāā useHomeViewModel.ts
āāā useArchViewModel.ts
āāā useSettingsViewModel.ts
ViewModel Responsibilities:
- Manage screen state
- Format data for display
- Expose actions that View can execute
- Abstract business logic from View
ViewModel (useSettingsViewModel.ts):
`typescript
export function useSettingsViewModel() {
const { t, i18n } = useTranslation();
const { isDark, toggleTheme } = useTheme();
const { language, setLanguage } = useAppStore();
// Data formatted for the View
const title = t('settings.title');
const themeValue = isDark ? t('settings.dark') : t('settings.light');
// Available actions
const handleToggleTheme = useCallback(() => {
toggleTheme();
}, [toggleTheme]);
return {
isDark,
title,
themeValue,
handleToggleTheme,
// ...
};
}
`
View (SettingsScreen.tsx):
`typescript
export function SettingsScreen() {
const vm = useSettingsViewModel();
return (
);
}
`
- Separation of concerns: More organized and maintainable code
- Testability: ViewModels can be tested independently of UI
- Reusability: Logic can be shared between different Views
- Teamwork: Developers can work in parallel on layers
``
src/
āāā app/ # Routes (Expo Router)
ā āāā _layout.tsx # Root layout
ā āāā (tabs)/ # Tab Navigator
ā āāā _layout.tsx # Tabs layout
ā āāā index.tsx # Home
ā āāā arch.tsx # Architecture
ā āāā settings.tsx # Settings
ā
āāā components/ # Reusable components
ā āāā ui/ # Base UI components
ā āāā Button.tsx
ā āāā Card.tsx
ā āāā Input.tsx
ā āāā Text.tsx
ā
āāā core/ # Configuration and bootstrap
ā āāā config/
ā āāā bootstrap.ts # App initialization
ā āāā env.ts # Environment variables
ā
āāā data/ # Data layer
ā āāā api/ # HTTP client (Axios)
ā āāā storage/ # Local storage (MMKV)
ā
āāā domain/ # Application domain
ā āāā entities/ # Entities/types
ā āāā schemas/ # Zod schemas
ā
āāā hooks/ # Custom hooks
ā āāā useApi.ts
ā āāā useForm.ts
ā
āāā i18n/ # Internationalization
ā āāā index.ts
ā āāā locales/
ā āāā pt-BR.ts
ā āāā en-US.ts
ā
āāā presentation/ # Presentation layer (MVVM)
ā āāā screens/ # Views
ā āāā viewmodels/ # ViewModels
ā
āāā providers/ # Context Providers
ā āāā AppProvider.tsx
ā āāā ThemeProvider.tsx
ā āāā query-client.ts
ā
āāā stores/ # Global state (Zustand)
ā āāā app.store.ts
ā
āāā styles/ # Global styles
ā āāā global.css
ā
āāā types/ # Global types
āāā global.d.ts
- Node.js 18+
- Yarn or npm
- Android Studio (for Android)
- Xcode (for iOS, macOS only)
#### Using npx (Recommended)
`bash`
npx create-expo-app my-app -t phl-rn-boilerplate
cd my-app
Then skip to step 4 (prebuild).
#### Manual Installation
1. Clone the repository:
`bash`
git clone https://github.com/your-username/phl-rn-boilerplate.git
cd phl-rn-boilerplate
2. Install dependencies:
`bash`
yarn installor
npm install
3. Configure environment variables:
`bash`
cp .env.example .env
4. Run prebuild (see section below):
`bash`
npx expo prebuild
5. Start the project:
`bashDevelopment
yarn start
Prebuild: Why is it necessary?
$3
The
npx expo prebuild (or expo prebuild) command generates the native android/ and ios/ folders of the project. This process is essential when using Expo with native modules.$3
This boilerplate uses libraries that require native code:
| Library | Reason |
|---------|--------|
| react-native-mmkv | High-performance native storage |
| react-native-reanimated | Native animations |
| react-native-gesture-handler | Native gestures |
| react-native-screens | Optimized native navigation |
These libraries don't work with Expo Go (Expo's default development app) because they contain custom native code that needs to be compiled.
$3
`
āāāāāāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāā
ā expo prebuild ā āāā¶ ā Generates ā āāā¶ ā expo run:* ā
ā ā ā android/ & ios/ā ā or yarn * ā
āāāāāāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāā
`$3
- First time cloning the project
- After adding a new native library
- After modifying
app.json (name, icon, splash, etc.)
- After updating the Expo SDK$3
`bash
Generate native folders
npx expo prebuildClean and regenerate (useful after issues)
npx expo prebuild --cleanGenerate Android only
npx expo prebuild --platform androidGenerate iOS only
npx expo prebuild --platform ios
`$3
| Expo Go | Development Build |
|---------|-------------------|
| Ready-to-download app | Custom build |
| Limited to Expo APIs | Supports any native library |
| No prebuild needed | Requires prebuild |
| Great for prototyping | Required for production |
This boilerplate uses Development Build, which offers full flexibility to use any native library.
Included Features
- Tab Navigator with 3 screens (Home, Architecture, Settings)
- Dark/Light Mode with persistence
- Internationalization (Portuguese and English)
- Persistence of preferences in MMKV
- Reusable UI Components (Button, Card, Input, Text)
- Configured HTTP Client (Axios)
- Form Validation (Zod + React Hook Form)
- Global State (Zustand with persistence)
- Server State (React Query)
Available Scripts
`bash
yarn start # Start Metro Bundler
yarn android # Run on Android
yarn ios # Run on iOS
yarn web # Run in browser
`Customization
$3
1. Update
app.json:
`json
{
"expo": {
"ios": {
"bundleIdentifier": "com.yourdomain.app"
},
"android": {
"package": "com.yourdomain.app"
}
}
}
`2. Run prebuild:
`bash
npx expo prebuild --clean
`$3
1. Create translation file in
src/i18n/locales/
2. Import and register in src/i18n/index.ts
3. Add option in useSettingsViewModel.ts$3
1. Create ViewModel in
src/presentation/viewmodels/
2. Create Screen in src/presentation/screens/
3. Create route in src/app/
4. Export in index.ts` filesMIT
---
Developed with ā¤ļø by PhL