WSL2 + Expo Development Environment Setup Guide

Prerequisites Confirmed

  • ✅ WSL2 with Ubuntu 24.04 LTS
  • ✅ VS Code with WSL extension
  • ✅ iPhone for primary testing
  • 🔄 Node.js/npm/nvm (to be installed)

Phase 1: Core Development Tools Setup

1.1 Install Node.js via NVM

First, let’s install nvm (Node Version Manager) for better Node.js version control:

# Update package lists
sudo apt update && sudo apt upgrade -y

# Install curl if not present
sudo apt install curl -y

# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

# Reload your shell configuration
source ~/.bashrc

# Verify nvm installation
nvm --version

Now install Node.js (LTS version recommended for Expo):

# Install latest LTS Node.js
nvm install --lts

# Set as default
nvm alias default node

# Verify installation
node --version
npm --version

1.2 Install Git and Configure

# Install Git
sudo apt install git -y

# Configure Git (replace with your info)
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"

# Configure Git to handle line endings properly between Windows and Linux
git config --global core.autocrlf input
# Install Expo CLI globally
npm install -g expo-cli @expo/cli

# Install EAS CLI for future deployment
npm install -g eas-cli

# Verify installation
expo --version

1.4 Additional Development Tools

# Install build essentials (needed for some npm packages)
sudo apt install build-essential -y

# Install watchman for better file watching performance (optional but recommended)
sudo apt install watchman -y

Phase 2: Project Directory Structure

2.1 Create Project Directory in WSL2 Filesystem

# Create project root directory
mkdir -p ~/projects/game-platform
cd ~/projects/game-platform

# Create sub-directories
mkdir mobile-app backend shared-types docs

# Verify structure
tree -L 2

2.2 Initialize Expo Project

# Navigate to mobile-app directory
cd ~/projects/game-platform/mobile-app

# Create new Expo project with TypeScript
npx create-expo-app . --template blank-typescript

# Install additional dependencies
npm install @supabase/supabase-js expo-secure-store expo-router

Phase 3: Network Configuration for Physical Device Testing

3.1 Find Your WSL2 IP Address

Create a helper script to easily get your WSL2 IP:

# Create a script file
echo '#!/bin/bash
echo "WSL2 IP: $(hostname -I | awk '"'"'{print $1}'"'"')"
echo "Windows IP: $(ip route | grep default | awk '"'"'{print $3}'"'"')"' > ~/get-wsl-ip.sh

# Make it executable
chmod +x ~/get-wsl-ip.sh

# Run it
~/get-wsl-ip.sh

3.2 Configure Windows Firewall

You’ll need to allow incoming connections to WSL2. Run this in Windows PowerShell as Administrator:

# Create firewall rule for Expo (port 8081)
New-NetFirewallRule -DisplayName "WSL2 Expo Dev Server" -Direction Inbound -Protocol TCP -LocalPort 8081 -Action Allow

# Create firewall rule for Metro bundler (port 19000-19006)
New-NetFirewallRule -DisplayName "WSL2 Metro Bundler" -Direction Inbound -Protocol TCP -LocalPort 19000-19006 -Action Allow

3.3 Create Port Forwarding Script

Create a script to forward ports from Windows to WSL2:

# Create the script in your home directory
cat > ~/forward-ports.sh << 'EOF'
#!/bin/bash
# Get WSL2 IP
WSL_IP=$(hostname -I | awk '{print $1}')
WINDOWS_IP=$(ip route | grep default | awk '{print $3}')

echo "Forwarding ports from Windows ($WINDOWS_IP) to WSL2 ($WSL_IP)..."

# Run in Windows (you'll need to copy and run these commands in Windows PowerShell as Admin)
echo "Run these commands in Windows PowerShell as Administrator:"
echo ""
echo "netsh interface portproxy add v4tov4 listenport=8081 listenaddress=0.0.0.0 connectport=8081 connectaddress=$WSL_IP"
echo "netsh interface portproxy add v4tov4 listenport=19000 listenaddress=0.0.0.0 connectport=19000 connectaddress=$WSL_IP"
echo "netsh interface portproxy add v4tov4 listenport=19001 listenaddress=0.0.0.0 connectport=19001 connectaddress=$WSL_IP"
echo ""
echo "To check existing rules: netsh interface portproxy show all"
echo "To remove a rule: netsh interface portproxy delete v4tov4 listenport=8081 listenaddress=0.0.0.0"
EOF

chmod +x ~/forward-ports.sh

Phase 4: Expo Development Configuration

4.1 Configure Expo for WSL2

Create a custom Expo start script that handles WSL2 networking:

cd ~/projects/game-platform/mobile-app

# Create a start script
cat > start-expo.sh << 'EOF'
#!/bin/bash
# Get the WSL2 IP address
WSL_IP=$(hostname -I | awk '{print $1}')

echo "Starting Expo on WSL2 IP: $WSL_IP"
echo "Make sure your phone is on the same WiFi network!"
echo ""

# Set the React Native packager hostname
export REACT_NATIVE_PACKAGER_HOSTNAME=$WSL_IP

# Start Expo
npx expo start --host tunnel
EOF

chmod +x start-expo.sh

4.2 Alternative: Use Expo Tunnel (Easier but Slower)

If port forwarding is problematic, you can use Expo’s tunnel feature:

# Install ngrok globally (used by Expo for tunneling)
npm install -g @expo/ngrok

# Start Expo with tunnel
npx expo start --tunnel

Phase 5: VS Code Configuration

Install these extensions in VS Code (in WSL2 mode):

# Open VS Code in your project
cd ~/projects/game-platform/mobile-app
code .

Then install:

  • React Native Tools
  • Expo Tools
  • TypeScript React code snippets
  • Prettier - Code formatter
  • ESLint

5.2 VS Code Settings for WSL2

Create workspace settings:

{
  "files.watcherExclude": {
    "**/node_modules/**": true,
    "**/.git/**": true
  },
  "search.exclude": {
    "**/node_modules": true,
    "**/android": true,
    "**/ios": true
  },
  "typescript.tsdk": "node_modules/typescript/lib",
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

Phase 6: Testing Your Setup

6.1 Create a Test App

cd ~/projects/game-platform/mobile-app

# Replace App.tsx with a simple test
cat > App.tsx << 'EOF'
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>Hello from WSL2 + Expo! 🚀</Text>
      <Text style={styles.subtext}>If you can see this on your phone, everything is working!</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  text: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 10,
  },
  subtext: {
    fontSize: 16,
    color: '#666',
    textAlign: 'center',
    paddingHorizontal: 20,
  },
});
EOF

6.2 Start Development Server

# Option 1: Using the custom script (recommended)
./start-expo.sh

# Option 2: Using tunnel (easier but slower)
npx expo start --tunnel

6.3 Connect Your iPhone

  1. Install “Expo Go” from the App Store
  2. Make sure your phone is on the same WiFi as your computer
  3. Scan the QR code shown in the terminal
  4. You should see the test app load on your phone!

Troubleshooting Tips

If Expo Go Can’t Connect:

  1. Check WSL2 IP: Run ~/get-wsl-ip.sh and make sure you’re using the correct IP
  2. Firewall Issues: Temporarily disable Windows Firewall to test
  3. Use Tunnel Mode: Run npx expo start --tunnel as a fallback
  4. Restart WSL2: In PowerShell: wsl --shutdown then restart Ubuntu

If File Watching Doesn’t Work:

# Increase file watcher limit
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

If Performance is Slow:

  • Ensure your project is in WSL2 filesystem (~/projects/), not /mnt/c/
  • Close unnecessary applications
  • Consider using npx expo start --no-dev --minify for production-like performance

Next Steps

  1. Set up TypeScript configuration
  2. Configure Expo Router for navigation
  3. Set up Supabase authentication
  4. Create WebSocket service for real-time features

Quick Reference Commands

# Start Expo development
cd ~/projects/game-platform/mobile-app && ./start-expo.sh

# Check WSL2 IP
~/get-wsl-ip.sh

# Install new packages
npm install package-name

# Clear Expo cache
npx expo start --clear

# Build for production (later)
eas build --platform ios --profile preview

Ready to start building your cross-platform gaming app! 🎮


Back to top

Copyright © 2025 Your Name. Distributed under an MIT license.