Week 1: Expo vs. Bare Workflow & Your First App

This course assumes you're already comfortable with React — JSX, hooks, component composition. This week is the on-ramp to mobile specifically: choosing between Expo and a bare workflow, understanding the project structure and Metro bundler underneath either choice, and getting a real app running on an actual device or simulator.

Phase 1 of 8 Week 1 of 22 ~3–4 Hours Hands-on Exercise Included

By the end of this week, you'll be able to

  • Explain the difference between Expo Go and a bare React Native workflow, and choose correctly
  • Navigate a React Native project's structure & understand what Metro does
  • Run a React Native app on iOS Simulator, Android Emulator & a physical device

1. Expo vs. Bare Workflow

React Native itself is a library for building native iOS/Android apps with React — but almost nobody starts a project with it directly. Two practical starting points exist, and the choice between them matters from day one:

  • Expo (managed workflow) — a toolchain and set of libraries wrapped around React Native. Handles native build configuration, provides a huge library of pre-built native modules (camera, location, notifications), and lets you build and update apps without ever opening Xcode or Android Studio directly.
  • Bare React Native workflow — the raw framework, with native iOS/Android project folders you own and edit directly. More control, but you're responsible for native build configuration yourself.

This course uses Expo throughout — it removes an enormous amount of native-tooling friction while learning, and as of Expo SDK 51+, "ejecting" from managed Expo is no longer a one-way door: prebuild generates the native folders on demand whenever a project genuinely needs custom native code (covered in the Native Modules phase later in this course), so choosing Expo now doesn't lock you out of anything later.

"Expo apps aren't real native apps" is outdated

This was true years ago; it isn't anymore. An Expo app compiles to a genuine native iOS/Android binary — the same output a bare workflow produces. The difference is entirely in the development and build tooling around it, not in what ships to users.

2. Creating a Project

Install the tooling and scaffold a new project:

terminal
npx create-expo-app@latest my-app --template blank-typescript
cd my-app

npx expo start

--template blank-typescript starts with TypeScript configured from the first line of code — this course uses TypeScript throughout, the same as it would be used in any serious React codebase. npx expo start launches the development server and prints a QR code plus a menu of ways to open the app.

3. Project Structure & Metro

A fresh Expo project's structure, and what actually matters in it:

project layout
my-app/
├── app.json          ← app name, icon, splash screen, native permissions
├── package.json
├── App.tsx            ← the entry component -- your app starts here
├── assets/            ← images, fonts
└── tsconfig.json

Metro is React Native's JavaScript bundler — the equivalent role Webpack or Vite plays for a web React app, but purpose-built for React Native's needs (bundling per-platform code, fast refresh during development, resolving .ios.tsx/.android.tsx file variants covered in Week 3). It's what npx expo start actually launches, watching your files and serving the current JS bundle to whichever device connects.

app.json — the essentials
{
  "expo": {
    "name": "My App",
    "slug": "my-app",
    "version": "1.0.0",
    "icon": "./assets/icon.png",
    "splash": { "image": "./assets/splash.png" },
    "ios": { "bundleIdentifier": "com.yourname.myapp" },
    "android": { "package": "com.yourname.myapp" }
  }
}

bundleIdentifier/package are your app's permanent unique ID on each store — worth setting deliberately now, since changing it later (once an app is published) is disruptive.

4. Running on a Device

Three ways to actually see the app running, in increasing order of fidelity:

terminal
# 1. Expo Go on a physical phone -- fastest to start, scan the QR code
npx expo start
# Scan the printed QR code with the Expo Go app (iOS/Android)

# 2. iOS Simulator (Mac only, requires Xcode)
npx expo start --ios

# 3. Android Emulator (requires Android Studio)
npx expo start --android

Expo Go is a pre-built native app (downloadable from either app store) that dynamically loads and runs your JS bundle — no native build step required at all while you're prototyping. It's the fastest possible loop for early development, though it can't load truly custom native code (that's what prebuild and a development build are for, once Native Modules week arrives).

Test on a real device early

Simulators/emulators are convenient, but touch interactions, real GPS, camera hardware, and actual performance only show up truthfully on a physical device. Get Expo Go on your own phone in Week 1 — you'll use it constantly for the rest of this course.

5. Your First Screen

App.tsx is the root component — this looks almost exactly like a web React component, with one crucial difference: there's no HTML. React Native has its own set of built-in components (covered fully next week), and <div>/ <span> simply don't exist here.

App.tsx
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Hello, React Native!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  title: {
    fontSize: 20,
    fontWeight: '600',
  },
});

View and Text are the two components you'll use more than any other in this course — View is the layout container (roughly a <div>'s job), Text is the only component allowed to contain literal text (unlike the web, plain text can't sit directly inside a View). Both get covered in full depth next week.

6. Hands-on Exercise

Hands-on

Scaffold a project and get it running on your own phone

The whole point of this week is proving the full loop works end to end before any real code gets written.

Requirements:

  1. Install the Expo Go app on your own phone (iOS or Android).
  2. Run npx create-expo-app@latest my-app --template blank-typescript and start it with npx expo start.
  3. Scan the QR code with Expo Go and confirm the default app loads on your phone.
  4. Edit app.json: set a real name, slug, and both bundleIdentifier and package using a domain-style ID you own or control (e.g. com.yourname.myapp).
  5. Edit App.tsx: change the text, background color, and font size, and confirm the change appears on your phone within a second or two (Fast Refresh) without manually reloading.
Hint

If the QR code scan fails to connect, your phone and computer need to be on the same Wi-Fi network — this is the single most common Week 1 setup issue.

7. Knowledge Check

Four quick questions. Expand each to check your answer.

Q1

Does choosing Expo now permanently prevent writing custom native code later?

No — that was true under the old "eject" model, but modern Expo's prebuild generates the native iOS/Android project folders on demand whenever custom native code is genuinely needed, without abandoning the rest of Expo's tooling. Starting with Expo is a low-risk default, not a one-way commitment.

Q2

What does Metro actually do?

It's React Native's JavaScript bundler — it watches your source files, bundles them (resolving platform-specific file variants along the way), and serves the current JS bundle to whichever device or simulator connects, refreshing it automatically as files change. It plays the same architectural role Webpack or Vite plays for a web React project, purpose-built for React Native's specific needs.

Q3

Why can't you write <div>Hello</div> directly in a React Native component the way you would on the web?

There's no HTML or DOM in React Native at all — <div>, <span> and every other HTML tag simply don't exist as components here. React Native ships its own set of built-in components (View, Text, and others covered next week) that render to real native iOS/Android UI elements instead of HTML.

Q4

Why does this lesson recommend testing on a real device early, rather than relying only on a simulator/emulator?

Simulators and emulators are convenient but don't perfectly represent reality — genuine touch interaction, real GPS/camera hardware, and true performance characteristics only show up accurately on physical hardware. Since this course covers real device APIs (camera, location, sensors) starting in Phase 3, having a physical test device from Week 1 avoids discovering simulator-only quirks late.