Build.
Turning your web app into iOS and Android apps
What Capacitor actually does, the one architectural decision that matters, and why Apple rejects apps like yours.
Your customers keep asking for the app. You have a working web app and no appetite for building the same thing twice in two native languages. Capacitor is the usual answer: it wraps your web app in a native shell, so one codebase ships to both stores and to the web.
Before any of the technical work, there is one decision that shapes everything after it.
The decision: bundled or live?
Capacitor can ship your web app in one of two ways.
Bundled. Your web files are packaged inside the app itself. It works offline, it starts instantly, and every change needs a new build and a new store review.
Live. The app loads your website inside the shell. Fixes reach everyone the moment you deploy, with no store review at all, and it needs a connection to work.
Neither is wrong. Live is a strong fit for anything content-driven that changes often, like a radio station app, a catalogue or a dashboard. On a project we run that way, a web-layer fix reaches existing App Store users immediately, which turns an urgent bug from a week into an hour.
The catch is that Apple rejects apps that are only a website in a frame with nothing native about them. Live loading needs genuine native features around it to pass review.
What you get for free, and what you do not
Free, because it is your existing web app: every screen, every flow, your styling, your backend.
Not free, and worth budgeting for:
- Native features. Camera, notifications, biometrics and deep links each need a plugin and configuration on both platforms.
- The Android back button. On the web, nobody presses a hardware back button. On Android they will, constantly, and by default it can close your app from any screen.
- Safe areas. Notches and home bars overlap your layout unless you account for them.
- Keyboard behaviour. A keyboard appearing can shove your whole layout up in ways it never does in a mobile browser.
- Session persistence. This is the big one.
The bug that catches everyone
Web apps refresh their login session when the page regains focus. On a phone, the app regains focus every time someone switches back to it, and several parts of your app can fire that refresh at the same moment.
Supabase, and most token systems, treat two simultaneous refreshes with the same token as a sign that the token was stolen, and revoke the whole session. Your users get signed out at random and nobody can reproduce it on a laptop.
The fix is a lock: allow one refresh at a time, and have everything else wait for its result. We traced exactly this on a live radio app, where it was the single biggest source of complaints.
What Apple rejects apps for
In rough order of how often we see it:
- No native purpose. A wrapped website with no native capability at all.
- Payments outside their system for digital content, where their rules require in-app purchase.
- Missing account deletion. If people can sign up in the app, they must be able to delete their account in the app.
- Privacy answers that do not match the app, particularly around tracking.
- A login wall with no way to look around, for apps that do not genuinely require an account.
- Placeholder content in screenshots or in the app itself.
Google Play is more forgiving on review and stricter on paperwork: the data safety form, target API levels and a privacy policy that is actually reachable.
Keep the keys in your own name
Your Apple Developer account, your Google Play account, your signing keys. If a developer holds the signing key for your Android app and disappears, you cannot ship an update to your existing users at all. Ever. It is the single most expensive thing to get wrong, and it costs nothing to get right.
A realistic sequence
- Fix your web app on real phones first, because every problem there becomes a problem in the app.
- Decide bundled or live.
- Wrap it, add the native features that justify its existence, handle the back button and safe areas.
- Fix the session refresh before anyone tests it.
- Test on real devices, not only simulators.
- Prepare the store listings, privacy answers and screenshots.
- Submit, expect one rejection, and read the reason carefully.