System Requirements
Node.js : Version specified in .nvmrc (currently 20.x)
npm : Comes with Node.js
Git : For version control
nvm : Recommended for Node version management
watchman : Required for React Native development
macOS : Required for iOS development
Windows/Linux : Can develop for Android and Web
All Platforms : Can develop for Web
General Setup
1. Install nvm
macOS/Linux
# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
# Reload shell configuration
source ~/.bashrc # or ~/.zshrc for zsh
# Verify installation
nvm --version
Windows
Use nvm-windows .
2. Install Node.js and npm
# From the project directory
nvm install
# Verify installation
node --version
npm --version
3. Install Watchman
macOS
Linux
# Ubuntu/Debian
sudo apt-get install watchman
# Or build from source
# See: https://facebook.github.io/watchman/docs/install.html
Windows
Not required for Windows development.
4. Clone Repository
# Clone the repo
git clone https://github.com/Expensify/App.git
cd App
# Install dependencies
npm install
Web Development
Setup
No additional setup required beyond general setup.
Running the Web App
The app will be available at http://localhost:8080.
External Contributors
Set this environment variable to avoid CORS errors:
# Create .env file
echo "USE_WEB_PROXY=true" > .env
# Run the app
npm run web
Troubleshooting Web
CORS Errors
Access to fetch at 'https://www.expensify.com/api/BeginSignIn'
from origin 'http://localhost:8080' has been blocked by CORS policy
Solution : Remove .env file or set USE_WEB_PROXY=true.
Port Already in Use
# Kill process on port 8080
lsof -ti:8080 | xargs kill -9
# Or use a different port
PORT = 8081 npm run web
iOS Development
macOS only : iOS development requires macOS and Xcode.
Prerequisites
Xcode : Install from App Store (latest stable version)
Xcode Command Line Tools :
CocoaPods : Install Ruby dependencies
sudo gem install cocoapods
Setup
# Install iOS dependencies
cd ios
pod install
cd ..
Running on iOS Simulator
npm run ios
# Or specify a device
npm run ios -- --simulator= "iPhone 15 Pro"
Running on Physical Device
See HOW_TO_BUILD_APP_ON_PHYSICAL_IOS_DEVICE.md .
Troubleshooting iOS
Pod Install Fails
# Clean pod cache
cd ios
pod deintegrate
pod install --repo-update
cd ..
Build Fails
# Clean build
cd ios
xcodebuild clean
cd ..
# Remove derived data
rm -rf ~/Library/Developer/Xcode/DerivedData
# Reinstall dependencies
npm run clean
npm install
cd ios && pod install && cd ..
Simulator Not Opening
# Reset simulator
xcrun simctl erase all
# Or open Xcode and reset from menu:
# Device > Erase All Content and Settings
Android Development
Prerequisites
Java Development Kit (JDK)
# macOS
brew install openjdk@17
# Ubuntu/Linux
sudo apt-get install openjdk-17-jdk
Android Studio
Download from developer.android.com
Install with default settings
Open Android Studio and complete initial setup
Android SDK
Open Android Studio > Settings > Appearance & Behavior > System Settings > Android SDK
Install:
Android SDK Platform 34
Android SDK Build-Tools 34.0.0
Android SDK Command-line Tools
Environment Variables
Add to .bashrc, .zshrc, or .bash_profile:
export ANDROID_HOME = $HOME / Library / Android / sdk # macOS
# or
export ANDROID_HOME = $HOME / Android / Sdk # Linux
export PATH = $PATH : $ANDROID_HOME / emulator
export PATH = $PATH : $ANDROID_HOME / platform-tools
Reload shell:
source ~/.bashrc # or ~/.zshrc
Create Android Virtual Device (AVD)
Open Android Studio
Tools > Device Manager
Create Virtual Device
Select a device (e.g., Pixel 6)
Select system image (API 34 recommended)
Finish setup
Running on Android Emulator
# Start emulator (from Android Studio or command line)
emulator -avd Pixel_6_API_34 &
# Run app
npm run android
Running on Physical Device
Enable Developer Options on your device
Enable USB Debugging
Connect device via USB
Verify connection:
Run app:
Troubleshooting Android
Build Fails
# Clean gradle build
cd android
./gradlew clean
cd ..
# Clear metro cache
npm start -- --reset-cache
ADB Offline
adb kill-server
adb start-server
adb devices
Emulator Not Starting
# List available AVDs
emulator -list-avds
# Start specific AVD
emulator -avd < avd_nam e >
# Cold boot (slower but more reliable)
emulator -avd < avd_nam e > -no-snapshot-load
Port Already in Use
# Kill metro bundler
lsof -ti:8081 | xargs kill -9
# Restart
npm start
macOS Desktop Development
Prerequisites
Same as iOS development requirements.
Running macOS App
Required : All changes must be tested on iOS, Android, Web, and mWeb before submitting a PR.
Testing Without Mac
If you don’t have a Mac, see TESTING_MACOS_AND_IOS.md for alternatives:
Cloud-based Mac services
MacinCloud
CI/CD preview builds
Testing Mobile Web (mWeb)
Use browser DevTools to simulate mobile:
Open http://localhost:8080 in Chrome
Open DevTools (F12)
Click device toggle icon (Cmd+Shift+M / Ctrl+Shift+M)
Select mobile device (e.g., iPhone 12 Pro)
Test the app
IDE Setup
Visual Studio Code (Recommended)
Recommended Extensions
// .vscode/extensions.json
{
"recommendations" : [
"dbaeumer.vscode-eslint" ,
"esbenp.prettier-vscode" ,
"bradlc.vscode-tailwindcss" ,
"ms-vscode.vscode-typescript-next"
]
}
Settings
// .vscode/settings.json
{
"editor.formatOnSave" : true ,
"editor.defaultFormatter" : "esbenp.prettier-vscode" ,
"eslint.validate" : [
"javascript" ,
"javascriptreact" ,
"typescript" ,
"typescriptreact"
],
"typescript.tsdk" : "node_modules/typescript/lib"
}
IntelliJ IDEA / WebStorm
Settings > Languages & Frameworks > JavaScript > Prettier
Check “On save”
Set Prettier package: <project>/node_modules/prettier
Environment Variables
Common Variables
# .env (optional - not recommended for external contributors)
NEW_EXPENSIFY_URL = https://dev.new.expensify.com
SECURE_EXPENSIFY_URL = https://www.expensify.com/api
EXPENSIFY_URL = https://www.expensify.com
USE_WEB_PROXY = true # External contributors should set this
Creating .env is not recommended for external contributors. Variables can become outdated and cause errors.
Testing Specific Features
# Enable Redux DevTools for Onyx debugging
USE_REDUX_DEVTOOLS = true
# Enable Why Did You Render for performance debugging
USE_WDYR = true
# Capture performance metrics
CAPTURE_METRICS = true
ONYX_METRICS = true
Development Workflow
1. Start Development Server
# Terminal 1: Metro bundler (for React Native)
npm start
# Terminal 2: Run platform
npm run web # or ios/android
2. Make Changes
Edit files in src/. Changes will hot-reload automatically.
3. Run Code Quality Checks
# Format code (REQUIRED before commit)
npm run prettier
# Lint
npm run lint
# Type check (fast, development)
npm run typecheck-tsgo
# Type check (production gate)
npm run typecheck
# Run all checks
npm run prettier && npm run lint && npm run typecheck
4. Run Tests
# Run all tests
npm test
# Run specific test file
npm test -- MyComponent.test.tsx
# Run tests in watch mode
npm test -- --watch
5. Clean and Reset
If things aren’t working:
# Clean everything
npm run clean
# Reinstall dependencies
npm install
# iOS: Reinstall pods
cd ios && pod install && cd ..
# Android: Clean gradle
cd android && ./gradlew clean && cd ..
# Clear React Native cache
npm start -- --reset-cache
# Nuclear option: Delete everything and start over
rm -rf node_modules ios/Pods ios/Podfile.lock
npm install
cd ios && pod install && cd ..
Debugging
# Install globally
npm install -g react-devtools
# Run
react-devtools
# In app, shake device (or Cmd+D) > "Toggle Inspector"
Flipper
Flipper is installed automatically with React Native:
Download Flipper Desktop
Run app in development mode
Flipper auto-detects the app
View logs, network, layout, Onyx state, etc.
Open http://localhost:8080 in Chrome
Open DevTools (F12)
Debug like a normal web app
Enable Web Inspector on iOS device:
Settings > Safari > Advanced > Web Inspector
Run app on device or simulator
Open Safari on Mac > Develop > [Device] > [App]
# Run performance tests
npm run test:perf
# Compare with baseline
npm run test:perf -- --compare
See REASSURE_PERFORMANCE_TEST.md .
Common Issues
Metro Bundler Port Conflict
# Kill process on port 8081
lsof -ti:8081 | xargs kill -9
# Restart metro
npm start
Node Version Mismatch
# Check current version
node --version
# Use correct version
nvm use
# Install if missing
nvm install
Pod Install Fails (iOS)
cd ios
rm -rf Pods Podfile.lock
pod install --repo-update
cd ..
Gradle Sync Fails (Android)
cd android
./gradlew clean
cd ..
rm -rf android/.gradle
npm run android
Next Steps
Coding Standards Learn the coding standards and best practices
Testing Write and run tests
Pull Requests Submit your first PR
Architecture Understand the architecture
Additional Resources