Lovable to APK: turning a Lovable web app into an Android app
Lovable produces a React and TypeScript web app with a hosting preview. That build already runs in a browser, so the Android question is not how to write an app. It is what to wrap, and what will break inside a WebView.
A note before the routes: no packaging service turns a web app into a native app. A wrapper gives you an icon, a splash screen, a back button, permissions and a signed artifact. Anything that needs a device API stays native.
Route 1: publish to HTTPS, then wrap the URL
Publish the Lovable project, ideally to a custom domain you control, and point the build at that HTTPS origin. The app loads it in a Trusted Web Activity, which is Chrome rendering your site full screen. Nothing is bundled, so every change you make in Lovable afterwards is live in the installed app on its next launch. No rebuild, no reinstall, no store update.
Two requirements come with this route. The origin must be HTTPS, and the app opens without a browser address bar only when Android can verify that the site and the app have the same owner: it fetches https://your-domain/.well-known/assetlinks.json and matches the app's signing certificate fingerprint against the entry in that file. That fingerprint is the certificate's SHA-256, not the keystore file's hash, and a mismatch is the most common reason a wrapped app shows an address bar.
A Lovable preview subdomain usually cannot serve files at the site root, so a custom domain is the practical requirement for the full-screen result. Without one, use Route 2: a bundled build needs no assetlinks file.
Route 2: export the code and package the built assets
Export the project to GitHub, clone or download it, install dependencies, and run the web build (npm run build for a Vite project). You get a dist/ folder holding index.html and its assets. Zip that folder and upload it with a package ID, an icon and a signing key. The app then loads its own files from inside the APK: no web hosting, no live origin, and it opens with no network.
Two things to get right first. Bake your environment variables in, because a Lovable app's backend URL and anon key are read at build time and a missing value is a blank screen. And set the base path to relative, so absolute /assets/... URLs do not resolve to nothing inside the app.
The trade is updates. A bundled app is frozen at the moment you packaged it, so fixing a typo means a new build with a higher version code, redistributed as an APK or published to Play. That suits a demo, a course handout or an internal tool on a fixed release, and hurts a product you change weekly.
What breaks in a WebView: sign-in, camera and file downloads
Google refuses OAuth inside a WebView and reports it as disallowed_useragent, and other providers block the same pattern. The fix is a handoff: sign-in opens in the device browser or a Custom Tab, and the provider redirects back into the app through a callback URL registered in the manifest. A URL build sidesteps the problem entirely, because the page runs in Chrome and signs in normally.
A file input does nothing in a WebView unless the app implements the file chooser callback and declares the permissions it needs, including the media read permission on Android 13 and later. A live camera preview through getUserMedia also needs a secure context, which a page loaded from inside the APK does not automatically have.
Downloads are the third gap. A link to a PDF or a CSV export is a silent no-op without a download listener, and blob URLs and the system share sheet need their own handling.
What breaks in a WebView: the back button, links and sessions
Android's back gesture exits the app by default, while users expect it to go back one page inside the app until there is no history left. Unhandled, that makes the app feel wrong in the first minute.
External links and target="_blank" open inside the wrapper with no way back unless you route them to a Custom Tab or the browser, and only your own domain should stay inside the app.
Sessions deserve a plan too. A wrapped app that keeps its login token in localStorage can lose it when the system clears app data or the user reinstalls. Layout is the last detail: the status bar, the gesture bar and a resizing keyboard all change what fits on screen, and only a real device shows whether your header, bottom navigation and forms survive them.
Why a published-URL build updates without reinstalling
The installed app is a frame, and Chrome fetches the page on each launch. Lovable deploys reach the app the next time a user opens it: no rebuild, no version code, no store review, and it works for sideloaded installs as well.
The exceptions are worth knowing. Anything baked into the shell, such as the app name, icon, splash colour, package ID and permissions, still needs a rebuild. Offline behaviour needs a service worker in the web app itself, which is separate from the packaging step.
When a native rewrite is unavoidable
A wrapper is the wrong tool when the app depends on the device rather than on a page. Plan native work when you need push notifications delivered through Firebase Cloud Messaging, background location or geofencing, Bluetooth, background sync while the app is closed, NFC, a home-screen widget, or sustained background audio.
Performance can force the same decision: a canvas-heavy game or a long live data table feels worse in a WebView than in a browser tab.
Everything else fits the wrapper: a form-based SaaS, a booking flow, a course app, a customer portal, a dashboard. Start there, test on a real device, and rewrite only the screens that the testing proves need it.
Step-by-step
- Decide the route: Publish to a real HTTPS URL if the app has sign-in or you change it often. Export the code so the app runs offline only when it must.
- Publish to a custom domain: Move the Lovable project off the preview subdomain so you control the origin and can serve /.well-known/assetlinks.json from the site root.
- Build the app: Enter the production URL, or upload the ZIP of your built dist/ folder, plus the app name, package ID, 512 by 512 icon and splash colour.
- Add the assetlinks file: For a URL build, publish the assetlinks.json entry containing the app's signing certificate SHA-256, so Android can verify the app and open it full screen.
- Test the WebView gaps on a device: Check sign-in, the camera and file pickers, a file download, the back gesture, external links and the keyboard on a real device first.
- Keep the keystore and version code: Store the keystore for that package, and raise the version code on every rebuild you distribute or upload to Google Play.
Frequently asked questions
Can I turn a Lovable app into an Android app without exporting any code?
Yes. Publish the project to an HTTPS URL and build a URL-based app that loads it. That route needs no repository, no build step on your machine and no reinstall when the web app changes.
Why does Google sign-in fail inside the app?
Google refuses OAuth from a WebView and shows an error such as disallowed_useragent. The working pattern is to hand sign-in to the device browser or a Custom Tab and return to the app through a registered callback. A URL build does not hit this at all, because the page runs in Chrome.
Does the installed app pick up my new Lovable changes?
With a URL build, yes: the app loads your live site, so the next launch shows the new version with no rebuild. With a bundled ZIP build, no: the files are fixed inside the APK, and a change needs a new build with a higher version code.
What is assetlinks.json and do I need it?
It is the file Android fetches from your domain to confirm that your app and your site share an owner. It is needed for a URL build to open full screen without a browser address bar, and the value it contains is the signing certificate's SHA-256 fingerprint, not a hash of the keystore file. A bundled build does not need the file.
Do I need a custom domain?
For a full-screen URL build, practically yes, because you must serve a file at the site root, which a preview subdomain does not let you do. A bundled build works from any domain, or from no domain at all.
Will the camera and file uploads work in the app?
They work once the shell implements the file chooser callback and declares the needed permissions. A live camera preview also requires a secure context, which a page loaded from inside the APK does not automatically have. Test these on a real device before you distribute anything.
Can I upload the result to Google Play?
Yes, as an AAB, and the package name then becomes permanent. Be aware that a listing with no function beyond loading a website is a review risk, so plan some device-level value, or distribute the APK directly for internal use.
Is the app signed, and can I update it later?
Every build is signed, and each project keeps its own keystore so consecutive builds of the same app share an identity. Keep that keystore, because updates signed with a different key cannot install over an existing app.
Is there a way to try this before paying?
New accounts get free credits on signup, which cover a first build. Paid plans add monthly credits and remove the free-tier watermark on builds.