ReadyNative

Pass App Review

Run the store check, fix what it flags, fill in the metadata, and submit to the App Store and Google Play without burning a review cycle.

Pro

Hey - by the end of this page you'll have a build that passed bun run doctor --store, a report from the store-review skill with every finding tied to a guideline id, and the store metadata filled in from that report. Then you submit.

Nobody can promise approval - reviewers are people and the guidelines move. What this page does is take the rejections that are predictable off the table before you wait a week to hear about them.

1. Run the check ✅

From your app's root:

bun run doctor --store

It reads readynative.config.ts, app.config.ts, .readynative.json and your package.json, and prints one finding per problem - blocking, warning or info - with its id, platform, guideline citation, the file and line, and the fix:

Store review check
Blocking - fix before you submit (1)
✗ Missing usage string for expo-location  [ios-usage-string-missing · ios · App Store Review 5.1.1(i)]
    app.config.ts:41
    expo-location is installed but ios.infoPlist has no NSLocationWhenInUseUsageDescription
    fix: Add the "expo-location" config plugin to plugins (with its *Permission prop) or set ios.infoPlist.NSLocationWhenInUseUsageDescription.

It also prints a Data safety draft - one row per SDK you selected, with what it collects and the vendor's disclosure page. Keep that output open; you'll paste from it in step 3.

In a Starter tree the command prints that the check is part of Pro and exits.

2. Fix the blocks

Work top to bottom. The findings that come up most:

  • Account deletion (App Store Review 5.1.1(v), Play Account deletion) - if you picked any auth option, users can create an account, so the app has to let them delete it from inside the app. The finding points at the settings screen; wire a "Delete account" row to deleteAccount() in src/lib/auth.ts, and if you offer Sign in with Apple, revoke the token server-side.
  • Sign in with Apple (App Store Review 4.8) - a Google or other social button on the sign-in screen means Apple's button has to be there too, with the same prominence.
  • Paywall copy (App Store Review 3.1.2(c), Play Subscriptions) - price, billing period and renewal terms on the paywall itself, plus a Restore Purchases action. The payments module ships these; the finding fires if you removed one or if urls.terms / urls.privacy in readynative.config.ts are still empty.
  • Digital goods through in-app purchase (App Store Review 3.1.1, Play Payments policy) - subscriptions or unlocks used inside the app must be sold through StoreKit / Play Billing (the RevenueCat or Adapty option). Stripe Checkout alone is fine for physical goods and services; for digital Pro it is allowed as a link-out on the US App Store storefront, and elsewhere only with Apple's external purchase entitlement. Offering both rails, as the Snap Recipe example does, is the safe shape.
  • Purpose strings (App Store Review 5.1.1(ii)) - every permission-bearing dependency needs its NS*UsageDescription in app.config.ts, and the string names the feature, not the permission.
  • Tracking (App Store Review 5.1.2(i)) - analytics or ads SDKs that link your data with other companies' data need the App Tracking Transparency prompt. The analytics modules ship expo-tracking-transparency with a purpose string; set features.tracking: true in readynative.config.ts and app.config.ts adds its plugin and NSPrivacyTracking: true, and AnalyticsProvider asks once the app is active, with analytics.identify waiting for consent. Off (the default), Android's AD_ID permission is blocked and doctor --store reminds you to answer "No" to tracking in App Store Connect.
  • Privacy manifest (ITMS-91053) - setup composes ios.privacyManifests from the selected modules' declarations; the finding fires if it is missing or declares tracking while features.tracking is off. The Privacy and consent page has the full picture.
  • Placeholders - com.acme.app, an empty urls.support, the default app name. Reviewers read them as an unfinished app (App Store Review 2.1(a)). Config lists every field.

Re-run the command until it is green.

3. Fill in the metadata 📋

The stores ask for things no file in your tree can prove. Go through these in App Store Connect and the Play Console before you upload:

  • Screenshots that show the app in use - not the splash or sign-in screen - for every device class you support: iPhone, iPad if supportsTablet is on, phone plus 7" and 10" tablets on Play.
  • The age rating questionnaire, answered from what the app actually contains.
  • Export compliance: ITSAppUsesNonExemptEncryption in app.config.ts matches your answer.
  • A demo account in the App Review notes when anything sits behind sign-in, and a backend that stays up while the reviewer is in.
  • The Data safety form on Play and the App Privacy answers in App Store Connect, filled from the draft table doctor --store printed - every SDK in .readynative.json accounted for.
  • A privacy policy URL and a support URL that are live, public and reachable from Settings.
  • On Play, the account-deletion web link in the Data safety form.

The draft table is a starting point, not an answer

doctor --store knows which SDKs you selected and what their vendors say they collect. It does not know what your own backend stores. Add your own data types before you submit the form - an inaccurate Data safety form gets updates blocked.

4. Run the skill with your agent 🤖

The mechanical check cannot judge copy, flows, or whether a permission prompt reads as a reason. That is the store-review skill. In Claude Code, Cursor or any agent that reads .agents/skills/:

Run the store-review skill on this app and give me the report.

It runs doctor --store, reads the paywall, onboarding, sign-in and settings screens against the distilled App Store and Play checklists, optionally screenshots them on the simulator, and returns a table of findings - likely rejection, fix before submit, fine - each with the guideline id and file:line. Fix the first two groups, then ask it to run again.

5. Submit

Build and submit the way Ship to TestFlight set up:

bunx eas-cli build --profile production --platform all
bunx eas-cli submit --platform all

Paste the demo account and a specific description of what is new into the review notes (App Store Review 2.3.1 rejects generic ones), then submit for review.

Congrats 🎉

You submitted with every predictable rejection already handled and a report you can hand to whoever asks why a screen looks the way it does. If a reviewer still comes back with something, the reply cites the guideline they name - run the skill again with their message and it will tell you which finding it maps to. Next: keep users current without another review with Your first update.

On this page

Get ReadyNative