Skip to content
MVP & Vibe-Code Rescue

Your vibe coded app: how to get it store-ready

An AI-built app meets gates a website never does: five review guidelines, four privacy declarations, two crash thresholds, a rebuild deadline. What to fix first.

Ingenious Techlab Team9 min read
Contents
  1. Gate 1: review, which is five gates
  2. Gate 2: the security model, which is the website problem made worse
  3. Gate 3: four privacy declarations that have to agree
  4. Gate 4: two numbers that decide your distribution
  5. Gate 5: the rebuild you have already been scheduled for
  6. Gate 6: devices you did not choose
  7. The order to fix it
  8. What a professional team actually changes
  9. What to check this week, free

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.

What a working prototype demonstrates, and what production additionally requiresAbove a waterline: The screens, The happy path, Your own data, Your own device, Your own network — the things a demo proves. Below the waterline, a larger set of properties that only appear with real users, real load and store or search review: Authorisation, Store review, Privacy declarations, Crash and freeze rates, Device spread, Offline and interruption, Release process, OS upgrades, Accessibility, Deletion.WHAT THE DEMO PROVEDThe screensThe happy pathYour own dataYour own deviceYour own networkthe waterline: strangers, load, time, reviewWHAT PRODUCTION ALSO REQUIRESAuthorisationchecked on the server, not in the appStore reviewfive guidelines a first build usually failsPrivacy declarationsfour separate answers that must agreeCrash and freeze ratesthresholds that cost you distributionDevice spreadold phones, small screens, large textOffline and interruptiontunnels, calls, backgrounding, low batteryRelease processsigning keys, staged rollout, rollbackOS upgradesevery September, whether you planned for it or notAccessibilityVoiceOver, TalkBack, dynamic typeDeletionin-app account deletion, or no store listing
The top band is not wrong or wasted — it is a real product decision, validated cheaply, and that is worth something. It is just the part that is visible from where the builder was standing.

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.

The App Review gates a first submission has to pass, and the guideline each one rejects underGuideline 2.1, App Completeness: requires a final build, no placeholder text, working URLs, a live backend, and demo account details if there is a login. Guideline 2.3.1, Accurate Metadata: requires no hidden or undocumented features, and specific review notes rather than a generic description. Guideline 4.2, Minimum Functionality: requires more than a wrapped website. Guideline 4.3, Spam: requires a meaningfully different experience from what the store already carries. Guideline 5.1.1, Data Collection and Storage: requires a reachable privacy policy, consent before collecting anything, and in-app account deletionSubmitted buildEach gate can send it back on its own. Reviewers stop at the first one that fails.2.1
App Completeness
Needs a final build, no placeholder text, working URLs, a live backend, and demo account details if there is a login
“We will reject incomplete app bundles and binaries that crash”
2.3.1
Accurate Metadata
Needs no hidden or undocumented features, and specific review notes rather than a generic description
“generic descriptions will be rejected”
4.2
Minimum Functionality
Needs more than a wrapped website
“features, content, and UI that elevate it beyond a repackaged website”
4.3
Spam
Needs a meaningfully different experience from what the store already carries
“indistinguishable from what’s already widely available”
5.1.1
Data Collection and Storage
Needs a reachable privacy policy, consent before collecting anything, and in-app account deletion
“you must also offer account deletion within the app”
Rejected at any gateBack to the queue with a guideline number.Each round trip costs days, not minutes.Through all fiveLive — and now measured on crash and freezerates that decide how findable it is.
Rejection is not a verdict on your idea — it is a specific guideline number with a specific remedy, and the same five account for most first-submission failures. Quoted phrases are Apple's own wording from the App Review Guidelines.

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.

Where the trust boundary sits in a mobile appEverything inside the app runs on hardware the user controls, so every check there can be edited or skipped. Requests can reach the API directly, bypassing the client entirely. Only checks that run on the server side of the boundary are enforced.UNTRUSTED — the user controls thisThe appOn a device someone else ownsif (hasSubscription) — paywallAPI key compiled into the binaryInput validationDebug / internal screensEditable. Readable. Skippable.trust boundaryTRUSTED — you control thisYour APIWho is calling?Are they allowed?Is the input sane?Per request. Every time.DatabaseRow-level rulesDeny by defaultService keys server-only1. The path you testedThrough your own UI, logged in, behaving.Unzip the IPA or APK, then curlYour UI is not involved at all2. The path that decideswhether you have a productor an incident.POST /api/export — no UI, no paywall
Anything on the left of the dashed line is a suggestion. Only the right-hand side is enforcement. The second path is not an exotic attack — it is one person putting a proxy in front of the app, reading the request and replaying it without your app in the way.

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.

How a secret reaches the client, and why rotating it is not the hard partA five-step chain: the app needs a third-party key; the key is placed in client-side code; Strings in the binary, readable with `strings` on the IPA or APK; anyone can read it out of the shipped app; the key is then used outside your app, producing charges, data access and abuse under your name. Rotating the key is quick, but identifying what was accessed requires request logs a prototype usually does not have.
A key is needed
Payments, email, maps, an AI API
It goes in the app code
Because that is where the call is written
The compiler embeds it
Strings in the binary, readable with `strings` on the IPA or APK
Anyone reads it
Unzip the package, or watch the traffic with a proxy
Used without you
Your quota, your bill, your name
WHAT THAT TURNS INTOAn unexpected bill
Metered APIs do not rate-limit on your behalf
Data you hold about others
The key often reads more than the app shows
Messages sent as you
Email and SMS keys are reputational, not just financial
Rotating the key: minutesIssue a new one, move it server-side,proxy the call, revoke the old key.This is the part everyone does.Knowing what was taken: unanswerableWithout request logs from before the leak,there is no way to scope the disclosure —which is what a regulator will ask for.
Every arrow here is ordinary tooling working exactly as documented. Nothing is hacked. The vulnerability is the decision about which side of the boundary the key lives on.

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.

The four privacy declarations that must agree with each other and with the codeWhat the code and its SDKs actually collect must match the app's privacy manifest (PrivacyInfo.xcprivacy), the App Store privacy labels, Google Play's Data safety form, and the published privacy policy. Each is written at a different time by a different route, and stores check them against one another.GROUND TRUTHWhat the code doesYour own network callsEvery third-party SDKAnalytics and crash toolsAnything an AI feature sendsDiscoverable only by reading itPrivacyInfo.xcprivacyIn the app bundle. Required-reason APIs and SDK signatures.Apple, since May 1, 2024App Store privacy labelsIn App Store Connect. Shown on your listing.AppleData safety formIn Play Console. Shown on your listing.Google PlayYour privacy policyA live URL, in the app and in the listing metadata.Both stores, plus the lawWhen they disagreeRejection under 5.1.1,or a build refused at uploadfor a missing manifest.After launch it is worse:a labelled promise youare not keeping.
One source of truth, four audiences. The usual break is an analytics, crash-reporting, advertising or AI SDK added late: the code changes, and none of the four declarations does.

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.

Google Play core vitals bad-behaviour thresholds for crashes and freezesUser-perceived crash rate: the overall bad-behaviour threshold is 1.09 per cent of daily users across all device models, and 8 per cent for a single device model. User-perceived ANR rate: the overall bad-behaviour threshold is 0.47 per cent of daily users across all device models, and 8 per cent for a single device model. an app over the overall threshold is likely to be less discoverable on Google Play, and a warning may be shown on its store listing.How much failure Google Play allows before it costs you installsBoth are measured against daily users, across every device your app runs on — not against sessions you tested.User-perceived crash rate1.09% of daily users — over this, distribution suffersCounts crashes that happen while someone is actually using the app.Separately, 8% on any single device model is enough to be pushed down on that model alone.Band shown at 10× scale for legibility.User-perceived ANR rate0.47% of daily users — over this, distribution suffersCounts the app freezing long enough for Android to offer to close it.Separately, 8% on any single device model is enough to be pushed down on that model alone.Band shown at 10× scale for legibility.An app with no crash reporting is not below these thresholds. It is unmeasured — and the threshold applies anyway.
Thresholds from Play Console's Android vitals documentation. Exceeding the overall threshold means an app over the overall threshold is likely to be less discoverable on Google Play, and a warning may be shown on its store listing. The bands below are drawn at ten times scale — at true scale each one is under two pixels wide.

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.

Published platform deadlines that require an existing app to be rebuiltAugust 31, 2026, Google Play: New apps and updates must target Android 16 (API level 36) or higher. Existing apps need Android 15 (API level 35) or higher to stay available to new users on newer devices. November 1, 2026, Google Play: Last day of a requested extension. An extension has to be applied for in Play Console, not assumed. April 2027, Apple: every App Store upload must be built with the iOS 27 SDK. Apps built with that SDK must also use the scene-based life cycle, or they do not launchRebuild deadlines already on the calendarNot a forecast. These are the dates the two stores have announced.August 31, 2026GOOGLE PLAY
New apps and updates must target Android 16 (API level 36) or higher
Existing apps need Android 15 (API level 35) or higher to stay available to new users on newer devices
November 1, 2026GOOGLE PLAY
Last day of a requested extension
An extension has to be applied for in Play Console, not assumed
April 2027APPLE
every App Store upload must be built with the iOS 27 SDK
Apps built with that SDK must also use the scene-based life cycle, or they do not launch
Plus one every autumn: a new iOS and Android release, with or without a deadline attached.
Every date here is published by the platform owner and applies to apps that are already live. An app you cannot confidently rebuild is not a finished project — it is a deadline you have not met yet.

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.

Copy/pasted lines rising while refactored lines fallAcross 211 million changed lines from January 2020 to December 2024, the share of copy/pasted lines rose from 8.3 per cent to 12.3 per cent, while the share of moved, refactored lines fell from about 25 per cent to under 10 per cent. The two lines crossed, and copy/pasted lines exceeded moved lines for the first time in the dataset.0%10%20%30%20202024Share of all changed linesTwo trends that swapped places. The lower line is the one that keeps a codebase changeable.Moved — refactoring: 25%under 10%Copy/pasted: 8.3%12.3%The crossing: more code duplicated than consolidatedFrom here, every fix has to be applied more than once — and usually is not.
GitClear, 211 million changed lines, January 2020 to December 2024. In 2024 copy/pasted lines exceeded moved lines for the first time in the dataset. This is what "it works but nobody can change it" looks like as a measurement: the same logic living in several places, so every change means finding all of them.

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

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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.

Sorted by what cannot be undone, not by difficulty. Items 1 to 3 change what a bad day costs you; the rest change what a good year costs you. The effort bands are our estimates for a small codebase and are not measurements.

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

  1. Unzip your .apk or .ipa and run strings over the binary. Search for key, secret and token. Rotate anything you find, then move the call server-side.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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.

Sources

Verified

This post is part of our work onFrom prototype to product people can trust

Related reading

Let's talk

Tell us what you are building

Send us the scope and we will come back with an honest assessment: what it takes, roughly what it costs, and whether we are the right people for it.

  • A written reply from an engineer
  • No call required
  • No obligation