<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ship Desk</title>
    <description>The latest articles on DEV Community by Ship Desk (@shipdesk).</description>
    <link>https://dev.to/shipdesk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4144615%2F3a0c10f2-0fb2-4a96-b85b-8cbbb24ac7c2.png</url>
      <title>DEV Community: Ship Desk</title>
      <link>https://dev.to/shipdesk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shipdesk"/>
    <language>en</language>
    <item>
      <title>What each App Store rejection guideline actually means for AI-built apps</title>
      <dc:creator>Ship Desk</dc:creator>
      <pubDate>Sat, 26 Sep 2026 17:12:13 +0000</pubDate>
      <link>https://dev.to/shipdesk/what-each-app-store-rejection-guideline-actually-means-for-ai-built-apps-3j6k</link>
      <guid>https://dev.to/shipdesk/what-each-app-store-rejection-guideline-actually-means-for-ai-built-apps-3j6k</guid>
      <description>&lt;p&gt;If you shipped your app with Lovable, Base44, Bolt, v0, Replit, or another AI app builder — or you're driving Claude Code / another coding agent directly — you'll eventually hit one of a small set of App Store rejections that show up over and over for this category of app. The guideline number Apple prints is a category, not a diagnosis, and treating it as a diagnosis is the single most expensive mistake you can make: it costs a full review cycle (typically 2-4 days) per wrong guess.&lt;/p&gt;

&lt;p&gt;This is a plain-language breakdown of the five guidelines that account for most rejections in AI-built apps: 2.1 (App Completeness), 4.2 (Minimum Functionality), 4.8 (Login Services), 5.1.1(v) (Account Deletion), and 3.1.1 (In-App Purchase). For each one: what Apple actually means, why it shows up disproportionately in AI-built apps, and what fixing it actually looks like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why AI-built apps hit these specific five
&lt;/h2&gt;

&lt;p&gt;There's a pattern behind why these guidelines cluster together for this category of app, and it's worth naming before going through them individually.&lt;/p&gt;

&lt;p&gt;Apps built quickly with an AI builder or coding agent tend to pass their &lt;em&gt;first&lt;/em&gt; review and fail later ones. The first version usually has a small "review surface" — maybe just email sign-in, no payments, no social login. Then over a few weeks the surface grows: Google sign-in gets added, then Apple sign-in, then in-app purchases, then an invite-code system. Each addition doubles what a reviewer can touch. And because testing tends to mean "click through it myself, logged in as me," nobody walks the &lt;em&gt;new&lt;/em&gt; areas the way a stranger with a brand-new account would.&lt;/p&gt;

&lt;p&gt;None of the five guidelines below are really about code quality. They're about what a reviewer, acting as a first-time user with no history in the app, can and cannot do.&lt;/p&gt;

&lt;h2&gt;
  
  
  2.1 — App Completeness
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it actually means:&lt;/strong&gt; the reviewer hit something that didn't work — a crash, a button that does nothing, an endless spinner, a blank screen, a link to nowhere. Apple reviews on real, current devices, often an iPad even if you only designed for iPhone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why AI-built apps hit this:&lt;/strong&gt; the most common cause isn't a bug in the traditional sense — it's a login or sign-up path that works fine for the account you've been testing with (which has months of history and every permission already granted) but fails for an account created fresh, thirty seconds before the reviewer clicks the next button. A second common cause: the layout was designed and tested on a phone simulator and never opened on an iPad, so a control is off-screen or covered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What "fixed" actually looks like:&lt;/strong&gt; get the exact device and OS from the rejection notice (open the submission in App Store Connect and read the full message — the summary email and the version-page banner are not the full text). Walk the exact path the reviewer describes with a brand-new account, not your logged-in one. If you genuinely cannot reproduce it, don't guess and resubmit — reply and ask for the exact reproduction steps. Apple's follow-up often names the real cause in one sentence, and that sentence is worth more than three days of guessing.&lt;/p&gt;

&lt;p&gt;One thing worth knowing before you guess: a wrong hypothesis chased for days is a common trap here. If the rejection says "not responsive" and you can't reproduce it, the honest reply — "we could not reproduce this on [devices tested]; could you share the exact steps?" — is a better use of a review cycle than shipping five plausible-looking fixes and hoping one of them was right.&lt;/p&gt;

&lt;h2&gt;
  
  
  4.2 — Minimum Functionality
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it actually means:&lt;/strong&gt; Apple thinks the app is a website in a wrapper, offering nothing a browser tab doesn't already give you. This is the single most common rejection specifically for apps made with web-based AI builders and then wrapped for iOS (Capacitor, WebView-based shells, etc.) — it exists almost entirely for this category of app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why AI-built apps hit this:&lt;/strong&gt; the builder generates a responsive web app, and the path to "iOS app" is often just wrapping that same web app in a native shell with no additional native behavior. Apple can tell. Browser-style navigation (back arrows, links opening inside the wrapper), a blank white screen with no connection instead of an offline state, and zero use of anything the phone actually offers (notifications, camera, share sheet, haptics) are the tells.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What "fixed" actually looks like:&lt;/strong&gt; this isn't a bug fix, it's an addition. You need at least one or two things that are specific to being on a phone: push notifications when something relevant happens, camera or photo input, a proper offline screen with cached content instead of blank white, a native tab bar instead of the website's header/footer. When you reply to Apple, name the specific native features you added — "we improved the app" gets you the same rejection again. "Build 1.2 adds push notifications when a booking is confirmed, offline access to saved items, and share-sheet export of reports" gets read.&lt;/p&gt;

&lt;h2&gt;
  
  
  4.8 — Login Services
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it actually means:&lt;/strong&gt; you offer a third-party login (Google, Facebook, etc.) but not one that meets Apple's privacy conditions — in practice, Sign in with Apple. Or Sign in with Apple exists but is broken.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why AI-built apps hit this:&lt;/strong&gt; most auth templates generated by builders default to "Continue with Google" because it's the most common OAuth example in training data and documentation, and nobody adds the Apple equivalent until Apple asks for it. It's genuinely one of the cheaper fixes on this list — most auth providers (Supabase, Firebase, and others) support Sign in with Apple as a checkbox-level feature — but it has to be wired into your entitlements file and your backend's auth settings, not just added as a button.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A specific failure mode worth knowing in advance:&lt;/strong&gt; Sign in with Apple can be technically working — the user genuinely signs in — while the app never tells the screen. This happens when the app decides "is this user signed in?" by checking a profile record that loads a moment &lt;em&gt;after&lt;/em&gt; the sign-in session is created, rather than checking the session itself. Email/password sign-in often accidentally avoids this because of how the code happens to sequence, while Apple sign-in exposes the race. From the reviewer's side, this looks exactly like "not responsive" — tap the button, sign in successfully, nothing happens until you force-relaunch the app. If Apple reports Sign in with Apple as unresponsive, check the step &lt;em&gt;after&lt;/em&gt; sign-in completes, not just the sign-in call itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What "fixed" actually looks like:&lt;/strong&gt; add Sign in with Apple at the same size and visual weight as your other sign-in options, using Apple's actual button asset (not a generic apple icon from an icon library — reviewers, and contrast checkers, both notice). Test with an Apple ID that has genuinely never touched your app, including the "Hide My Email" relay option, and confirm the very next screen appears without a restart.&lt;/p&gt;

&lt;h2&gt;
  
  
  5.1.1(v) — Account Deletion
&lt;/h2&gt;

&lt;p&gt;**What it actually means: **users can create an account inside the app but can't delete it from inside the app. Apple has required in-app account deletion since 2022 — not a support email, not a web form, an actual in-app path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why AI-built apps hit this:&lt;/strong&gt; the feature is very often &lt;em&gt;actually present&lt;/em&gt; and still gets rejected, because of where it's placed. A common pattern: account deletion lives on a settings screen that's only visible to users with an admin or elevated role, because "that's where settings live" in the generated UI. If the demo account provided to Apple isn't an admin, the reviewer genuinely cannot find the feature — even though it exists and works. A correct feature can fail review purely because of who's allowed to see it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What "fixed" actually looks like:&lt;/strong&gt; "Delete account" needs to be reachable from every account role, not just admins — it only ever deletes the current user's own account, so there's usually no security reason to gate it. Confirm once, then actually delete (or clearly start deletion of) the account and its data, and say in the UI how long that takes. If you use Sign in with Apple, revoke the Apple token as part of deletion. In your review notes, spell out the exact path — "Settings → Account → Delete Account" — rather than assuming the reviewer will find it.&lt;/p&gt;

&lt;h2&gt;
  
  
  3.1.1 — In-App Purchase Required for Digital Content
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it actually means:&lt;/strong&gt; the app sells or unlocks digital features or content — premium features, credits, subscriptions to the app itself — using a payment method other than Apple's In-App Purchase, or links out to one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why AI-built apps hit this:&lt;/strong&gt; Stripe checkout is the default payment integration in most AI builder templates, because it's the fastest thing to wire up and it's genuinely the right call for a web product. It is very often the wrong call for the iOS build of the same product. A "Subscribe" button in the iOS app that opens a web checkout for something used inside the app is close to a guaranteed rejection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What actually needs to change, and what doesn't:&lt;/strong&gt; the rule turns on what you're selling, not how you built the app. Digital features or content consumed inside the app generally need In-App Purchase. Physical goods and real-world services — deliveries, bookings, in-person coaching — can keep using your own payment processor, because they're consumed outside the app. If you have an "invite code" or similar unlock mechanism, document exactly what it does and doesn't unlock in your App Review notes; reviewers assume the worst about anything that looks like a payment bypass unless told otherwise, explicitly.&lt;/p&gt;

&lt;p&gt;One detail that costs people a review cycle for reasons that have nothing to do with code: In-App Purchase product identifiers have to match, exactly, between what your app requests and what's registered in App Store Connect. If a note in your own project log says this was fixed, treat that as a claim about the past, not a fact about today — re-check the live dashboard, with today's date, before relying on it. And a release build that's missing the purchase configuration will show the reviewer a bare paywall error, which reads as a completeness bug even though the cause was a build step, not a bug.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one habit that generalizes across all five
&lt;/h2&gt;

&lt;p&gt;Every one of these guidelines is really asking the same underlying question from five different angles: what does this app look like to someone with no history in it, on a device you didn't personally test on, following exactly the path described? Read the full rejection text before writing a single line of code in response — the guideline number is a category, the message underneath it is the actual finding, and conflating the two is what turns a two-day fix into a two-week one.&lt;/p&gt;

&lt;p&gt;If you want the full decision tree for a specific rejection message — which guideline it maps to, the typical causes for AI-built apps specifically, and a reply template — there's a free rejection decoder here: &lt;a href="https://neumax-labs.github.io/decoder.html" rel="noopener noreferrer"&gt;https://neumax-labs.github.io/decoder.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>appstore</category>
      <category>nocode</category>
      <category>mobile</category>
    </item>
    <item>
      <title>The App Store checklist for apps built with Lovable/Bolt/v0</title>
      <dc:creator>Ship Desk</dc:creator>
      <pubDate>Sat, 26 Sep 2026 16:41:22 +0000</pubDate>
      <link>https://dev.to/shipdesk/the-app-store-checklist-for-apps-built-with-lovableboltv0-93</link>
      <guid>https://dev.to/shipdesk/the-app-store-checklist-for-apps-built-with-lovableboltv0-93</guid>
      <description>&lt;p&gt;If you built your app with an AI app builder (Lovable, Bolt, v0, Replit, or similar) and wrapped it for iOS with something like Capacitor, you're going to hit App Review with a specific set of blind spots. Not because the app is bad — because the tools that generated it optimize for "it works when I click through it," not "it works from a stranger's brand-new account, on the free plan, on an iPad."&lt;/p&gt;

&lt;p&gt;This is a stage-by-stage checklist built from actual rejection cycles: real guideline numbers, real causes. It won't guarantee approval — nothing does, Apple reviews every submission and makes the call — but it closes off the failure modes that keep coming back for apps built this way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why these apps get rejected in predictable ways
&lt;/h2&gt;

&lt;p&gt;AI-built apps tend to pass their &lt;em&gt;first&lt;/em&gt; review and fail later ones. The reason is almost always the same: the first version had a small "review surface" — maybe just email sign-in, no payments, no social login. Then over a few weeks you add Google sign-in, then Apple sign-in, then in-app purchases, then an invite-code system. Each addition doubles what a reviewer can touch. And because the builder tool (and the humans using it) tested by walking the same happy path over and over, nobody ever walked through the &lt;em&gt;new&lt;/em&gt; areas as a first-time stranger would.&lt;/p&gt;

&lt;p&gt;Keep that framing in mind as you go through this list: every stage below exists because someone, somewhere, shipped a feature that worked for them and failed for a reviewer with no history in the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 1 — Before you touch sign-in
&lt;/h2&gt;

&lt;p&gt;If your app offers any third-party login (Google, Facebook, etc.), Apple's Guideline 4.8 requires you to also offer an equivalent privacy-respecting option — in practice, Sign in with Apple. This is not optional and not negotiable, and it's cheap to add early and expensive to retrofit.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] If you offer any social/OAuth login, Sign in with Apple is also implemented natively (not just as a web view).&lt;/li&gt;
&lt;li&gt;[ ] Sign in with Apple is wired into your entitlements file and your backend's auth settings — not just the button on the screen.&lt;/li&gt;
&lt;li&gt;[ ] You've tested first-time sign-in with &lt;em&gt;every&lt;/em&gt; login method on a device that has never used the app before.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last item matters more than it sounds. A very common bug: the app's "is this a new user, send them to onboarding" logic was written when only one login provider existed, and never updated when a second one was added. Result: a new user via the second provider skips onboarding, has no account state set up, and every subsequent request silently fails. Nothing crashes, nothing shows an error — the screen just sits there, which to a reviewer looks exactly like "this button does nothing."&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 2 — Account deletion, and who can see it
&lt;/h2&gt;

&lt;p&gt;Since 2022, Guideline 5.1.1(v) requires that any app letting users create an account must let them delete it from inside the app — not just via a support email, not just via a web page.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] "Delete account" exists inside the app, not only on a website.&lt;/li&gt;
&lt;li&gt;[ ] It's visible to &lt;em&gt;every&lt;/em&gt; account role, not just admins.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That second point trips up more apps than you'd expect. It's common to build a settings screen that's admin-only, and then bury account deletion on it because "that's where settings live." If your test/demo account for reviewers isn't an admin, the reviewer literally cannot find the feature — even though it exists. A correct feature can still fail review because of where it's placed and who's allowed to see it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 3 — Payments, the part everyone gets wrong once
&lt;/h2&gt;

&lt;p&gt;Guideline 3.1.1 requires that digital features consumed inside the app be sold through Apple's in-app purchase system, with narrow exceptions (mainly for goods/services consumed outside the app). If your builder-generated app routes users to a web checkout for anything used inside the app, expect a rejection.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Any paid feature usable inside the iOS app is sold via StoreKit / in-app purchase, not a web redirect.&lt;/li&gt;
&lt;li&gt;[ ] Web checkout, if you have one, is reserved for your website only — not linked or referenced from the iOS app's paywall.&lt;/li&gt;
&lt;li&gt;[ ] Any "invite code" or similar unlock mechanism is documented in your App Review notes explaining exactly what it does and does not unlock. If it doesn't bypass payment, say so explicitly — reviewers will otherwise assume the worst.&lt;/li&gt;
&lt;li&gt;[ ] Your in-app purchase products are registered in App Store Connect and the identifiers match exactly what your app requests. (Mismatches here are a classic case of a note in a project log going stale — re-verify the actual dashboard state with a date, don't trust an old comment.)&lt;/li&gt;
&lt;li&gt;[ ] You can produce a release build that includes the correct purchase configuration — a build without it will just show a paywall error to the reviewer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stage 4 — Your demo account, treated as a real submission artifact
&lt;/h2&gt;

&lt;p&gt;A huge fraction of "reviewer couldn't do X" rejections trace back to the demo account, not the code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] The demo account in App Store Connect actually logs in, right now, today (test it fresh before every submission).&lt;/li&gt;
&lt;li&gt;[ ] "Sign-in required" is checked correctly in the App Review information if your app needs an account to do anything meaningful.&lt;/li&gt;
&lt;li&gt;[ ] Your review notes describe the &lt;em&gt;current&lt;/em&gt; demo account — not a stale one from a previous submission.&lt;/li&gt;
&lt;li&gt;[ ] If your app has subscription tiers, provide a demo account whose subscription state matches what the reviewer needs to test (e.g., an account with an expired subscription if they need to test the renewal/paywall flow).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stage 5 — Placeholder and unfinished content
&lt;/h2&gt;

&lt;p&gt;Guideline 2.1 (App Completeness) covers a wide net: placeholder content, coming-soon labels, crashes, and unfinished features. AI-generated UIs are prone to shipping placeholder text that never got swapped out.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] No "your logo here," "lorem ipsum," or similar placeholder strings anywhere in the build a reviewer can reach.&lt;/li&gt;
&lt;li&gt;[ ] No buttons or nav items labeled "coming soon" that lead nowhere.&lt;/li&gt;
&lt;li&gt;[ ] No "beta" language describing the app itself, unless you're actually distributing via TestFlight beta review.&lt;/li&gt;
&lt;li&gt;[ ] Every plan/tier, including the free one, has been clicked through end to end, on the cheapest plan, without crashing.&lt;/li&gt;
&lt;li&gt;[ ] Testimonials or social proof, if present, are attributed to a real, checkable source.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stage 6 — Test it as a stranger, on an iPad
&lt;/h2&gt;

&lt;p&gt;This is the stage most builder-tool workflows skip entirely, because the builder's preview is usually a phone-sized web view.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] You've done a full run-through on an actual iPad (not just resized phone simulator), on the free plan, with a brand-new account.&lt;/li&gt;
&lt;li&gt;[ ] You've done the same run-through on a physical iPhone, not just a simulator — some things (Sign in with Apple in particular) behave differently on-device.&lt;/li&gt;
&lt;li&gt;[ ] If Apple's rejection asks for a screen recording, you're prepared to record it on a real device, not a simulator driven by automation. Simulator recordings may be accepted, but a reviewer who explicitly asked for a device recording is telling you they distrust simulator evidence.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stage 7 — When you do get rejected: get the actual message
&lt;/h2&gt;

&lt;p&gt;This isn't a pre-submission item, but it belongs in the checklist because it changes how you spend the days after a rejection.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Don't diagnose from the guideline number alone. "2.1" covers crashes, placeholders, missing features, and broken flows — it is a category, not a specific cause.&lt;/li&gt;
&lt;li&gt;[ ] Open the actual rejected submission in App Store Connect and read the full message text, including any attached screenshots and the device/OS the reviewer used. The summary email and the version page are not the full message.&lt;/li&gt;
&lt;li&gt;[ ] Note the specific device mentioned (e.g., "iPad Air, current iPadOS") — if none of your own testing covered that device, that's your first lead.&lt;/li&gt;
&lt;li&gt;[ ] Match your fix list to what was &lt;em&gt;actually said&lt;/em&gt;, not to everything you can find that might loosely relate to the guideline number. It's easy to spend days fixing seven real things when Apple only flagged three — and fixing the wrong six doesn't get you approved.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stage 8 — Before you resubmit
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Every item Apple's message named specifically has a corresponding fix, and you can explain the fix in one sentence in your reply.&lt;/li&gt;
&lt;li&gt;[ ] Any external dashboard state you're relying on (payment processor, backend config) has been re-checked &lt;em&gt;today&lt;/em&gt;, not assumed from an old note.&lt;/li&gt;
&lt;li&gt;[ ] Your reply to App Review states plainly what changed and, if useful, why the reviewer may have seen the described behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using this as a running list
&lt;/h2&gt;

&lt;p&gt;None of this is exotic — it's mostly things that are obvious in hindsight and invisible in the moment, because AI builder tools are very good at making the happy path work and say nothing about the paths nobody walked. Treat this less as a one-time pre-submission task and more as a standing checklist you run every time you open up a new area of the app: a new sign-in method, a new plan tier, a new role.&lt;/p&gt;

&lt;p&gt;We turned this into an interactive checklist (progress saved locally in your browser, nothing sent anywhere) if you'd rather work through it that way instead of copy-pasting a markdown list: &lt;a href="https://neumax-labs.github.io/checklist.html" rel="noopener noreferrer"&gt;https://neumax-labs.github.io/checklist.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>appstore</category>
      <category>nocode</category>
      <category>mobile</category>
    </item>
  </channel>
</rss>
