Expo Getting Started: Your First App from Zero to Launch
A complete Expo getting started guide. Learn to set up your environment, create a project, debug, build for iOS/Android, and accelerate with starter kits.

You're probably in one of two places right now. You've got an app idea and want it running on your phone today, or you've already tried a React Native setup and hit enough tooling friction to wonder if you picked the wrong stack.
Expo is usually the fastest way out of that stall. It gives you a modern path from blank folder to running app without forcing you to wire native iOS and Android tooling on day one. That matters when you're still validating the product, learning the ecosystem, or trying to ship an MVP without burning a week on setup mistakes.
Most Expo getting started guides stop the moment the sample app opens. That's useful, but it leaves a real gap. The hard part starts right after the QR scan: choosing the right runtime, debugging the first broken dependency, understanding when Expo Go is enough, and getting a project into a shape you can build and release.
Table of Contents
- Why Start Your App Journey with Expo
- Setting Up Your Development Environment
- Creating and Running Your First Project
- Debugging and Common Troubleshooting
- Building Your App for Production
- From 'Hello World' to a Real App with AppLighter
Why Start Your App Journey with Expo
If your goal is to build for iOS, Android, and web without juggling three separate starting points, Expo is the cleanest entry into the React Native ecosystem. The biggest advantage isn't just convenience. It's that Expo gives you one development loop from the start, so you can create a project, run it, scan a QR code, and iterate on a real device without front-loading native complexity.
That clarity matters even more because older tutorials still float around. Some still tell you to use expo init and the older expo-cli flow. A beginner guide published around that older model shows expo init MyFirstApp, then cd MyFirstApp, then expo start, while current Expo guidance has moved to npx create-expo-app@latest and npx expo start instead, which marks a real shift toward a more standardized project generator rather than the older CLI-led setup, as shown in this historical Expo starter comparison.
Why the newer workflow matters
The practical takeaway is simple. If you follow an old article, you can still learn concepts, but the commands and defaults may no longer match what you see on your machine.
That mismatch creates beginner confusion fast:
- Old command mismatch: You copy
expo initfrom a blog post, then wonder why current docs say something else. - Different defaults: Older starters often assume a project layout or dependency set that doesn't match today's generated app.
- Harder troubleshooting: When your terminal output differs from the guide, every error feels bigger than it is.
Practical rule: When you're learning Expo, trust current Expo docs for commands and trust older articles only for context.
Expo also sits in a useful middle ground. It removes a lot of setup pain, but it doesn't lock you out of serious app development. You can prototype quickly, then grow into more advanced workflows as your app adds auth, APIs, and native requirements. If you're still weighing trade-offs, this comparison of Expo vs React Native for app teams is worth reading before you commit to your stack.
Setting Up Your Development Environment
A clean environment saves you from the most annoying class of early problems. Most Expo getting started issues aren't really Expo problems. They're machine problems: conflicting Node versions, missing package tooling, simulator confusion, or trying to test on a device that isn't ready.
A modern developer workspace with a laptop displaying code, a coffee mug, and programming books on a desk.
Install the tools you actually need
Start with Node.js. Use a version manager like nvm instead of installing Node globally and forgetting about it. That gives you a controlled runtime for Expo projects and keeps future upgrades from breaking older work.
Then pick one package manager and stay consistent. npm is fine. Yarn is fine too. What causes pain is mixing lockfiles, switching habits per repo, or pasting commands from tutorials without noticing they assume a different package manager.
A practical baseline looks like this:
- Node via a version manager: Keeps your environment predictable across projects.
- One package manager: Use
npmor Yarn, but don't mix them casually. - VS Code or another solid editor: You want good TypeScript support, terminal access, and quick file navigation.
- Git from day one: Even for a throwaway prototype, commit early so experiments don't turn into unrecoverable edits.
If you like keeping setup checklists tight, AppLighter's own Expo environment setup guide is a useful machine-prep reference.
A good editor setup also pays off immediately. Install extensions for TypeScript, ESLint, and Prettier if your workflow uses them. You don't need a huge plugin stack. You need fast feedback when imports break, types drift, or formatting gets inconsistent.
Early discipline beats later cleanup. A small amount of environment setup prevents hours of debugging the wrong thing.
If your app will need onboarding flows later, it's also worth seeing how teams approach guided UI setup in adjacent React projects. A practical example is installing StepsKit with React, not because you should copy that exact stack into Expo immediately, but because it shows how much easier feature work becomes when installation patterns are explicit.
Prepare your test devices early
The next mistake is waiting too long to test on real hardware. Set up your targets before you write app logic.
Use this order:
- Phone first: Install Expo Go on your iPhone or Android device.
- Simulator second: If you're on a Mac, install Xcode so the iOS Simulator is available when you need it.
- Browser last: Web support is useful, but it shouldn't be your only validation path for a mobile app.
Why that order? Because a phone exposes reality faster. Touch behavior, safe areas, font scaling, and connection quirks all show up earlier on real hardware than in a desktop browser.
Here's the short version of what each target is good at:
| Target | Best use | Common trap |
|---|---|---|
| Physical phone | Real device checks, camera-style QR flow, touch validation | Assuming desktop and device behave the same |
| iOS Simulator | Fast iteration on Mac, layout debugging | Forgetting simulator success doesn't guarantee device success |
| Web browser | Quick UI checks, broad layout review | Treating web as proof your mobile app is solid |
Creating and Running Your First Project
The modern Expo starting point is straightforward. Current Expo documentation uses npx create-expo-app@latest to generate a new project, then guides you through choosing an Expo SDK version. In the tutorial flow, Expo shows SDK 54, and after project creation the docs tell you to start with npx expo start, scan the QR code, and press W to open the web app in a browser, which shows Expo's single workflow for iOS, Android, and web from the first run in the official create your first Expo app tutorial.
A person holding a smartphone displaying the text Hello World, representing the first step in app development.
Create the app with the current Expo workflow
Open your terminal and run:
npx create-expo-app@latest
That command scaffolds a fresh project using the current Expo generator. During setup, you may be prompted to choose options that shape the starter. Don't overthink the first project. Pick the standard path and get the app running before you start customizing.
Once the files are generated:
- Change into the project directory.
- Start the development server with
npx expo start. - Wait for the Metro server and QR code to appear.
This part matters more than it seems. That terminal session becomes your control center. When something fails, that output is often more useful than the red screen on your phone.
Understand what the starter gives you
A new Expo app is small on purpose. It's not trying to solve your architecture yet. It's giving you a working baseline with enough structure to edit screens, install packages, and verify that your environment works.
When I'm guiding junior developers, I usually tell them to inspect only a few things at first:
- Entry point files: Find the first screen that renders and make one visible text change.
- Package manifest: Skim dependencies so you know what the project starts with.
- Scripts: Check what commands are already available in
package.json. - Asset folders: Confirm where images and static files live before you start scattering them elsewhere.
Don't spend your first hour renaming folders and reorganizing everything. The immediate goal is feedback. Change text, save the file, and confirm the update lands on the target device.
If live reload works, your project is alive. Don't skip that small win. It confirms the toolchain is connected end to end.
Run the app on phone simulator and web
The QR code flow is one of Expo's best features for beginners because it removes a lot of ceremony. Open Expo Go on your phone, scan the QR code, and the app should load on-device.
You should also try the web target once, even if you're building mobile-first. In Expo's onboarding tutorial, pressing W launches the app in a browser. That's useful for quick checks, but don't confuse “works in browser” with “works as a mobile product.”
A practical testing rhythm looks like this:
- Use your phone for behavior: navigation taps, gestures, device feel
- Use simulator for speed: fast restarts, layout checks, repeated test flows
- Use web for sanity checks: shared logic, rough UI validation, quick feedback
After you've seen the starter app once, make a tiny code edit. Change a heading, background color, or button label. Save it and watch the update reflect without rebuilding the whole app. That fast loop is why Expo remains such a productive place to begin.
This walkthrough is worth keeping nearby if you want a second visual reference while you code:
What usually goes wrong on first run
The first-run failures are usually boring, which is good news because boring problems are fixable.
Here are the common ones:
- Wrong folder: You ran
npx expo startoutside the project directory. - Dependency install hiccup: The scaffold completed, but package installation failed unnoticed or partially.
- Phone and laptop aren't aligned: The QR code opens, but the device can't reach the dev server.
- You edited the wrong file: The app runs, but your visible change never appears.
When that happens, strip the problem down. Can the server start? Can the phone load the app? Can one small UI edit refresh? Answer those in order and you'll usually isolate the break quickly.
Debugging and Common Troubleshooting
Most Expo frustration starts when developers assume every runtime behaves the same. It doesn't. The biggest distinction early on is Expo Go versus a development build.
A practical startup pitfall is choosing the wrong runtime for the app's needs. Expo Go is described as a limited sandbox for quick evaluation, while a development build is recommended when the app needs native libraries or production-style App Store work. In the quickstart flow, the sequence is to create the project, install Expo Go on a phone, run npx expo start --go, scan the QR code, and verify live reload on-device. The main failure mode is trying to validate native-module features inside Expo Go, where those modules are not available, as covered in this Expo Go and development build quickstart video.
A comparison infographic showing best practices and common pitfalls for debugging React Native Expo applications.
Know when Expo Go is enough
Expo Go is excellent for the first stage of Expo getting started. It's fast, convenient, and perfect for proving that your JavaScript and UI loop are healthy.
But it is still a sandbox. That's the key mental model.
Use Expo Go when you're doing things like:
- Basic UI work: screens, layout, spacing, typography
- Simple app flows: navigation, forms, loading states
- Fast iteration: quick edits on a physical phone without extra setup
Move to a development build when you need:
- Native libraries beyond the Expo Go sandbox
- A runtime closer to production behavior
- More realistic testing for store-bound apps
If a package depends on native code and it isn't supported in Expo Go, no amount of refreshing will make it work there. That's not a bug in your component. It's the wrong runtime.
The fastest debug fix is often a runtime decision, not a code change.
Fix the failures that show up first
When a junior developer tells me “Expo is broken,” I usually ask for the exact failure class. That matters because the fix for a red screen is very different from the fix for a connectivity problem.
Use this quick diagnosis table:
| Symptom | Likely cause | First move |
|---|---|---|
| QR code scans but app won't load | Device can't reach the dev server | Check network, VPN, and firewall conditions |
| App loads, then crashes on a feature | Native dependency not available in Expo Go | Test in the correct runtime |
| Edit doesn't appear after save | Fast refresh stalled or wrong file edited | Confirm the edited screen is actually rendered |
| Terminal logs are noisy and unclear | Multiple issues layered together | Fix the first error in the stack, not the last one shown |
Network issues are especially common. Firewalls, VPNs, and restrictive Wi-Fi can break the device-to-laptop connection. If the app worked yesterday and suddenly won't connect, check the environment before rewriting code.
Syntax mistakes also waste a lot of time because they feel bigger than they are. A bad import path, wrong named export, or small typo can look like an Expo problem when it's just a normal JavaScript or TypeScript error.
Build a debugging habit early
Strong debugging in Expo is less about secret commands and more about sequence. Don't change five things at once. Change one variable, re-run, and observe.
A useful rhythm looks like this:
- Read the terminal first. Metro usually tells you more than the device screen.
- Reduce the problem. Remove the new package, comment out the new screen, or isolate the failing hook.
- Check runtime assumptions. Ask whether this feature belongs in Expo Go or a development build.
- Retest on the intended target. A fix on web or simulator doesn't always prove the phone path is solved.
When developers learn this habit early, Expo becomes much less mysterious. Most problems turn out to be environment, runtime, or import issues. That's good news because those are all teachable and repeatable to solve.
Building Your App for Production
Running an app locally is one milestone. Shipping it is another job entirely. In that context, Expo Application Services, usually shortened to EAS, becomes part of the conversation.
Expo's current recommended bootstrap also points toward modern delivery workflows. The official getting-started path recommends npx create-expo-app@latest --template default@sdk-56, and Expo positions this as the standard way to create a new app. For first-run testing, Expo pairs the project with Expo Go or EAS-based workflows depending on whether you need only a sandbox or native libraries, which is part of the official Expo project creation workflow.
What EAS changes in practice
Without EAS, you eventually run into the traditional native build world head-on. That means local build tooling, signing requirements, platform-specific setup, and a lot of room for machine-specific issues.
EAS smooths that handoff. In practice, it gives you a cleaner path from an Expo project to installable app artifacts without demanding that every developer become an iOS signing specialist or Android build systems expert on day one.
The key shift is this:
- Local development stays focused on product work
- Build and distribution concerns move into a clearer workflow
- Native complexity becomes something you manage intentionally, not something that ambushes you early
You'll typically install the EAS CLI, configure the project, and use eas build when you're ready to generate production-oriented builds.
Shipping starts before the build command. If app config, assets, environment variables, and bundle identity are sloppy, the build step just exposes the mess.
A production checklist before you build
Before you trigger any production build, check the boring details. They cause the most preventable release delays.
Use a checklist like this:
- App identity: Confirm package names and bundle identifiers are final enough to keep.
- Environment separation: Know which keys and endpoints belong to development versus production.
- Assets and metadata: Icons, splash assets, and app naming should be intentional, not starter leftovers.
- Feature readiness: Remove placeholder flows you don't want users seeing in a store review build.
- Runtime choice: If your app depends on native libraries, validate in a development build before aiming at release artifacts.
For web, you should also create a production web build and test it separately. A passing development server on your laptop doesn't prove your deployed web output is healthy.
From 'Hello World' to a Real App with AppLighter
The most under-covered part of Expo getting started is what happens after the first successful run. Expo's own FAQ emphasizes that Expo is a framework for iOS, Android, and web with live updates and scaling features, but beginner-oriented material often stops at setup and QR scanning rather than getting deep into architecture and production structure, which is the gap highlighted in the official Expo FAQ.
That gap is where many first projects go sideways. The sample app works, then the actual app begins. You add authentication, navigation rules, API calls, global state, protected screens, onboarding, and error handling. Suddenly the easy starter no longer answers the hard questions.
Why starter apps stop being enough
A fresh Expo project is good at one thing: getting you moving. It is not, by itself, a scalable application foundation.
That becomes obvious as soon as you need to answer questions like these:
- Where does authenticated versus unauthenticated routing live?
- How should API code be organized so screens don't become a mess?
- Which state belongs in local component state versus a shared store?
- How do you keep feature code maintainable once multiple developers touch it?
Those aren't “advanced” questions reserved for big companies. Small apps hit them quickly.
Screenshot from https://www.applighter.com
A working prototype proves the idea. A structured codebase determines whether you can keep shipping after week one.
What a scalable foundation should already solve
If you don't want to reinvent the same stack decisions on every project, a starter kit can save serious time. The value isn't just prewritten screens. It's the opinionated wiring: authentication, navigation, API boundaries, state setup, and a project shape that still makes sense after the first feature sprint.
That's the appeal of a production-oriented Expo foundation. Instead of spending your early momentum on repetitive setup, you start with the parts developers typically build anyway.
When evaluating a starter kit, I'd look for these traits:
| What to check | Why it matters |
|---|---|
| Auth already wired | Prevents ad hoc login flow decisions from spreading across the app |
| Clear navigation structure | Makes protected routes and nested flows easier to reason about |
| API layer conventions | Stops screens from becoming direct networking clients |
| State strategy | Reduces random store creation and inconsistent data flow |
| Tooling for real teams | Helps when the project moves beyond solo experimentation |
If you want to see an example of that kind of Expo-first app foundation, this guide to building a real Expo mobile app workflow is a useful next read.
If you've outgrown starter templates and want a faster path to a production-ready Expo app, AppLighter gives you an opinionated foundation with authentication, navigation, state management, API tooling, and AI-assisted development workflows already wired up, so you can spend more time building product features and less time assembling the stack.