App is not merely a web view wrapper around a website
Why it matters
Apple's guideline 4.2 requires apps to offer functionality beyond what a mobile web browser can provide. A root <WebView> loading your website URL — or a tab navigator where every tab is a WebView — provides exactly zero native value and is rejected routinely. Google Play applies the same standard. Beyond rejection: a WebView wrapper offers worse performance than Safari/Chrome, no access to native APIs, broken back-button behavior on Android, and user interfaces that feel foreign on mobile. The rejection is not a technicality — the platforms genuinely won't distribute apps that are just website containers.
Severity rationale
High because Apple guideline 4.2 minimum-functionality rejections are applied consistently — any app whose primary content is a WebView loading a URL will be rejected.
Remediation
Replace WebView-based primary content with native components. Start with the root navigator.
// Before (rejected):
export default function HomeScreen() {
return <WebView source={{ uri: 'https://yoursite.com/home' }} style={{ flex: 1 }} />;
}
// After (native):
export default function HomeScreen() {
const { data } = useHomeData();
return (
<ScrollView>
<FlatList data={data} renderItem={({ item }) => <PostCard post={item} />} />
</ScrollView>
);
}
WebViews are permitted for: OAuth flows, in-app help browser, PDF preview, or one specific screen of third-party external content. Every tab in your tab navigator must render native components as its primary content.
Detection
-
ID:
not-web-view-wrapper -
Severity:
high -
What to look for: Count all relevant instances and enumerate each. Look at the root navigator and main screens. If the primary content rendering is one or more
WebViewcomponents loading a URL, this is a web view wrapper. Specifically look for: a root<WebView source={{ uri: 'https://yoursite.com' }} />as the only content; a tab navigator where every tab is aWebViewloading a different URL;WKWebView(iOS) orWebView(Android) as the primary rendering mechanism. Also check forexpo-web-browserbeing used as the app's main content (not just for OAuth or help links). In Flutter, look forWebViewWidgetorInAppWebViewas the root widget. Contrast this with legitimate uses of WebView for: an in-app browser for help docs, OAuth authentication, showing a specific piece of external content. -
Pass criteria: The app's primary content and navigation are rendered using native components (React Native components, Flutter widgets, SwiftUI views, Jetpack Compose composables). At least 1 implementation must be verified. WebView usage is limited to specific, justified uses (OAuth, in-app browser for external content).
-
Fail criteria: The app's core content is entirely or primarily rendered by a
WebViewloading a website URL, with no meaningful native navigation or functionality. -
Skip (N/A) when: Never — all apps must provide meaningful native functionality.
-
Detail on fail:
"App's main screen is a single WebView loading 'https://yoursite.com' — the app is a web view wrapper"or"All 4 tab bar screens render WebView components pointing to website URLs" -
Remediation: Apple guideline 4.2 requires apps to provide functionality beyond what a mobile web browser can offer. Google Play similarly rejects pure web view wrappers.
- Migrate primary content to native components:
- React Native: Replace WebView with native FlatList, ScrollView, and custom components
- Flutter: Use native Material/Cupertino widgets instead of WebView
- Swift/Kotlin: Use native UIKit/SwiftUI or Jetpack Compose
- WebViews are permitted for: OAuth, in-app help browser, previewing external documents, one specific screen of external content
- At minimum, the app must have a meaningful native shell (navigation, authentication, state management) even if some content is web-based
Review the configuration in
src/orapp/directory for implementation patterns. - Migrate primary content to native components:
External references
- external · apple-guideline-4.2-minimum-functionality — Apple App Store Review Guideline 4.2 — Minimum Functionality (no web-view wrappers)
Taxons
History
- 2026-04-18·v1.0.0·Initial import from app-store-review-blockers·automated