AI-Generated Expo Apps: From RapidNative ZIP to TestFlight

(149 chars): What's inside your RapidNative Expo project export and how to publish it to TestFlight and the App Store — a step-by-step guide from ZIP to submit.

RI

By Riya

7th Aug 2026

Last updated: 7th Aug 2026

AI-Generated Expo Apps: From RapidNative ZIP to TestFlight

Your chat ends. You click Download. A myapp-expo.zip lands in ~/Downloads, weighing maybe a few megabytes. Somewhere in there is an entire React Native app — one you'd have paid an agency $40,000 to write. Now what?

If you want to publish an Expo app to TestFlight and eventually the App Store, the code is only half the journey. The other half is a specific sequence of commands, config edits, and Apple's paperwork — and it's the part where most non-technical builders freeze. This guide walks through exactly what to do with a RapidNative export, from the moment the ZIP hits your disk to the moment TestFlight lights up on a beta tester's phone.

We'll cover what's actually inside the archive (down to the file), the three config files you must edit, the two commands that produce a signed iOS build, and how the same flow gets you into Google Play in parallel.

Developer holding phone showing app interface next to laptop with code editor Photo by Dose Media on Unsplash

What RapidNative's Export Actually Gives You

Before touching the terminal, it helps to know what you're looking at. RapidNative's export route (/api/user/projects/[projectId]/download) doesn't compile anything or run a build — it assembles a live snapshot of your project's files, straight out of Postgres, into a ZIP using the adm-zip package. That means the archive is a real Expo workspace, not a bundled binary. Every file in there is human-readable, editable, and re-runnable.

Unzipped, a fullstack-v2 project (RapidNative's default template) looks like this:

myapp/
├── mobile/                  # your Expo app (this is where you'll work)
│   ├── app/                 # Expo Router screens
│   │   ├── (app)/           # protected routes (post-auth)
│   │   ├── (auth)/          # sign-in / sign-up
│   │   └── _layout.tsx
│   ├── components/          # generated React Native components
│   ├── src/
│   │   ├── db/              # Vibecode DB client + schema
│   │   ├── hooks/           # useAuth, useApp
│   │   └── providers/       # AppProvider, ThemeProvider
│   ├── assets/              # icons, splash images
│   ├── app.json             # Expo config (bundle ID, name, icons)
│   ├── eas.json             # EAS Build & Submit profiles
│   ├── metro.config.js      # Metro bundler config
│   ├── tailwind.config.js   # NativeWind (Tailwind for RN)
│   ├── tsconfig.json        # TypeScript strict mode
│   ├── package.json
│   └── .env                 # injected secrets
├── api/                     # optional Express server workspace
├── web/                     # generated web landing (static)
├── .env                     # root-level env
└── README.md

The important tell here is mobile/ as a workspace. RapidNative's export code detects this monorepo shape and does some quiet plumbing — root-level assets/ get remapped into mobile/assets/ so that require('../../assets/x') resolves correctly, and the .env file gets written to both the repo root and the mobile workspace so scripts in either scope pick up secrets.

The dependency versions inside mobile/package.json are the current stable set: Expo SDK 54.0.13, React Native 0.81.4, React 19.1.0, Expo Router 6.0.12, NativeWind 4.2.1, TypeScript 5.9.3. If you're used to fighting version mismatches when starting a React Native project, this part is done.

The Three Config Files That Matter Most

Nothing about publishing works until three files reflect the app you actually want to ship — not the placeholder RapidNative generated. Open them before you do anything else.

app.json

This is Expo's manifest. It's what App Store Connect, TestFlight, and Google Play read to identify your app. The generated defaults look like:

{
  "expo": {
    "name": "RapidNative App",
    "slug": "rapidnative-app",
    "version": "1.0.0",
    "sdkVersion": "54.0.0",
    "orientation": "portrait",
    "icon": "./assets/icon.png",
    "scheme": "rapidnative-app",
    "ios": { "bundleIdentifier": "com.rapidnative.app" },
    "android": { "package": "com.rapidnative.app" },
    "plugins": ["expo-router", ["expo-splash-screen", { "backgroundColor": "#ffffff" }]]
  }
}

The four fields you must change before your first real build:

FieldWhy it matters
nameThe label under your app icon on the home screen. Users see it.
slugIdentifies the project inside your Expo account. Once used, don't change it — updates depend on it.
ios.bundleIdentifierGlobally unique on the App Store (e.g., com.yourcompany.yourapp). Locked forever after first submit.
android.packageSame idea for Google Play. Locked after first submit.

Get the bundle identifier right on the first submission. Apple treats it as the identity of the app across every future release — you can rename the app in App Store Connect, but the bundle ID is forever.

eas.json

Expo Application Services (EAS) is the cloud service that actually compiles your JavaScript into signed iOS and Android binaries. Every RapidNative export ships with an eas.json that already defines three build profiles:

{
  "cli": { "version": ">= 15.0.0", "appVersionSource": "remote" },
  "build": {
    "development": { "developmentClient": true, "distribution": "internal" },
    "preview":     { "distribution": "internal" },
    "production":  { "autoIncrement": true }
  },
  "submit": { "production": {} }
}

You don't have to change anything here to get started. The production profile is what you'll use for App Store builds, and autoIncrement will bump your build number automatically each time you rebuild — small detail that prevents App Store Connect from rejecting duplicate uploads.

.env

RapidNative injects environment variables at export time — pulling them from the encrypted project_envs table plus system-managed keys. If your generated app uses Supabase, you'll see:

EXPO_PUBLIC_SUPABASE_URL=https://xxxx.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOi...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOi...

Any variable prefixed with EXPO_PUBLIC_ is bundled into the client and is safe to expose. The service role key is server-only — if your api/ workspace uses it, leave it there and never reference it from mobile/. Before your first production build, replace any development values (dev Supabase project, dev Stripe keys) with your production credentials.

Terminal window showing code and command line output Photo by Sigmund on Unsplash

Step 1: Run It Locally in Three Commands

Before you point cloud services at it, run it on your own machine. This catches 90% of "something's off" moments in five minutes.

cd myapp/mobile
npm install
npx expo start

Metro will start on http://localhost:8081, print a QR code, and open the Expo Dev Tools. If your project's a full-stack template with the api/ workspace, install its dependencies too and start the server in a separate terminal (cd api && npm install && npm run dev).

You should see the exact same UI you saw in the RapidNative preview — because you're running the same files, just against your local Metro instead of RapidNative's admin gateway. If something looks different, it's almost always one of: missing .env values, uninstalled peer deps, or an image path that broke during ZIP extraction on Windows (use WSL or Git Bash if you're on Windows).

Step 2: Test on Your Real Device with Expo Go

Publishing without ever running the app on a real phone is a rookie mistake. Screen sizes, keyboard behavior, and touch targets are impossible to judge from a browser simulator.

Install Expo Go from the App Store (iOS) or Play Store (Android). With npx expo start running, open the Camera app on iOS or Expo Go on Android and scan the QR code in your terminal. The bundle streams to your phone in a few seconds. If you edit a file locally, the app hot-reloads.

This is the same mechanism RapidNative's in-editor QR button uses — it generates a QR pointing at your project's live preview URL (exps://<slug>-expo-dev.<domain>), routing through Expo Go on your device.

One catch: Expo Go can only run your app if it uses libraries included in the Expo Go binary. RapidNative's default templates stick to Expo SDK libraries deliberately, so you're fine. If you later add a library requiring native code (e.g., a custom Stripe SDK, a specific analytics package with native modules), you'll need a development build — same command, different profile:

eas build --profile development --platform ios

More on eas build in the next section.

Step 3: Rebrand for Production

The generated project uses placeholder branding — a generic icon, a generic name, com.rapidnative.app as the bundle ID. Before you build for the store, swap these out.

Icon and splash. Drop your 1024×1024 PNG icon at mobile/assets/icon.png and a splash image at mobile/assets/splash.png. Expo will generate every derived size (App Store icon, notification icon, adaptive icon) at build time. There are free tools like Expo's icon generator if you're starting from scratch.

app.json fields. Update name, slug, ios.bundleIdentifier, android.package, and — if you know your marketing site — the scheme (used for deep links).

Version numbers. Leave version at 1.0.0 for your first release. EAS handles buildNumber (iOS) and versionCode (Android) via autoIncrement in eas.json, so you never have to think about them.

That's the rebranding pass. It takes about 15 minutes if you have your assets ready.

Step 4: Build with EAS

EAS Build is Expo's cloud build service. You don't need Xcode installed. You don't need a Mac. You just need an Expo account and your Apple Developer credentials the first time you build for iOS.

Install the EAS CLI:

npm install -g eas-cli
eas login
eas build:configure   # only if eas.json is missing (it isn't, but harmless to run)

Kick off your first production build:

eas build --platform ios --profile production

The first iOS build asks a few questions:

  1. Bundle identifier — confirm it matches your app.json.
  2. Apple Developer account — EAS logs in and pulls your team ID.
  3. Distribution certificate and provisioning profile — say yes to letting EAS manage these. It'll create them for you. You do not want to manage certificates by hand unless you enjoy suffering.
  4. App Store Connect app — EAS will create the app record automatically the first time.

The build itself runs in the cloud and takes 15-25 minutes. You get a URL to watch progress. When it's done, you'll have a signed .ipa ready for the App Store.

For Android, run it in parallel (yes, at the same time):

eas build --platform android --profile production

Android skips the certificate dance entirely — EAS generates a keystore for you on first build. You'll end up with a .aab (Android App Bundle) ready for Google Play.

If you'd rather do both platforms in one command: eas build --platform all --profile production.

Person holding phone showing app in Expo Go with laptop in background Photo by Alvaro Reyes on Unsplash

Step 5: Submit to TestFlight

TestFlight is Apple's beta distribution channel. Getting an app onto TestFlight is the last technical step before real users can install your app on their phones. From build to invited testers is roughly 30 minutes of clock time, most of it Apple's automated processing.

With the signed build in hand:

eas submit --platform ios --profile production --latest

--latest tells EAS to submit the most recent build for that profile. EAS uploads your .ipa to App Store Connect, which takes about 5-10 minutes to process. You'll get an email from Apple when the build is ready.

Then, in App Store Connect:

  1. Open your app → TestFlight tab.
  2. Add a Test Information — an email for feedback and a description ("Beta build, please try creating an account and posting").
  3. Choose Internal Testing — invite up to 100 members of your Apple Developer team. Their invites arrive within minutes.
  4. Or External Testing — up to 10,000 users. External testing requires a Beta App Review (usually 24-48 hours) but doesn't count against your App Store review.

Your testers download TestFlight on their phones, accept your invite, and get the app. Every rebuild you eas submit gets pushed to them automatically — the update prompt is native.

For Google Play's equivalent (Internal Testing track):

eas submit --platform android --profile production --latest

The first Android submit asks you to upload a Google Play Service Account JSON key — this is Google's authentication for automated uploads. Google's docs walk through creating one, and EAS caches it so you only do this once.

Google Play in Parallel

Everything about the App Store side has a Google Play equivalent, usually simpler:

TaskiOS (App Store)Android (Play Store)
Developer account$99/year Apple Developer Program$25 one-time Google Play Console
Build serviceeas build --platform ioseas build --platform android
Submiteas submit --platform ioseas submit --platform android
Beta distributionTestFlightPlay Console → Internal / Closed testing
First-review time24-48h (external testing), 1-3 days (App Store review)1-3 hours (usually)
Certificate hellYes, but EAS handles itMinimal — keystore auto-generated

Google's review process is faster and looser. Apple's is slower and stricter but has TestFlight, which is genuinely the best beta channel of the two. Publish to both in parallel and don't wait for iOS to launch on Android.

Why RapidNative Deliberately Stops at Handoff

RapidNative generates the code, hosts the preview, and packages the export. It does not run the eas build for you. This is a design choice, and it's worth understanding why.

App Store and Google Play both bind the identity of your app — the developer account, the certificates, the revenue, the App Store review contact — to a real business entity. If RapidNative built and submitted for you, RapidNative would appear as the publisher. Your users would see RapidNative's name. Refunds would flow to RapidNative. Your app would live inside RapidNative's account.

None of that is what you want. You want to ship an app under your LLC, with your developer account, with your payment split, and be able to fire RapidNative tomorrow and continue shipping updates. Handing you a real Expo project — the same one you'd have written by hand — is the only way to make that work.

The tradeoff is one extra evening of your time. You'll spend maybe two hours reading Apple's docs on your first submission and never think about it again. Every subsequent build is one command.

Common Snags and How to Avoid Them

A handful of issues catch first-time publishers. All of them are easy if you know they're coming.

Bundle identifier collision. If you use a placeholder like com.rapidnative.app for your first build, you'll get a rejection at submission because someone else on Apple's servers has already claimed it. Always change to a real one you own — com.yourdomain.appname — before your first build.

Icon transparency. iOS icons can't have transparent pixels. If your PNG has transparency, App Store Connect will reject the build. Export as fully opaque PNG or JPEG.

Missing usage descriptions. If your app uses the camera, microphone, or location, iOS requires NSCameraUsageDescription-style strings explaining why. Expo config plugins add these automatically for most permissions, but check app.json for a plugins array covering any permission you request.

Rejected for "does not comply with 4.2 Minimum Functionality." Apple rejects apps that look like brochures — a single static screen wrapping a website. RapidNative's generated apps have interactive screens, real data flow, and multiple routes, so this is rarely a problem. If you strip your export down to a landing page and one form, Apple will notice.

From ZIP to TestFlight, Realistically

Here's the actual clock time for a typical first release:

  • Rebranding pass (icon, name, bundle ID): 30 minutes
  • Apple Developer account signup: 1-2 days (Apple's verification, one-time)
  • EAS Build for iOS + Android: 20-25 minutes each, running in parallel
  • EAS Submit + App Store Connect setup: 1 hour
  • TestFlight processing: 15-30 minutes
  • Beta App Review (if inviting external testers): 24-48 hours

Once you've done it once, subsequent releases are eas build --auto-submit --platform all --profile production and you're back to writing features. That is what the export pipeline is buying you — not just the code, but a path to the store that doesn't require you to reinvent the deployment process.

If you're still on the fence about whether AI-generated code can survive real production shipping, the honest answer is: it can, because what you're shipping isn't the AI — you're shipping React Native and Expo, the same stack Discord, Coinbase, and Shopify Shop use in production. RapidNative writes the initial code and hands you a real Expo project. Everything after that is standard mobile deployment, executed with fewer commands than you'd expect.

Ready to try it? Start building your app or see how the export pipeline works end-to-end. If you're weighing this against traditional development, our breakdown of RapidNative vs. hiring an agency covers cost, timeline, and quality tradeoffs. Pricing lives on the Pro plan page — export is a Pro-tier feature.

Start now

Ready to build your app?

Turn your idea into a production-ready React Native app in minutes.

Free tools to get you started

Questions

Frequently asked questions

What is RapidNative?

RapidNative is an AI-powered mobile app builder. Describe the app you want in plain English and RapidNative generates real, production-ready React Native screens you can preview, edit, and publish to the App Store or Google Play.

Can I export the code?

Yes. RapidNative generates clean React Native and Expo code that you can export at any time. No lock-in, no proprietary format. Hand it to your developers or keep building inside RapidNative.

Is RapidNative free to use?

Yes. You can build apps on the free plan with no credit card required. Paid plans unlock unlimited AI generations, code export, and direct publishing to the App Store and Google Play.

Do I need to know how to code?

No. Most users build apps by describing what they want in plain English. Developers can drop into the code whenever they want more control, but coding is optional.

How long does it take to build an app?

Most users have a working first screen in under a minute. A full MVP usually takes a few hours instead of the weeks or months traditional development requires.