Wrap a Lovable App With Capacitor
Capacitor is the fastest way to get a Lovable web app into the App Store and Google Play without rewriting a single screen. It packages your compiled Vite build — the exact HTML, CSS, and JavaScript Lovable generates — inside a native iOS and Android shell. This guide covers the setup, the native plugin integrations, Supabase deep-link auth, and the submission checklist.
By Founder Name · Last verified: 2026-06-24
What exactly does Capacitor do to a Lovable app?
Capacitor bundles your compiled web build — the `dist/` folder produced by `npm run build` — into a native iOS and Android container. That container renders your web app inside a native WebView, exposes device APIs (camera, push notifications, filesystem) via a JavaScript plugin bridge, and produces a signed binary that the App Store and Google Play accept. Your Lovable source code, Supabase configuration, and routing all remain unchanged.
The result is a real native app from the stores' perspective. Users download it from the App Store or Google Play, find it on their home screen, and can grant it permission to access the camera, location, and notifications. The UI renders your existing Lovable components — there is nothing to rewrite.
The practical constraint: anything that worked in a desktop Chrome tab works in Capacitor's WebView with minimal changes. Things that require OS-level background access — background location polling, background audio, persistent background tasks — require explicit Capacitor plugins and user permissions. Those are additions, not rewrites.
How do I install Capacitor in a Lovable project?
Capacitor is installed as an npm package directly into your Lovable project. Because Lovable generates a standard Vite + React project, the installation follows the same steps as any Vite app. The one Lovable-specific consideration is that your `vite.config.ts` build output directory must be `dist/` — Capacitor reads from there by default.
- Clone your Lovable project to a local machine using the GitHub integration (Lovable editor → GitHub → Export).
- Run `npm install @capacitor/core @capacitor/cli` to add Capacitor.
- Run `npx cap init` — enter your App Name and Bundle ID (e.g. com.yourcompany.appname). Use reverse-domain notation; this cannot easily change after App Store submission.
- Confirm `capacitor.config.ts` sets `webDir: 'dist'` to match your Vite output directory.
- Run `npm run build` to generate the `dist/` folder.
- Run `npx cap add ios` to scaffold the native iOS project (requires macOS + Xcode).
- Run `npx cap add android` to scaffold the native Android project.
- Run `npx cap sync` to copy the web build and any installed plugins into both native projects.
- Open Xcode: `npx cap open ios` — set your development team under Signing & Capabilities.
- Open Android Studio: `npx cap open android` — connect a device or emulator and run the app.
Which Capacitor plugins does a typical Lovable app need?
Most Lovable apps need three plugins at minimum: Push Notifications (for FCM on Android and APNs on iOS), Status Bar (to control the native status bar appearance), and possibly Camera if the app handles file uploads. Installing plugins requires adding the npm package, running `npx cap sync`, and then configuring any native permissions in `Info.plist` (iOS) or `AndroidManifest.xml` (Android).
Push Notifications setup: `npm install @capacitor/push-notifications && npx cap sync`. On iOS, add the Push Notifications capability in Xcode → Signing & Capabilities. On Android, add your `google-services.json` file to the `android/app/` directory. The plugin fires JavaScript events when a notification arrives; your app code stores the device token in Supabase.
Camera plugin: `npm install @capacitor/camera && npx cap sync`. Declare `NSCameraUsageDescription` in `ios/App/App/Info.plist` and `CAMERA` permission in `AndroidManifest.xml`. The Capacitor Camera API replaces the HTML `<input type='file' accept='image/*'>` for native camera access.
How do I configure Supabase auth deep links in Capacitor?
Supabase's OAuth and magic-link flows redirect to a URL after authentication. In a browser, that redirect returns to your web app. In a Capacitor app, you need the redirect to open your native app instead — via a custom URL scheme registered in the OS. Without this, your users get stuck in a browser tab after OAuth and the Capacitor app never receives the auth session.
- In `capacitor.config.ts`, add the scheme under the app section: `server: { androidScheme: 'https' }` and define a custom scheme for deep links.
- Register your scheme in `ios/App/App/Info.plist` under `CFBundleURLTypes` with the key `CFBundleURLSchemes` set to your bundle ID or custom scheme.
- Register the intent filter in `android/app/src/main/AndroidManifest.xml` under the main Activity.
- In your Supabase Auth settings (Dashboard → Authentication → URL Configuration), add your scheme as an allowed redirect URL: e.g. `com.yourcompany.appname://auth/callback`.
- In your Lovable app code, listen for the `appUrlOpen` Capacitor event and pass the received URL to `supabase.auth.setSession()` to complete the OAuth exchange.
- Test by triggering a Google OAuth sign-in and confirming the app opens and the user session is established.
What CSS changes does a Lovable app need for mobile?
Lovable apps designed for desktop browsers often have layouts that need minor adjustments for iOS and Android. The most important is the safe-area inset — on iPhones with a notch or Dynamic Island, content can be hidden behind the status bar or home indicator unless the CSS accounts for it. This is a 10-minute fix, not a redesign.
Add this to your global CSS to account for iOS safe areas: `padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom);`. Set this on your root layout element, not on every individual component.
Remove any `position: fixed` elements that relied on `100vh` equaling the visible viewport — on iOS WebView, `100vh` includes the area behind the address bar. Use `100dvh` (dynamic viewport height) instead. Also verify that any bottom navigation bars clear the home indicator area on iPhone X and later models.
How do I submit the wrapped app to the App Store and Google Play?
Submission requires an Apple Developer account ($99/year) for the App Store, and a Google Play developer account ($25 one-time) for Google Play. Both stores require a signed binary. iOS signing happens in Xcode using your provisioning profile and distribution certificate. Android signing uses a keystore file you must keep securely — it cannot be recovered if lost.
- Apple: Create an App ID in the Apple Developer portal matching your bundle ID. In Xcode → Product → Archive, build a release archive. Use the Distribute App flow to upload directly to App Store Connect.
- In App Store Connect, create a new app record, fill in metadata (name, description, screenshots), and select the uploaded build for review.
- Google: In Android Studio → Build → Generate Signed Bundle/APK, create or select your keystore and build a release AAB.
- Upload the AAB to Google Play Console → Create app → Production track.
- Both stores require screenshots at required resolutions — iOS needs 6.5-inch and 5.5-inch screenshots at minimum; Google Play requires phone screenshots plus tablet if you target tablets.
- Submit for review. App Store review typically takes 1–3 business days for first submissions. Google Play review takes 1–7 days.
Frequently asked questions
Do I need to clone my Lovable project to use Capacitor?
Can Capacitor access the iPhone camera from a Lovable app?
How often do I need to resubmit to the App Store after a Lovable update?
What is the difference between npx cap sync and npx cap copy?
Will my Supabase real-time subscriptions work in the Capacitor WebView?
How do I handle push notifications in my Lovable app after wrapping it?
Can I test the Capacitor app without a physical device?
What if my Lovable app uses iframes or external scripts that Capacitor blocks?
Talk to a senior engineer — not a salesperson.
Book a free 30-minute audit call. We'll diagnose what's wrong and tell you exactly what it costs to fix.