React Native WebView

If your Next.js site is already built, already deployed, and you mainly want an icon in the Apple App Store and Google Play Store rather than a rebuilt native UI, the react-native-webview package is the fastest way to get there. It gives you a <WebView> component -- a native view that embeds a full browser engine (WKWebView on iOS, the system WebView on Android) -- and you point it at your live, deployed Next.js URL. The React Native app itself is just a thin native frame around your existing website.

This is different from a plain PWA install (see Progressive Web App) mainly in distribution: a WebView app is a real binary you submit to the app stores, so it shows up in store search and can be installed the way users expect a "real app" to be installed, even though under the hood it's still rendering your web app's HTML and JavaScript.

Basic usage

At minimum, a WebView-based app is a single screen whose entire body is a <WebView> pointed at a URL. Everything else -- navigation, state, data fetching -- continues to be handled by your Next.js app running inside the WebView, exactly as it would in a mobile browser tab.

Install the package into an Expo or bare React Native project, then render a full-screen <WebView> pointed at your deployed site.
terminal:
npx expo install react-native-webview

App.tsx:
import { SafeAreaView, StyleSheet } from 'react-native'
import { WebView } from 'react-native-webview'

export default function App() {
  return (
    <SafeAreaView style={styles.container}>
      <WebView
        source={{ uri: 'https://www.example-nextjs-app.com' }}
        style={styles.webview}
        pullToRefreshEnabled
        startInLoadingState
      />
    </SafeAreaView>
  )
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  webview: { flex: 1 },
})

For most sites this basic setup already covers navigation -- clicking a link inside the WebView just loads the next page of your Next.js app inside the same WebView, the same way it would in a normal browser tab. If you need to react to navigation from the native side (to update a native tab bar title, for example), the onNavigationStateChange prop reports the current URL.

A minimal JS bridge lets the web page talk back to the native shell when you do need some native behavior -- for example, triggering a native share sheet from a button in your Next.js UI.
App.tsx:
import { WebView } from 'react-native-webview'
import { Share } from 'react-native'

<WebView
  source={{ uri: 'https://www.example-nextjs-app.com' }}
  onMessage={(event) => {
    const data = JSON.parse(event.nativeEvent.data)
    if (data.type === 'SHARE') {
      Share.share({ message: data.url })
    }
  }}
/>

app,share-button.tsx (in the Next.js app):
'use client'

export default function ShareButton({ url }: { url: string }) {
  const isInNativeShell = typeof window !== 'undefined' && 'ReactNativeWebView' in window

  if (!isInNativeShell) return null // hide when viewed as a normal web page

  return (
    <button
      onClick={() =>
        (window as any).ReactNativeWebView.postMessage(
          JSON.stringify({ type: 'SHARE', url })
        )
      }
    >
      Share
    </button>
  )
}


Tradeoffs vs. a "real" React Native app

Faster to shipLittle to no UI code to write -- you're reusing your entire existing Next.js app as-is. A working app-store submission can happen in a day.
Feels less nativeScrolling physics, transitions, and text rendering come from the web engine, not the platform's native UI toolkit, so it rarely feels indistinguishable from a fully native app to attentive users.
No native API access by defaultCamera, filesystem, Bluetooth, and similar APIs aren't reachable from inside the WebView's web content. You can bridge specific capabilities across with postMessage / onMessage as shown above, but each one is manual, one-off wiring -- there's no general plugin ecosystem like Capacitor's (see Capacitor).
Network-dependentBecause the WebView loads your live, deployed URL, the app is unusable offline unless you separately add caching -- either the PWA service worker described in Progressive Web App (which the WebView's browser engine will still honor), or WebView-level caching via its cacheEnabled prop.


When this approach makes sense

Reach for react-native-webview when the goal is specifically an app-store presence for a site that already exists and is already deployed, and you don't need deep native API access or native-feeling animations -- a marketing site, a content site, an internal tool, or a first version of a product where "listed in the app stores" matters more than "feels perfectly native." Invest in full React Native instead once native performance, native navigation, or non-trivial native device integration become real product requirements -- at that point the amount of custom bridging code a WebView needs starts to rival the cost of just building native screens.