← Back to Guides
9 min readIntermediate
Share

Vibecoding an iOS + Android App with Expo

A hands-on getting-started guide to building a real cross-platform app with Expo and React Native using AI — from project setup to previewing on your phone.

Vibecoding an iOS + Android App with Expo

This is the hands-on companion to the planning and prompting guides. We'll go from nothing to a working app running on your actual phone — one codebase, both platforms, no Mac required to start. The example is deliberately tiny so the mechanics stay front and center.

Prerequisites: Node.js installed, a phone (iOS or Android), and an AI coding assistant. That's it. No Xcode or Android Studio needed to get started — Expo Go handles previewing.

Why Expo for this

Expo is the friendliest on-ramp to React Native, and it's the stack where AI is most effective:

  • You write TypeScript — the language the AI knows best.
  • Expo Go previews your app on a real device instantly, over Wi-Fi.
  • EAS builds and signs iOS apps in the cloud, so you don't need a Mac.
  • Native features come as Expo packages configured in JSON, not native code.

If you haven't picked a stack yet, read Native vs. Cross-Platform first. If you have, let's build.

Step 1: Create the project

You can have the AI generate the exact command, but this one is stable:

npx create-expo-app@latest streak
cd streak
npx expo start

npx expo start opens a dev server and shows a QR code in your terminal. This is your live reload loop for the whole build.

Step 2: Preview on your phone

Install Expo Go from the App Store or Google Play. Then:

  • iOS: open the Camera app, point it at the QR code, tap the notification.
  • Android: open Expo Go, tap "Scan QR code," point it at the terminal.

Your app loads on the phone. Every time you save a file, it reloads. Keep the phone next to you — this is the tightest feedback loop in mobile development, and it's where you catch the things the AI can't see.

Test on a real device from the start. The emulator and simulator hide safe-area, keyboard, and performance issues that only appear on hardware.

Step 3: Set up navigation before screens

Modern Expo uses Expo Router, which is file-based — a file in app/ becomes a route. Prompt the AI with your navigation map from planning:

Using Expo Router, set up a tab layout with three tabs: Home, History, Settings. Create placeholder screens for each showing the tab name centered. Add a modal route for "Log workout."

You'll get an app/ directory with (tabs)/ and a modal route. Reload on your phone — you should see three working tabs. Navigation working first means every screen you build next has somewhere to live.

Step 4: Build the first vertical slice

Now the core loop. Following the prompting strategies, build one screen fully:

Build the Home screen. Show a large streak number (hardcode 5 for now) and a "Log workout" button that opens the Log workout modal. Respect safe areas on both iOS and Android. TypeScript, function component.

Reload, confirm the button opens the modal. This slice proves layout, safe areas, and navigation all work together before any data exists.

Step 5: Add the data layer

Wire in real storage so logged workouts persist across app restarts:

Add expo-sqlite. Create a workouts table (id, date, type, durationMinutes, notes). Build the Log workout modal form with fields for type, duration, and notes; on save, insert into SQLite and dismiss. This must work fully offline.

Install what it asks for (npx expo install expo-sqlite), reload, and log a test workout. Close the app completely and reopen it — the data should still be there. If it isn't, the AI stored it in memory; point that out and ask for SQLite persistence explicitly.

Step 6: Close the loop

Make the Home screen read real data:

Update the Home screen to compute the streak from the workouts in SQLite instead of the hardcoded 5. Reload the data when the screen regains focus so a newly logged workout updates the streak immediately.

The useFocusEffect refresh detail matters on mobile — without it, the Home screen shows stale data after you log something. Now you have a real, working app doing its one job, entirely offline, on both platforms.

Step 7: Handle the unglamorous states

Before you call any screen done, add the three states AI skips by default:

Add loading, empty ("Log your first workout"), and error states to the Home and History screens.

Step 8: Make it look like an app

Two quick wins:

  • App icon and splash — drop images into assets/ and point app.json at them. Generate the icon with an image tool; Expo produces the platform sizes.
  • Test both platforms — if you built on Android, borrow an iPhone (or vice versa) and run Expo Go there. Fix whatever looks off. They will differ.

Step 9: When you're ready to leave Expo Go

Expo Go is for development. To ship, or to use a native module Expo Go doesn't bundle, you make a development build or a production build with EAS:

npm install -g eas-cli
eas login
eas build --platform android   # or ios, or all

EAS builds in the cloud and hands you an installable file — an .apk/.aab for Android or an .ipa for iOS, the iOS one built without you owning a Mac. That output is what you submit to the stores.

What you've got

A single TypeScript codebase running on iOS and Android, storing data offline, previewed live on your phone the whole way. The pattern generalizes to any app: navigation first, then vertical slices, each tested on a real device, each built with a precise single-screen prompt.

From here it's more slices — and then the store submission machinery, which is a different kind of work entirely.

Next steps

Stay in the flow

Get vibecoding tips, new tool announcements, and guides delivered to your inbox.

No spam, unsubscribe anytime.