Skip to main content

Documentation Index

Fetch the complete documentation index at: https://resources.devweekends.com/llms.txt

Use this file to discover all available pages before exploring further.

Environment Setup

Module Overview

Estimated Time: 1-2 hours | Difficulty: Beginner | Prerequisites: Module 1 completed
Setting up a React Native development environment can be tricky, especially for iOS development. Think of it like setting up a workshop: you need different tools depending on what you are building. iOS development requires Apple’s proprietary tools (Xcode, CocoaPods) that only run on macOS — there is no workaround for this at the local level. Android development is more platform-agnostic, but the toolchain (Android Studio, JDK, SDK, emulator with hardware acceleration) has many moving parts that must all agree on versions. This module walks you through every step on all platforms. What You’ll Learn:
  • Expo vs React Native CLI decision
  • Node.js and package manager setup
  • iOS development setup (macOS only)
  • Android development setup (all platforms)
  • VS Code configuration
  • Troubleshooting common issues

Expo vs React Native CLI

Before setting up, choose your development approach. This is one of the most consequential decisions in a React Native project, and it is not as binary as it once was. Expo has evolved from “the training wheels option” to a production-grade toolchain used by companies like Shopify and Discord. The bare CLI remains necessary for brownfield integrations (adding React Native screens to an existing Swift/Kotlin app) and for teams that need full control over native build configuration.
┌─────────────────────────────────────────────────────────────────────────────┐
│                    Expo vs React Native CLI                                  │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│   Expo (Recommended for Most Projects)                                       │
│   ────────────────────────────────────                                       │
│   ✅ Zero native code configuration                                          │
│   ✅ Expo Go app for instant testing                                         │
│   ✅ EAS Build for cloud builds                                              │
│   ✅ Over-the-air updates                                                    │
│   ✅ Pre-built native modules                                                │
│   ✅ Works on Windows/Linux for iOS (via EAS)                               │
│   ⚠️  Some native modules require "development builds"                      │
│                                                                              │
│   React Native CLI (Bare Workflow)                                           │
│   ────────────────────────────────                                           │
│   ✅ Full native code access                                                 │
│   ✅ Any native module/SDK                                                   │
│   ✅ Custom native code                                                      │
│   ⚠️  Requires Xcode (macOS) for iOS                                        │
│   ⚠️  More complex setup                                                    │
│   ⚠️  Manual native configuration                                           │
│                                                                              │
│   Recommendation:                                                            │
│   Start with Expo. Use "development builds" when you need custom            │
│   native code. You get the best of both worlds.                             │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
  • You’re learning React Native
  • Building a new project from scratch
  • Don’t need custom native modules (yet)
  • Want faster development iteration
  • Need to build iOS apps on Windows/Linux
  • Want managed OTA updates

Prerequisites (All Platforms)

1. Install Node.js

React Native requires Node.js 18 or newer. Node is the JavaScript runtime that powers Metro (the bundler), the development server, and all the CLI tooling. It does not run on the device itself — Hermes or JavaScriptCore handles that. Think of Node as the backstage crew: essential during development, invisible in production.
# Using Homebrew (recommended)
brew install node

# Or using nvm (Node Version Manager)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.zshrc  # or ~/.bashrc
nvm install 20
nvm use 20
nvm alias default 20

# Verify installation
node --version  # Should be v18.x or higher
npm --version   # Should be v9.x or higher

2. Install a Package Manager

npm comes with Node.js. No additional installation needed.
# Verify npm
npm --version

# Update npm (optional)
npm install -g npm@latest

3. Install Git

# Git comes with Xcode Command Line Tools
xcode-select --install

# Or using Homebrew
brew install git

# Verify
git --version

Expo Setup

Quick Start with Expo

# Create a new Expo project
npx create-expo-app@latest my-app

# Navigate to project
cd my-app

# Start development server
npx expo start

Install Expo Go

Download Expo Go on your physical device:

iOS

Download from App Store

Android

Download from Google Play

Running Your App

# Start the development server
npx expo start

# Options in the terminal:
# Press 'i' - Open iOS simulator (macOS only)
# Press 'a' - Open Android emulator
# Press 'w' - Open in web browser
# Press 'r' - Reload app
# Press 'm' - Toggle menu
# Press 'j' - Open debugger

# Or scan the QR code with:
# - iOS: Camera app
# - Android: Expo Go app

Expo Development Builds

For native modules not in Expo Go, create a development build:
# Install EAS CLI
npm install -g eas-cli

# Login to Expo
eas login

# Configure your project
eas build:configure

# Create development build
eas build --profile development --platform ios
eas build --profile development --platform android

# Or build locally (requires native tooling)
npx expo run:ios
npx expo run:android

iOS Setup (macOS Only)

iOS development requires macOS. Windows and Linux users can use EAS Build for cloud-based iOS builds.

1. Install Xcode

# Install from Mac App Store (recommended)
# Search for "Xcode" in App Store

# Or install via command line
xcode-select --install

# After installation, open Xcode and accept the license
sudo xcodebuild -license accept

# Install additional components when prompted
Xcode Requirements:
  • macOS Ventura 13.5 or later (for Xcode 15)
  • ~25GB free disk space
  • Apple ID (free)

2. Install Xcode Command Line Tools

# Install command line tools
xcode-select --install

# Verify installation
xcode-select -p
# Should output: /Applications/Xcode.app/Contents/Developer

# If you have multiple Xcode versions
sudo xcode-select --switch /Applications/Xcode.app

3. Install CocoaPods

CocoaPods is the dependency manager for iOS native dependencies — it is to iOS what Gradle is to Android. Every time you install a React Native library that includes native iOS code (camera, maps, push notifications), CocoaPods links those native modules into your Xcode project. If you skip pod install after adding a library, the JavaScript side will try to call native code that does not exist, resulting in a “module not found” crash at runtime.
# Install CocoaPods using Ruby gem
sudo gem install cocoapods

# Or using Homebrew (recommended)
brew install cocoapods

# Verify installation
pod --version

# Setup CocoaPods (first time only)
pod setup

4. Install iOS Simulator

# Open Xcode
open -a Xcode

# Go to: Xcode → Settings → Platforms
# Click '+' and install iOS simulators

# Or via command line
xcodebuild -downloadPlatform iOS

# List available simulators
xcrun simctl list devices
Watchman improves file watching performance:
# Install via Homebrew
brew install watchman

# Verify installation
watchman --version

iOS Setup Verification

# Create a test project
npx react-native@latest init TestProject
cd TestProject

# Run on iOS simulator
npx react-native run-ios

# Or with Expo
npx create-expo-app@latest test-expo
cd test-expo
npx expo run:ios

Android Setup (All Platforms)

1. Install Java Development Kit (JDK)

React Native requires JDK 17. Android builds use Gradle, which compiles your Java/Kotlin native code and packages the JavaScript bundle into an APK or AAB. The JDK version must match what Gradle expects — using JDK 11 or JDK 21 instead of 17 will produce cryptic build failures. This is one of the most common Android setup pitfalls: the version mismatch error messages rarely tell you “wrong JDK version” directly.
# Using Homebrew
brew install openjdk@17

# Add to PATH (add to ~/.zshrc or ~/.bashrc)
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
export PATH=$JAVA_HOME/bin:$PATH

# Verify
java -version

2. Install Android Studio

Download Android Studio from developer.android.com/studio During installation, ensure these are selected:
  • Android SDK
  • Android SDK Platform
  • Android Virtual Device (AVD)

3. Configure Android SDK

# Open Android Studio
# Go to: More Actions → SDK Manager (or Settings → Languages & Frameworks → Android SDK)

# SDK Platforms tab - Install:
# - Android 14 (API 34) - or latest stable
# - Android 13 (API 33)

# SDK Tools tab - Install:
# - Android SDK Build-Tools 34.0.0
# - Android SDK Command-line Tools
# - Android Emulator
# - Android SDK Platform-Tools
# - Google Play services (optional)

4. Set Environment Variables

Add to ~/.zshrc or ~/.bashrc:
# Android SDK
export ANDROID_HOME=$HOME/Library/Android/sdk  # macOS
# export ANDROID_HOME=$HOME/Android/Sdk        # Linux

export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin

# Apply changes
source ~/.zshrc  # or source ~/.bashrc

# Verify
echo $ANDROID_HOME
adb --version

5. Create Android Virtual Device (AVD)

The Android emulator simulates a physical Android device on your computer. Unlike the iOS Simulator (which runs native ARM code directly on Apple Silicon), the Android emulator actually emulates ARM hardware, which is why hardware acceleration (Hyper-V on Windows, KVM on Linux, Hypervisor.framework on macOS) is critical for performance. Without hardware acceleration, the emulator can be 10-50x slower. A practical tip: choose a recent Pixel device image with Google Play services if you need to test Google Maps, Google Sign-In, or push notifications. System images without Google APIs will not have these services available.
# Open Android Studio
# Go to: More Actions → Virtual Device Manager

# Click "Create Device"
# 1. Select hardware: Pixel 7 (or similar)
# 2. Select system image: API 34 (download if needed)
# 3. Name your AVD and finish

# Or via command line
# List available system images
sdkmanager --list | grep system-images

# Download system image
sdkmanager "system-images;android-34;google_apis;x86_64"

# Create AVD
avdmanager create avd -n Pixel_7_API_34 -k "system-images;android-34;google_apis;x86_64" -d "pixel_7"

# List AVDs
emulator -list-avds

# Start emulator
emulator -avd Pixel_7_API_34

6. Enable Hardware Acceleration

Hardware acceleration is enabled by default on macOS with Apple Silicon or Intel HAXM.

Android Setup Verification

# Create a test project
npx react-native@latest init TestProject
cd TestProject

# Start Android emulator (or connect physical device)
emulator -avd Pixel_7_API_34

# Run on Android
npx react-native run-android

# Or with Expo
npx create-expo-app@latest test-expo
cd test-expo
npx expo run:android

VS Code Setup

Install VS Code

Download from code.visualstudio.com

Essential Extensions

These extensions transform VS Code into a capable React Native IDE. The React Native Tools extension gives you inline debugging, and the Expo Tools extension provides autocomplete for app.json configuration (where a single typo can cause silent build failures).
// .vscode/extensions.json
{
  "recommendations": [
    // React Native -- provides launch configs, inline debugging, and IntelliSense for RN APIs
    "msjsdiag.vscode-react-native",
    // Expo -- autocomplete for app.json/app.config.ts, diagnostics for Expo SDK compatibility
    "expo.vscode-expo-tools",
    
    // JavaScript/TypeScript
    "dsznajder.es7-react-js-snippets",
    "dbaeumer.vscode-eslint",
    "esbenp.prettier-vscode",
    
    // Productivity
    "formulahendry.auto-rename-tag",
    "christian-kohler.path-intellisense",
    "naumovs.color-highlight",
    "streetsidesoftware.code-spell-checker",
    
    // Git
    "eamodio.gitlens",
    "mhutchie.git-graph",
    
    // Testing
    "orta.vscode-jest",
    
    // Optional but useful
    "usernamehw.errorlens",
    "gruntfuggly.todo-tree",
    "wayou.vscode-todo-highlight"
  ]
}

VS Code Settings

// .vscode/settings.json
{
  // Editor
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit",
    "source.organizeImports": "explicit"
  },
  "editor.tabSize": 2,
  "editor.wordWrap": "on",
  
  // TypeScript
  "typescript.preferences.importModuleSpecifier": "relative",
  "typescript.suggest.autoImports": true,
  "typescript.updateImportsOnFileMove.enabled": "always",
  
  // Files
  "files.associations": {
    "*.js": "javascriptreact",
    "*.ts": "typescriptreact"
  },
  "files.exclude": {
    "**/.git": true,
    "**/node_modules": true,
    "**/.expo": true,
    "**/ios/Pods": true
  },
  
  // Emmet
  "emmet.includeLanguages": {
    "javascript": "javascriptreact",
    "typescript": "typescriptreact"
  },
  
  // React Native
  "react-native.packager.port": 8081,
  
  // ESLint
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact"
  ]
}

Launch Configuration

// .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Android",
      "cwd": "${workspaceFolder}",
      "type": "reactnative",
      "request": "launch",
      "platform": "android"
    },
    {
      "name": "Debug iOS",
      "cwd": "${workspaceFolder}",
      "type": "reactnative",
      "request": "launch",
      "platform": "ios"
    },
    {
      "name": "Attach to packager",
      "cwd": "${workspaceFolder}",
      "type": "reactnative",
      "request": "attach"
    },
    {
      "name": "Debug Expo",
      "cwd": "${workspaceFolder}",
      "type": "reactnative",
      "request": "launch",
      "platform": "exponent"
    }
  ]
}

Physical Device Setup

iOS Physical Device

# 1. Connect iPhone via USB
# 2. Trust the computer on your iPhone
# 3. Open Xcode → Window → Devices and Simulators
# 4. Select your device and enable "Connect via network" (optional)

# For development builds
# 1. Sign in with Apple ID in Xcode
# 2. Select your team in project settings
# 3. Enable "Automatically manage signing"

# Run on device
npx react-native run-ios --device "Your iPhone Name"

# Or with Expo
npx expo run:ios --device

Android Physical Device

# 1. Enable Developer Options on your Android device
#    Settings → About Phone → Tap "Build Number" 7 times

# 2. Enable USB Debugging
#    Settings → Developer Options → USB Debugging → Enable

# 3. Connect via USB and accept the debugging prompt

# 4. Verify device is connected
adb devices
# Should show your device

# Run on device
npx react-native run-android

# Or with Expo
npx expo run:android --device

Wireless Debugging (Android 11+)

# 1. Enable Wireless debugging in Developer Options
# 2. Pair device with pairing code
adb pair <IP>:<PORT>
# Enter pairing code when prompted

# 3. Connect to device
adb connect <IP>:<PORT>

# 4. Verify connection
adb devices

Troubleshooting

Common Issues

# Install React Native CLI globally
npm install -g react-native-cli

# Or use npx (recommended)
npx react-native <command>
# Clear CocoaPods cache
cd ios
pod cache clean --all
rm -rf Pods Podfile.lock
pod install --repo-update

# If still failing, try:
sudo gem install cocoapods
pod setup
# Create local.properties in android folder
echo "sdk.dir=$ANDROID_HOME" > android/local.properties

# Or on Windows
echo sdk.dir=C:\\Users\\YOUR_USERNAME\\AppData\\Local\\Android\\Sdk > android\local.properties
# Clear emulator data
emulator -avd YOUR_AVD_NAME -wipe-data

# Or increase emulator storage in AVD settings
# Kill process on port 8081
# macOS/Linux
lsof -i :8081 | grep LISTEN | awk '{print $2}' | xargs kill -9

# Windows
netstat -ano | findstr :8081
taskkill /PID <PID> /F

# Or use different port
npx react-native start --port 8082
# Clear Metro cache
npx react-native start --reset-cache

# Clear watchman
watchman watch-del-all

# Clear npm cache
npm cache clean --force

# Reinstall dependencies
rm -rf node_modules
npm install
# 1. Open project in Xcode
open ios/YourProject.xcworkspace

# 2. Select your project in navigator
# 3. Go to Signing & Capabilities
# 4. Select your Team
# 5. Enable "Automatically manage signing"
# 6. Change Bundle Identifier if needed

Clean Build Commands

# Full clean (nuclear option)
# Stop Metro
# Close simulators/emulators

# Clean watchman
watchman watch-del-all

# Clean Metro cache
rm -rf $TMPDIR/metro-*
rm -rf $TMPDIR/haste-map-*

# Clean node modules
rm -rf node_modules
npm install  # or yarn

# Clean iOS
cd ios
rm -rf Pods Podfile.lock build
pod install --repo-update
cd ..

# Clean Android
cd android
./gradlew clean
cd ..

# Restart Metro
npx react-native start --reset-cache

Environment Verification Script

Create a script to verify your setup:
#!/bin/bash
# save as verify-setup.sh

echo "🔍 Checking React Native Development Environment..."
echo ""

# Node.js
echo "📦 Node.js:"
node --version 2>/dev/null || echo "❌ Node.js not installed"
npm --version 2>/dev/null || echo "❌ npm not installed"
echo ""

# Watchman
echo "👀 Watchman:"
watchman --version 2>/dev/null || echo "⚠️ Watchman not installed (optional)"
echo ""

# Java
echo "☕ Java:"
java -version 2>&1 | head -n 1 || echo "❌ Java not installed"
echo ""

# Android
echo "🤖 Android:"
if [ -n "$ANDROID_HOME" ]; then
  echo "ANDROID_HOME: $ANDROID_HOME"
  adb --version 2>/dev/null | head -n 1 || echo "❌ adb not found"
else
  echo "❌ ANDROID_HOME not set"
fi
echo ""

# iOS (macOS only)
if [[ "$OSTYPE" == "darwin"* ]]; then
  echo "🍎 iOS:"
  xcodebuild -version 2>/dev/null || echo "❌ Xcode not installed"
  pod --version 2>/dev/null && echo "CocoaPods: $(pod --version)" || echo "❌ CocoaPods not installed"
  echo ""
fi

# React Native CLI
echo "⚛️ React Native:"
npx react-native --version 2>/dev/null || echo "Using npx for React Native CLI"
echo ""

echo "✅ Verification complete!"
Run with:
chmod +x verify-setup.sh
./verify-setup.sh

Quick Reference

Essential Commands

# Create new project
npx create-expo-app@latest my-app          # Expo
npx react-native@latest init MyApp          # CLI

# Start development
npx expo start                              # Expo
npx react-native start                      # CLI

# Run on platforms
npx expo run:ios                            # Expo iOS
npx expo run:android                        # Expo Android
npx react-native run-ios                    # CLI iOS
npx react-native run-android                # CLI Android

# Clean and rebuild
npx expo start --clear                      # Expo
npx react-native start --reset-cache        # CLI

# Install dependencies
npx expo install <package>                  # Expo (ensures compatibility)
npm install <package>                       # CLI

Mobile Dev Setup Pitfalls

Common environment pitfalls that waste hours:iOS-specific:
  • Xcode updates frequently break CocoaPods caches. After any Xcode update, run pod deintegrate && pod install --repo-update in your ios/ folder.
  • If you see 'React/RCTBridgeModule.h' file not found, it almost always means CocoaPods failed to link properly. A clean pod install (delete Pods/ and Podfile.lock first) fixes it 95% of the time.
  • Running pod install with the wrong Ruby version can silently install incompatible pod versions. Use the system Ruby or rbenv to pin your Ruby version.
Android-specific:
  • The ANDROID_HOME environment variable must point to the SDK location, not Android Studio itself. On macOS it is ~/Library/Android/sdk, on Windows it is %LOCALAPPDATA%\Android\Sdk. Getting this wrong produces “SDK not found” errors.
  • Gradle daemon processes can hold stale caches. If Android builds fail mysteriously after upgrading a dependency, try cd android && ./gradlew --stop && ./gradlew clean.
  • The Android emulator requires significant RAM (2-4 GB per instance). If your machine has 8 GB total, expect slowdowns when running both an emulator and Metro simultaneously.
Cross-platform:
  • Running npm install and yarn install in the same project creates conflicting lock files (package-lock.json vs yarn.lock). Pick one package manager and stick with it.
  • Metro bundler defaults to port 8081. If another process (like McAfee on Windows) is using that port, Metro fails silently or with a confusing error. Use npx react-native start --port 8082 as a workaround.

Next Steps

Module 3: Project Structure

Learn how to organize your React Native project for scalability and maintainability

Interview Deep-Dive

Strong Answer:
  • They cannot run Xcode or iOS simulators on Windows — Apple restricts those to macOS. But they have three viable options. First, EAS Build runs iOS builds in the cloud on Apple silicon machines. The developer writes code on Windows, pushes to a branch, and EAS compiles the iOS build remotely.
  • Second, for on-device testing during development, they can use Expo Go on a physical iPhone. They run npx expo start on Windows, scan the QR code, and Expo Go loads the JS bundle over the network.
  • Third, for native debugging they can use cloud Mac services (MacStadium, AWS EC2 Mac instances) or pair with a macOS-using teammate for iOS-specific issues.
  • What I would not recommend: Hackintosh setups or assuming “it will work on iOS too” based on Android-only testing. Platform differences in keyboard handling, safe areas, and gesture navigation will surface in production.
Follow-up: The same developer reports that their Android emulator runs at 5fps on their Windows machine. How do you diagnose this?Follow-up Answer:
  • The number one cause is missing hardware acceleration. Check if Hyper-V or HAXM is enabled via systeminfo in PowerShell. If “Virtualization Enabled in Firmware” says No, they need to enable VT-x (Intel) or SVM (AMD) in BIOS.
  • Second: verify the system image architecture. Use x86_64 images on Intel hosts and arm64-v8a on ARM-based Windows. Mismatched architectures force software emulation, which is 10-50x slower.
  • Third: allocate at least 2GB RAM and 2 CPU cores in AVD Manager, and enable GPU acceleration (Hardware GLES 2.0).
  • If all else fails, use a physical Android device via USB. It is faster, shows real-world performance, and avoids emulator configuration entirely.
Strong Answer:
  • CocoaPods is the dependency manager for iOS, analogous to npm for JavaScript. Running pod install reads the Podfile, resolves version constraints, downloads native dependency source code, and generates an Xcode workspace that links everything. React Native itself is a CocoaPod, along with every native module.
  • Debugging failures depends on the error. “CDN: trunk URL could not be downloaded”: run pod repo update. “Specs satisfying dependency were not found”: a version conflict — check Podfile.lock for pins. “No podspec found for library”: the RN library was not properly linked — ensure npx pod-install ran after npm install.
  • The nuclear option: cd ios && rm -rf Pods Podfile.lock build && pod cache clean --all && pod install --repo-update. This clears all cached state and rebuilds from scratch.
  • Critical production practice: commit Podfile.lock to version control. Without it, different team members resolve different dependency versions, causing “works on my machine” failures. Treat it like package-lock.json.
Follow-up: Your CI pipeline fails with “The sandbox is not in sync with the Podfile.lock.” What does this mean?Follow-up Answer:
  • The Xcode project sandbox does not match the committed Podfile.lock. Someone updated a pod locally but CI has a stale Pods/ cache.
  • Fix: ensure CI runs cd ios && pod install after npm ci and before the Xcode build. Do not cache Pods/ without also keying on Podfile.lock.
  • Preventive measure: use pod install --deployment in CI, which fails if Podfile was modified without updating Podfile.lock, catching desync issues early.
Strong Answer:
  • First, check if an Expo config plugin already exists for the SDK. Config plugins modify native files (AndroidManifest, MainApplication, Info.plist) at build time without maintaining native code in your repository.
  • If no plugin exists, write a custom config plugin — a JavaScript function that receives the Expo config and returns modified native configuration. This is the modern replacement for ejecting.
  • If the SDK requires runtime native code, create a local Expo module using expo-modules-core. Write Swift/Kotlin that integrates with the Expo module system while keeping the managed workflow.
  • As a last resort, switch to development builds (npx expo run:android) which gives you the android/ directory while still using Expo’s module system. This is not ejecting — you retain EAS Build and EAS Update support.
Follow-up: The custom config plugin works locally but fails in EAS Build. How do you debug cloud build issues?Follow-up Answer:
  • EAS Build runs in a clean environment, so the failure likely involves environment differences. First, check the EAS Build logs for the exact error (they are available in the Expo dashboard).
  • Common causes: the config plugin references a local file path that does not exist in CI, or it depends on an environment variable not set in EAS secrets. Use eas build --local to reproduce the cloud build environment locally.
  • Add console.log statements in your config plugin — they appear in the build logs. Use the withDangerousMod modifier to inspect the generated native files mid-build and verify your modifications are applied correctly.