# Guideline 4.2 - Design: WebView-Only App With No Native Functionality

**Guideline:** 4.2 · **Store:** Apple App Store · **Risk:** high · **Difficulty:** medium · **Typical turnaround:** 1-2 weeks

Canonical URL: https://appstorereject.com/rejections/apple/4/guideline-42-design-webview-only-app-with-no-native-functionality

## Description

Apple rejected your app under Guideline 4.2 because it is essentially a wrapper around a website with no meaningful native iOS functionality. The app’s primary content is displayed through WKWebView or embedded web pages, and it does not leverage native iOS capabilities like push notifications, offline storage, camera, Siri, widgets, or other platform features. Apple considers such apps better suited as websites or Safari bookmarks rather than standalone App Store listings.

## Common variations

- Entire app is a single WKWebView pointing to a website URL
- App wraps a responsive web app with a navigation bar but adds no native features
- Content is loaded from a CMS via web views with no offline capability
- App is a PhoneGap/Cordova wrapper with no native plugins
- Login screen is native but all other content is web-based
- Tab bar or navigation exists but each tab loads a different web page

## Example rejection email

```
Guideline 4.2 - Minimum Functionality

Your app only includes links, images, or content aggregated from the Internet with limited or no native iOS functionality. Although this content may be useful, it would be more appropriate as a Safari bookmark, web clip, or web app.

Specifically, your app appears to be a repackaged version of a website. The primary interface is a web view that loads content from [your-domain.com] with no additional native features.

Next Steps: We encourage you to build your app using native iOS frameworks and technologies to create a more engaging, responsive user experience that takes advantage of iOS platform capabilities.
```

## Resolution steps

## How to Fix WebView-Only App With No Native Functionality

1. **Rewrite core screens in native SwiftUI or UIKit** — At minimum, convert the primary user-facing screens to native code. The home screen, navigation, lists, and detail views should all be native:

   ```swift
   // Instead of loading a URL in WKWebView, build native views
   List(articles) { article in
       NavigationLink(destination: ArticleDetailView(article: article)) {
           ArticleRowView(article: article)
       }
   }
   ```

2. **Add push notifications** — Register for remote notifications and send timely, relevant alerts. This is one of the clearest signals that an app is native:

   ```swift
   UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound])
   ```

3. **Implement offline functionality** — Cache content locally so the app is useful without an internet connection:
   - Use SwiftData or Core Data for structured content
   - Cache images with URLCache or a library like Kingfisher
   - Show cached content with a “last updated” indicator when offline

4. **Add native iOS features** that a website cannot provide:
   - **Widgets**: Show quick-glance information on the Home Screen
   - **Camera/photo integration**: Let users capture or select images natively
   - **Haptic feedback**: Add tactile responses to interactions
   - **Shortcuts/Siri**: Enable voice-driven actions
   - **Share extension**: Let users share content from other apps into yours

5. **Use native navigation** — Replace web-based navigation with UINavigationController or NavigationStack. Users should feel iOS-native transitions, swipe-back gestures, and standard navigation patterns.

6. **If some web content is necessary**, use it selectively — It’s acceptable to use WKWebView for specific content like terms of service, help articles, or rich HTML emails. The key is that the majority of the app must be native.

7. **Test the “airplane mode test”** — Put your phone in airplane mode and open your app. If it’s completely blank or unusable, you haven’t added enough native functionality.

## Appeal guidance

Appeals are very unlikely to succeed if your app truly is a web view wrapper. Apple’s policy is firm on this. If your app uses web views for specific content but has substantial native features the reviewer missed, reply with a detailed feature list and screenshots of the native components. Otherwise, invest the time in rebuilding core screens natively.

## Before / after examples

**Before:** // Entire app: a single WKWebView
struct ContentView: View {
    var body: some View {
        WebView(url: URL(string: "https://mysite.com")!)
    }
}

struct WebView: UIViewRepresentable {
    let url: URL
    func makeUIView(context: Context) -> WKWebView {
        let webView = WKWebView()
        webView.load(URLRequest(url: url))
        return webView
    }
    func updateUIView(_ uiView: WKWebView, context: Context) {}
}
**After:** // Native app with tabs, offline, and push notifications
@main
struct MyApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate

    var body: some Scene {
        WindowGroup {
            TabView {
                HomeView()          // Native SwiftUI list + search
                    .tabItem { Label("Home", systemImage: "house") }
                FavoritesView()     // Locally persisted favorites
                    .tabItem { Label("Saved", systemImage: "bookmark") }
                NotificationsView() // Push notification history
                    .tabItem { Label("Alerts", systemImage: "bell") }
                SettingsView()      // Native preferences
                    .tabItem { Label("Settings", systemImage: "gear") }
            }
        }
    }
}

// AppDelegate handles push notification registration
// SwiftData models for offline content caching
// WidgetBundle for Home Screen widget
**Why it works:** The single WKWebView was replaced with a fully native TabView-based architecture. Each tab renders native SwiftUI views. Push notifications, offline caching via SwiftData, and a Home Screen widget demonstrate native platform integration that a website cannot replicate.

**Before:** // Web-based content loading — no offline, no native features
func loadContent() {
    webView.load(URLRequest(url: URL(string: "https://api.mysite.com/feed")!))
}
// If offline: blank white screen
**After:** // Native content loading with offline cache
@Observable
class FeedViewModel {
    var articles: [Article] = []

    func loadContent() async {
        // Try network first
        if let remote = try? await APIClient.fetchArticles() {
            articles = remote
            try? SwiftDataStore.cache(remote)  // persist for offline
        } else {
            // Offline fallback — load cached content
            articles = SwiftDataStore.loadCached()
        }
    }
}

// Native list rendering
struct FeedView: View {
    @State var viewModel = FeedViewModel()

    var body: some View {
        List(viewModel.articles) { article in
            ArticleRow(article: article)
        }
        .refreshable { await viewModel.loadContent() }
        .task { await viewModel.loadContent() }
    }
}
**Why it works:** Content is fetched via a native API client and rendered in a SwiftUI List instead of a web view. Articles are cached locally with SwiftData so the app works offline. Pull-to-refresh provides a native interaction pattern that web views cannot match.

## Common questions

**Can you appeal a 4.2 rejection?**

Appeals are very unlikely to succeed if your app truly is a web view wrapper. Apple’s policy is firm on this. If your app uses web views for specific content but has substantial native features the reviewer missed, reply with a detailed feature list and screenshots of the native components. Otherwise, invest the time in rebuilding core screens natively.

**How long does this typically take to fix?**

Typical turnaround is 1-2 weeks (difficulty: medium). After resubmission, most re-reviews complete within 24-48 hours.

---
*Machine-readable source: https://api.appstorereject.com/api/rejections/detail?slug=guideline-42-design-webview-only-app-with-no-native-functionality*