A website you can build and ship the same day. Nobody has to approve it.
A mobile app is a different kind of object, and the difference has almost nothing to do with code. You are shipping into two stores that read your submission against written rules, measure your app’s stability after launch, publish deadlines that force you to rebuild it, and control whether anyone can find it. None of that is in the prompt, and none of it shows up while you are testing on your own phone.
So an AI-built app tends to arrive at submission in a particular state: the product works and the paperwork does not exist. This post is what sits between those two things, in the order it will hit you.
If you also have a website built this way, the code-quality evidence and the web-specific gaps are in the companion post. This one covers what is specific to shipping on a phone.
Gate 1: review, which is five gates
Rejection feels like a verdict. It is not — it is a guideline number with a specific remedy, and the same handful accounts for most first submissions.
Three of those deserve expanding, because they are the ones a generated app fails for structural reasons rather than careless ones.
2.1, App Completeness. Apple says plainly that they “will reject incomplete app bundles and binaries that crash”. In practice this catches: placeholder copy a model left in a settings screen, a link to a privacy policy page that was never written, a backend on a free tier that sleeps while a reviewer is looking at it, and — the most common of all — a login with no working demo account supplied. Reviewers do not sign up for your service. If they cannot get in, that is the rejection.
4.2, Minimum Functionality. Apple wants “features, content, and UI that elevate it beyond a repackaged website”. If your app is a WebView around the site you already have, this is the guideline you will meet. It is survivable, but it has to be answered deliberately — real native navigation, real offline behaviour, real platform integration — rather than discovered at submission.
5.1.1, Data Collection and Storage. Several hard requirements live here, and one of them is retrofitted constantly: “If your app supports account creation, you must also offer account deletion within the app.” Not an email address to write to. In-app deletion, reachable by the user. A generated app with a sign-up screen almost never has this, because nobody prompts for it — and it touches your data model, your backend and your subscription logic, so it is not a UI afternoon.
The same guideline requires a privacy policy that is reachable both inside the app and in App Store Connect, and consent before collecting anything — explicitly including data you consider anonymous, like analytics.
And before any of that on Android: if your Play Console account is a personal one created after 13 November 2023, you cannot publish at all until you have run a closed test with at least 12 testers, continuously opted in for 14 days, and then applied for production access and had it reviewed. Twelve real people for two weeks is a scheduling problem, not a coding one, and it is the single most common reason a finished Android app is still not live.
Gate 2: the security model, which is the website problem made worse
Everything about client-side trust from the web post applies here, with one change that makes it sharper: you are not shipping code to a browser, you are shipping a file to a device someone owns, permanently.
A subscription checked in app code is a suggestion. An if (hasPro) in your view
model is removed by anyone willing to spend an evening on it, and the entitlement
must therefore be established on your server — validate the store receipt
server-side, record the result against the account, and have the app ask.
The key point for mobile specifically: a compiled binary is not a hiding place. Strings in an IPA or APK are readable with standard tools, and traffic is readable with a proxy. Any third-party key in the app — analytics, maps, email, an AI API — is published, and unlike a web bundle you cannot quietly replace it. Users keep old versions installed for months.
Escape’s scan of publicly reachable vibe-coded apps reported 2,038 highly critical vulnerabilities and 400+ leaked secrets across 1.4K applications, with 175 instances of exposed personal data. And Veracode’s Spring 2026 measurement puts the AI-generated security pass rate at 55% across 150-plus models — statistically unchanged in two years, while syntactic correctness climbed steeply over the same period. Code that compiles and code that is safe did not improve together.
Gate 3: four privacy declarations that have to agree
This is the gate nobody sees coming, because every individual answer is honest.
Your code collects certain things. That has to match your privacy manifest, your App Store privacy labels, Google Play’s Data safety form, and your published privacy policy — and the stores compare them against each other, not just against their own rules.
Apple’s PrivacyInfo.xcprivacy requirement has been enforced since 1 May 2024:
declared reasons for required-reason APIs, plus privacy manifests and valid
signatures for commonly used third-party SDKs added as binary dependencies. An
upload missing that can be refused before review even begins.
Generated projects break this in a specific way. Dependencies get added because a model needed one to satisfy a request — a crash reporter, an analytics package, an ad SDK, an HTTP client. Each arrives with its own data collection, and nobody made a decision about it, so nobody declared it. The app is not dishonest. It is undocumented, which the stores treat the same way.
Gate 4: two numbers that decide your distribution
After launch, Google Play measures you. These are not guidelines.
Cross the overall thresholds and, in Play’s own terms, your app is likely to be less discoverable, with a warning possibly shown on your store listing. The per-device threshold matters just as much for a cross-platform app: 8% on one popular device model is enough to be pushed down on that model alone, which is exactly the shape of a layout or memory bug on older hardware.
Now the part that makes this a vibe-coding problem specifically. An app with no crash reporting is not below these thresholds — it is unmeasured, and the threshold applies anyway. A generated app rarely includes crash and ANR reporting, because nobody asks for it, so the first signal that something is wrong is a one-star review describing a screen you cannot reproduce.
Adding it takes an afternoon and should happen before your first submission, not after your first bad week. It is the highest-leverage hour in this entire post.
Gate 5: the rebuild you have already been scheduled for
A website you can leave alone for two years. An app you cannot.
All three of those dates are published by the platform owners. The last one is the sharpest: from April 2027, every App Store upload must be built with the iOS 27 SDK — and apps built with that SDK must use UIKit’s scene-based life cycle or they do not launch at all. If you are on a cross-platform framework, that depends on your framework shipping support and on you upgrading to it. We have written up exactly where each framework stands in the iOS 27 developer guide, and what it means commercially in the iPhone Duo and iOS 27 owner guide.
This is why the maintainability question is not academic for mobile in the way it can be for a marketing site. Somebody has to open that codebase, upgrade it, and ship it again — on a date you did not choose.
GitClear’s classification of 211 million changed lines shows the drift: copy/pasted lines rising from 8.3% to 12.3% of all changes while refactoring fell from about 25% to under 10%. DORA’s 2025 report, from nearly 5,000 professionals, found AI adoption correlating with higher throughput and lower delivery stability at once, and framed it well: AI doesn’t fix a team; it amplifies what’s already there.
An app you cannot confidently rebuild is not a finished project. It is a deadline you have not met yet.
Gate 6: devices you did not choose
You tested on your phone. Your phone is new, charged, on good wifi, in your language, at default text size, and never receives a call at an awkward moment.
The crash clusters in a first release are concentrated in exactly the conditions you never saw: a three-year-old mid-range Android, the largest accessibility text size, a small screen where your fixed-height layout clips the submit button, airplane mode halfway through a form, the app backgrounded for an hour and resumed, a permission the user denied and the code assumed was granted.
Generated code is optimistic by default. It assumes the network works, the response parses, the permission is granted, and the array is not empty. Each of those assumptions is one line to guard and one crash cluster to prevent.
The order to fix it
Sorted by what is irreversible and what gates distribution — not by difficulty.
The order to fix a vibe-coded mobile app, from irreversible risks to long-term maintainability
- 1Revoke and re-home every secretStop the bleedingHours to days
Anything compiled into the binary is readable. Move third-party calls behind your own endpoint, then rotate the keys.
- 2Move entitlement checks to the serverStop the bleedingDays
Subscriptions, feature flags and roles verified in-app are advisory. Receipts must be validated server-side and the answer stored against the account.
- 3Add crash and ANR reporting before you submitStop the bleedingHours
Play’s core vitals decide your distribution, and you cannot manage a number you cannot see. Without this, your first signal is a one-star review.
- 4Close the store-review gapsBefore more users arriveDays
Account deletion, a reachable privacy policy, consent before collection, demo credentials, no placeholder content. These are rejections, not suggestions.
- 5Make the four privacy declarations agreeBefore more users arriveDays
Code, privacy manifest, App Store labels and Play Data safety describe the same app. Mismatches are found in review and after it.
- 6Test on hardware you did not chooseBefore you spend on trafficDays
Old devices, small screens, largest text size, no network, an interrupting call. Most crash clusters in a first release live here.
- 7Build a release pipeline, then plan for SeptemberSo the next change is cheapOngoing
Reproducible signed builds, staged rollout, a rollback. Then the annual OS deadline — including the iOS 27 SDK floor — stops being a surprise.
What a professional team actually changes
Almost never a rewrite. Your build encodes real decisions about the product, and those were the expensive part to learn. What changes is everything that was never in the prompt.
The entitlement and authorisation model, moved server-side once, so every later feature inherits it rather than re-implementing it.
Submission as an engineering task. Account deletion, consent flows, demo credentials, review notes with specifics rather than a generic description, and the four privacy declarations reconciled against what the code actually does. We handle store review responses as part of shipping — it is a deliverable on our mobile work, not an afterthought.
Instrumentation before launch, so vitals are a number you manage instead of a surprise that costs installs.
A release pipeline — reproducible signed builds, staged rollout, a rollback that has been tested — which turns “the app is broken” from a crisis into a procedure.
Tests around the paths that move money or data, plus consolidation of the duplicated logic, so next September’s forced upgrade is a week and not a rebuild.
What to check this week, free
- Unzip your
.apkor.ipaand runstringsover the binary. Search forkey,secretandtoken. Rotate anything you find, then move the call server-side. - Find a request that returns user data, and replay it without the app — signed out, or signed in as a different account. What comes back is your top priority.
- Ask yourself whether a user can delete their account from inside the app. If they can create one and cannot delete it, that is a rejection under 5.1.1.
- Open Play Console → Android vitals. If it shows no data, you have no crash reporting, and that is the cheapest thing on this list to fix.
- Borrow the oldest phone you can find, set text size to maximum, turn off wifi mid-task, and try to complete your app’s main flow.
- Confirm your target API level against Play’s requirement, and find out whether your framework has shipped iOS 27 scene life cycle support.
Six checks, an afternoon, and you will know whether you are a week from the store or a month from it.
If you would like an engineer to do that properly, we offer a free written assessment of exactly this — what breaks, what to fix first, and a realistic effort estimate — at the app evaluation page. It is framed around iPhone Duo and iOS 27 because that is this autumn’s deadline, but send an app built any way at all and we will tell you where it stands.