vibe-coding mobile expo capacitor security react-native

From Vibe-Coded Web App to App Store: The Complete Guide

Built something amazing with Cursor or Lovable? Here's how to turn your AI-generated web app into a real mobile app—the quick way and the right way.

CursorGuard Team

From Vibe-Coded Web App to App Store

You did it. You vibed with Cursor, Lovable, or another AI coding assistant and built something genuinely useful. Maybe it’s a productivity tool, a SaaS dashboard, or that side project you’ve been dreaming about for years. It works beautifully in the browser.

Now comes the question that haunts every vibe coder: “How do I get this on the App Store?”

We dove into the Reddit community discussions, combined it with real-world experience, and put together this guide. But here’s the thing—we’re not just going to tell you the quick and dirty way. We’ll show you both paths: the fast wrapper approach and the better native approach. You decide what fits your project.

The Two Paths

Let’s be clear upfront about your options:

PathBest ForTime to App StoreUser Experience
Wrapper (Capacitor/PWA)MVPs, quick validationDaysGood, but “webby”
Expo/React NativeProduction apps1-2 weeksNative, polished

Both are valid. Neither is wrong. But they serve different purposes.


Path 1: The Quick Wrapper Approach

When you need your app live this week, wrapping your existing web app is the fastest route.

Option A: PWA + TWA (Android Only)

If your app doesn’t need deep native features (camera access, push notifications, Bluetooth), a Progressive Web App wrapped in a Trusted Web Activity is your fastest path to the Play Store.

What you need:

  • A properly configured PWA (manifest.json, service worker, HTTPS)
  • Google Play Developer account ($25 one-time)
  • Bubblewrap or PWABuilder to generate the AAB file

The process:

  1. Ensure your web app has a valid manifest.json with icons
  2. Add a service worker for offline support
  3. Use Bubblewrap or PWABuilder to wrap it
  4. Upload the generated .aab file to Google Play Console
  5. Fill out the store listing and submit

Limitations: This approach doesn’t work for iOS App Store—Apple requires more than a web wrapper.

Option B: Capacitor (Cross-Platform)

When you need native device features or want to publish on both stores, Capacitor is the go-to wrapper solution.

What you need:

  • Your existing React/Vue/Angular web app
  • Node.js and npm
  • Android Studio (for Android builds)
  • Xcode on a Mac (for iOS builds)
  • Apple Developer account ($99/year) for iOS

Basic setup:

# Add Capacitor to your existing project
npm install @capacitor/core @capacitor/cli
npx cap init

# Add platforms
npm install @capacitor/android @capacitor/ios
npx cap add android
npx cap add ios

# Build your web app and sync
npm run build
npx cap sync

# Open in native IDEs
npx cap open android
npx cap open ios

Adding native features:

# Push notifications
npm install @capacitor/push-notifications

# Camera access
npm install @capacitor/camera

# Secure storage (important for tokens!)
npm install @capacitor-community/secure-storage-plugin

Capacitor works well and many successful apps use it. But users can often tell the difference between a wrapped web app and a truly native one—especially on iOS where the expectations are higher.


Path 2: The Better Approach (Expo/React Native)

Here’s what the Reddit threads often miss: if your AI assistant generated React code (which Cursor and Lovable typically do), you’re already 70% of the way to a React Native app.

Why Expo is Often the Smarter Choice

  1. Your AI can help port the code — Cursor is excellent at converting React web components to React Native equivalents
  2. Expo Go for instant testing — Test on your actual phone without building anything
  3. EAS Build handles the hard parts — No need to configure Xcode signing certificates yourself
  4. Truly native UI — Users notice. App store reviewers notice.

Getting Started with Expo

# Create a new Expo project
npx create-expo-app@latest my-mobile-app
cd my-mobile-app

# Start development
npx expo start

Scan the QR code with Expo Go on your phone. You’re now testing on a real device in under 2 minutes.

Porting Your Web Components

Here’s the mental model: React Native uses the same React patterns, but different primitives.

Web React:

<div className="container">
  <span className="title">Hello</span>
  <button onClick={handlePress}>Click me</button>
</div>

React Native:

<View style={styles.container}>
  <Text style={styles.title}>Hello</Text>
  <Pressable onPress={handlePress}>
    <Text>Click me</Text>
  </Pressable>
</View>

The logic stays the same. Your hooks work identically. Your state management (Zustand, Redux, whatever) transfers directly. You’re mostly just swapping HTML elements for React Native components.

Pro tip: Give Cursor your web component and ask it to convert to React Native. It handles this remarkably well.

Building for App Stores with EAS

# Install EAS CLI
npm install -g eas-cli

# Configure your project
eas build:configure

# Build for both platforms
eas build --platform all

# Submit to stores
eas submit --platform ios
eas submit --platform android

EAS handles code signing, provisioning profiles, and all the nightmare configuration that usually takes days to figure out.


Platform Comparison

Before you choose a path, understand what you’re signing up for:

Google PlayApp Store
Developer fee$25 one-time$99/year
Review timeHours to a few daysDays to weeks
Build requirementsAndroid Studio (any OS)Xcode (Mac only)
Review strictnessModerateVery strict
PWA acceptanceYes (via TWA)No (requires native)

Apple’s review process is notoriously picky. They reject apps for minor UI issues, will scrutinize your privacy practices, and require you to use their payment system for digital goods. Plan for at least one rejection cycle.


The Security Problem Nobody Talks About

Here’s where this guide differs from every other “how to publish your app” tutorial.

Going mobile dramatically increases your attack surface.

When your code lived on a server, secrets stayed on the server. The moment you bundle code into an APK or IPA, everything in that bundle is extractable. Attackers literally decompile apps for fun.

The Dangers of Mobile Bundles

API keys get exposed:

// This is fine on a server
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

// This is a DISASTER in a mobile app
const stripe = new Stripe('sk_live_abc123xyz...');

APK files are just ZIP archives. Anyone can extract yours, run it through a decompiler, and grep for sk_live. Game over.

Insecure token storage:

// DON'T do this in mobile
await AsyncStorage.setItem('auth_token', token);

// DO use secure storage
import * as SecureStore from 'expo-secure-store';
await SecureStore.setItemAsync('auth_token', token);

AsyncStorage is essentially a plain text file. SecureStore uses the device’s secure enclave.

OAuth redirect hijacking:

If your app uses OAuth (Google Sign-In, GitHub, etc.), improperly configured redirect URIs can allow attackers to intercept authentication tokens.

Hardcoded secrets in AI-generated code:

This is the big one. When you prompt an AI to “add Stripe integration” or “connect to Firebase,” it often generates working code with placeholder credentials—or worse, prompts you to paste in your real keys. That code is now in your git history and about to be bundled into a downloadable app.


Mobile Security Checklist

Before you submit to any app store, verify:

  • No hardcoded API keys or secrets — Use environment variables or secure backend proxies
  • Secure storage for sensitive data — SecureStore (Expo) or Keychain/Keystore (native)
  • Environment variables properly configured — Not bundled, fetched securely at runtime
  • OAuth redirect URIs validated — Use app-specific deep links with proper verification
  • All network requests over HTTPS — No exceptions
  • Sensitive data never logged — console.log statements are extracted just as easily
  • Certificate pinning for sensitive APIs — Prevents man-in-the-middle attacks
  • Data safety declarations completed — Both stores now require these

How CursorGuard Catches These Issues

This is exactly why we built CursorGuard.

AI coding assistants generate code fast—but they don’t think about security. They’ll happily create a working Stripe integration with your live API key hardcoded in a constant. That code gets committed, pushed, and eventually bundled into your mobile app.

CursorGuard’s multi-layered scanning catches these issues before they ship:

Semgrep pattern matching finds known secret formats:

  • sk_live_* (Stripe keys)
  • sk-proj-* (OpenAI keys)
  • AKIA* (AWS access keys)
  • Firebase configs with embedded credentials

ESLint security plugins catch dangerous patterns:

  • Hardcoded credentials in any form
  • Insecure storage usage
  • Logging of sensitive data

Claude AI deep analysis understands context:

  • Finds secrets hidden in config objects and comments
  • Detects when environment variables might leak
  • Identifies insecure data flows that static analysis misses

Real Example

A developer building with Cursor asked the AI to add push notifications. The generated code included:

const firebaseConfig = {
  apiKey: "AIzaSyB...",
  authDomain: "myapp.firebaseapp.com",
  projectId: "myapp-12345",
  // ... more config
};

This is technically “fine” for Firebase web (these keys are meant to be public), but the AI also generated server-side Firebase Admin code with the private service account JSON embedded. That would have shipped in the mobile bundle.

CursorGuard flagged it as CRITICAL before the commit was even pushed.


Here’s our suggestion based on what we’ve seen work:

flowchart TD
  A[🚀 Your Web App] --> B{Need it live<br/>this week?}
  B -->|YES| C[⚡ Capacitor Wrapper]
  B -->|NO| D[📱 Expo/React Native]
  
  C --> E[Sync to GitHub]
  D --> E
  
  E --> F[Install CursorGuard]
  F --> G[🔍 Run Security Scan]
  G --> H{Issues Found?}
  H -->|YES| I[🔧 Fix Before Bundling]
  I --> G
  H -->|NO| J[✅ Build & Ship!]
  
  style A fill:#3b82f6,stroke:#1d4ed8,color:#fff
  style C fill:#f59e0b,stroke:#d97706,color:#fff
  style D fill:#10b981,stroke:#059669,color:#fff
  style J fill:#22c55e,stroke:#16a34a,color:#fff

The cost of fixing a security issue before release? Minutes.

The cost of fixing it after your API key has been harvested from a decompiled APK? We’ve seen bills hit $87,000.


Final Thoughts

Turning your vibe-coded web app into a mobile app is absolutely doable. The Reddit community is right about the basic paths—PWA wrappers for speed, Capacitor for features, native for quality.

But don’t skip the security step. The same AI speed that helped you build fast can also help you ship vulnerabilities fast. One scan before you build catches the issues that would otherwise end up in every user’s pocket.

Ready to ship securely? Run CursorGuard on your repo before you build that APK. Your future self (and your wallet) will thank you.

Related Posts