> ## 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.

# 02. Environment Setup

> Complete development environment setup for React Native on macOS, Windows, and Linux

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/devweeekends/images/courses/react-native-crash-course/environment-setup.svg" alt="Environment Setup" />
</Frame>

## Module Overview

<Info>
  **Estimated Time**: 1-2 hours | **Difficulty**: Beginner | **Prerequisites**: Module 1 completed
</Info>

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.                             │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
```

<Tabs>
  <Tab title="Choose Expo If">
    * 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
  </Tab>

  <Tab title="Choose CLI If">
    * Integrating into existing native app
    * Need specific native SDKs immediately
    * Have complex native requirements
    * Your team has native development experience
    * Building a brownfield app
  </Tab>
</Tabs>

***

## 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.

<Tabs>
  <Tab title="macOS">
    ```bash theme={null}
    # 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
    ```
  </Tab>

  <Tab title="Windows">
    ```powershell theme={null}
    # Option 1: Download installer from nodejs.org
    # https://nodejs.org/en/download/

    # Option 2: Using Chocolatey
    choco install nodejs-lts

    # Option 3: Using nvm-windows
    # Download from: https://github.com/coreybutler/nvm-windows/releases
    nvm install 20
    nvm use 20

    # Verify installation
    node --version
    npm --version
    ```
  </Tab>

  <Tab title="Linux">
    ```bash theme={null}
    # Using nvm (recommended)
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
    source ~/.bashrc
    nvm install 20
    nvm use 20
    nvm alias default 20

    # Or using NodeSource
    curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
    sudo apt-get install -y nodejs

    # Verify installation
    node --version
    npm --version
    ```
  </Tab>
</Tabs>

### 2. Install a Package Manager

<Tabs>
  <Tab title="npm (Default)">
    npm comes with Node.js. No additional installation needed.

    ```bash theme={null}
    # Verify npm
    npm --version

    # Update npm (optional)
    npm install -g npm@latest
    ```
  </Tab>

  <Tab title="Yarn">
    ```bash theme={null}
    # Install Yarn globally
    npm install -g yarn

    # Verify installation
    yarn --version
    ```
  </Tab>

  <Tab title="pnpm (Fastest)">
    ```bash theme={null}
    # Install pnpm globally
    npm install -g pnpm

    # Verify installation
    pnpm --version
    ```
  </Tab>
</Tabs>

### 3. Install Git

<Tabs>
  <Tab title="macOS">
    ```bash theme={null}
    # Git comes with Xcode Command Line Tools
    xcode-select --install

    # Or using Homebrew
    brew install git

    # Verify
    git --version
    ```
  </Tab>

  <Tab title="Windows">
    ```powershell theme={null}
    # Download from https://git-scm.com/download/win
    # Or using Chocolatey
    choco install git

    # Verify
    git --version
    ```
  </Tab>

  <Tab title="Linux">
    ```bash theme={null}
    # Ubuntu/Debian
    sudo apt-get install git

    # Fedora
    sudo dnf install git

    # Verify
    git --version
    ```
  </Tab>
</Tabs>

***

## Expo Setup

### Quick Start with Expo

```bash theme={null}
# 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:

<CardGroup cols={2}>
  <Card title="iOS" icon="apple" href="https://apps.apple.com/app/expo-go/id982107779">
    Download from App Store
  </Card>

  <Card title="Android" icon="android" href="https://play.google.com/store/apps/details?id=host.exp.exponent">
    Download from Google Play
  </Card>
</CardGroup>

### Running Your App

```bash theme={null}
# 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:

```bash theme={null}
# 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)

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

### 1. Install Xcode

```bash theme={null}
# 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

```bash theme={null}
# 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.

```bash theme={null}
# 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

```bash theme={null}
# 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
```

### 5. Install Watchman (Recommended)

Watchman improves file watching performance:

```bash theme={null}
# Install via Homebrew
brew install watchman

# Verify installation
watchman --version
```

### iOS Setup Verification

```bash theme={null}
# 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.

<Tabs>
  <Tab title="macOS">
    ```bash theme={null}
    # 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
    ```
  </Tab>

  <Tab title="Windows">
    ```powershell theme={null}
    # Download from Microsoft
    # https://learn.microsoft.com/en-us/java/openjdk/download

    # Or using Chocolatey
    choco install microsoft-openjdk17

    # Set JAVA_HOME environment variable
    # System Properties → Environment Variables → New
    # Variable: JAVA_HOME
    # Value: C:\Program Files\Microsoft\jdk-17.x.x

    # Verify
    java -version
    ```
  </Tab>

  <Tab title="Linux">
    ```bash theme={null}
    # Ubuntu/Debian
    sudo apt install openjdk-17-jdk

    # Fedora
    sudo dnf install java-17-openjdk-devel

    # Set JAVA_HOME (add to ~/.bashrc)
    export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
    export PATH=$JAVA_HOME/bin:$PATH

    # Verify
    java -version
    ```
  </Tab>
</Tabs>

### 2. Install Android Studio

Download Android Studio from [developer.android.com/studio](https://developer.android.com/studio)

During installation, ensure these are selected:

* Android SDK
* Android SDK Platform
* Android Virtual Device (AVD)

### 3. Configure Android SDK

```bash theme={null}
# 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

<Tabs>
  <Tab title="macOS/Linux">
    Add to `~/.zshrc` or `~/.bashrc`:

    ```bash theme={null}
    # 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
    ```
  </Tab>

  <Tab title="Windows">
    ```powershell theme={null}
    # Open System Properties → Environment Variables

    # Add new User variable:
    # Variable: ANDROID_HOME
    # Value: C:\Users\YOUR_USERNAME\AppData\Local\Android\Sdk

    # Edit Path variable, add:
    # %ANDROID_HOME%\emulator
    # %ANDROID_HOME%\platform-tools
    # %ANDROID_HOME%\tools
    # %ANDROID_HOME%\tools\bin

    # Restart terminal and verify
    echo %ANDROID_HOME%
    adb --version
    ```
  </Tab>
</Tabs>

### 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.

```bash theme={null}
# 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

<Tabs>
  <Tab title="macOS">
    Hardware acceleration is enabled by default on macOS with Apple Silicon or Intel HAXM.
  </Tab>

  <Tab title="Windows">
    ```powershell theme={null}
    # Enable Hyper-V (Windows 10/11 Pro)
    # Open PowerShell as Administrator
    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

    # Or enable Windows Hypervisor Platform
    Enable-WindowsOptionalFeature -Online -FeatureName HypervisorPlatform -All

    # Restart computer

    # For AMD processors, enable SVM in BIOS
    # For Intel processors, enable VT-x in BIOS
    ```
  </Tab>

  <Tab title="Linux">
    ```bash theme={null}
    # Install KVM
    sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils

    # Add user to kvm group
    sudo adduser $USER kvm

    # Verify KVM
    kvm-ok

    # Logout and login for group changes
    ```
  </Tab>
</Tabs>

### Android Setup Verification

```bash theme={null}
# 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](https://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).

```json theme={null}
// .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

```json theme={null}
// .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

```json theme={null}
// .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

```bash theme={null}
# 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

```bash theme={null}
# 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+)

```bash theme={null}
# 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

<AccordionGroup>
  <Accordion title="'react-native' command not found">
    ```bash theme={null}
    # Install React Native CLI globally
    npm install -g react-native-cli

    # Or use npx (recommended)
    npx react-native <command>
    ```
  </Accordion>

  <Accordion title="iOS: 'pod install' fails">
    ```bash theme={null}
    # 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
    ```
  </Accordion>

  <Accordion title="Android: 'SDK location not found'">
    ```bash theme={null}
    # 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
    ```
  </Accordion>

  <Accordion title="Android: 'INSTALL_FAILED_INSUFFICIENT_STORAGE'">
    ```bash theme={null}
    # Clear emulator data
    emulator -avd YOUR_AVD_NAME -wipe-data

    # Or increase emulator storage in AVD settings
    ```
  </Accordion>

  <Accordion title="Metro bundler port in use">
    ```bash theme={null}
    # 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
    ```
  </Accordion>

  <Accordion title="'Unable to load script' error">
    ```bash theme={null}
    # 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
    ```
  </Accordion>

  <Accordion title="Xcode build fails with signing error">
    ```bash theme={null}
    # 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
    ```
  </Accordion>
</AccordionGroup>

### Clean Build Commands

```bash theme={null}
# 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:

```bash theme={null}
#!/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:

```bash theme={null}
chmod +x verify-setup.sh
./verify-setup.sh
```

***

## Quick Reference

### Essential Commands

```bash theme={null}
# 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

<Warning>
  **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.
</Warning>

***

## Next Steps

<Card title="Module 3: Project Structure" icon="arrow-right" href="/courses/react-native-crash-course/03-project-structure">
  Learn how to organize your React Native project for scalability and maintainability
</Card>

***

## Interview Deep-Dive

<AccordionGroup>
  <Accordion title="A new developer on your team is on Windows and needs to develop and test iOS builds. What are their options?">
    **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.
  </Accordion>

  <Accordion title="Explain the role of CocoaPods in React Native iOS builds. What happens when pod install fails?">
    **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.
  </Accordion>

  <Accordion title="Your team uses Expo but needs to integrate a native SDK that modifies MainApplication.java. What are your options without ejecting?">
    **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.
  </Accordion>
</AccordionGroup>
