Capacitor

Ionic Capacitor is another way to wrap an existing web app in a native iOS, Android, or desktop shell -- but where React Native WebView typically points at your live, deployed URL, Capacitor instead bundles your own static build of the app directly inside the native binary and loads it locally, and gives you a plugin system for reaching real native device APIs from your web code.

Capacitor wraps your static export, not a live URL

Because Capacitor loads the app's HTML/CSS/JS from local files packaged into the native app, it needs a fully static build -- there's no server running at runtime to handle Server Components, Server Actions, or Route Handlers. That means the Next.js app has to be built with output: 'export' in next.config.js, producing a plain out/ folder of static HTML, exactly as described in the static export chapter. See Static Export for what that mode does and does not support (dynamic routes need generateStaticParams, Route Handlers must be static, no server-side rendering at request time, and so on).

Enable static export in next.config.js, then run Capacitor's init and sync commands to copy the exported output into native iOS and Android projects.
next.config.ts:
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  output: 'export', // required: Capacitor needs a static build, not a Node server
  images: {
    unoptimized: true, // the Image Optimization API needs a server; disable it for export
  },
}

export default nextConfig

terminal:
npm install @capacitor/core @capacitor/cli
npx cap init "My App" com.example.myapp

npm run build          # runs `next build`, producing the ./out folder
npx cap add ios
npx cap add android
npx cap sync           # copies ./out into the native projects
npx cap open ios       # or: npx cap open android


webDir points at the static export output

Capacitor's own config file needs to know where your static build lives so it knows what to copy into the native shell on every npx cap sync.


capacitor.config.ts:
import type { CapacitorConfig } from '@capacitor/cli'

const config: CapacitorConfig = {
  appId: 'com.example.myapp',
  appName: 'My App',
  webDir: 'out', // Next.js's static export output folder
  server: {
    // Optional, and mainly useful during development: point the shell at
    // a live dev server instead of the bundled static files so you get
    // hot reload while iterating.
    // url: 'http://192.168.1.10:3000',
    // cleartext: true,
  },
}

export default config


Native API access via plugins

This is Capacitor's main advantage over a plain WebView: official and community plugins expose native functionality to your web code through a consistent, promise-based JavaScript API, without you having to hand-write a native message bridge for each capability. Common plugins include camera access, filesystem read/write, push notifications, geolocation, and haptics.

Plugins are installed as regular npm packages and called directly from a Client Component -- the plugin's JS layer talks to the native implementation for you.
terminal:
npm install @capacitor/camera
npx cap sync

app,photo-button.tsx:
'use client'

import { Camera, CameraResultType } from '@capacitor/camera'

export default function PhotoButton() {
  async function takePhoto() {
    const photo = await Camera.getPhoto({
      resultType: CameraResultType.Uri,
      quality: 90,
    })
    console.log(photo.webPath)
  }

  return <button onClick={takePhoto}>Take Photo</button>
}


Capacitor vs. react-native-webview

What it loadsCapacitor: your own static export, bundled into the app and loaded locally. react-native-webview: typically your live, deployed URL, loaded over the network each time (see React Native WebView).
Offline behaviorCapacitor apps work offline by default for anything that doesn't need a live API, since the UI itself ships inside the binary. A WebView app is unusable offline unless you separately add a service worker or WebView caching.
Native API accessCapacitor has a real plugin ecosystem with a consistent JS API. A WebView needs manual, one-off postMessage bridging for each native capability you want to expose.
Keeping content freshA WebView always shows your latest deployed site with no extra work. A Capacitor app's bundled UI only updates when you rebuild, resync, and resubmit to the app stores (though it can still fetch live data from your API at runtime, and Capacitor's optional live-update services exist to soften this).
ConstraintsCapacitor forces a static export -- no Server Components, Server Actions, or dynamic Route Handlers at runtime. A WebView has no such constraint since it just loads whatever your Next.js server renders, static or dynamic.

In short: reach for react-native-webview when you want the least new code and are fine always showing the live site over the network; reach for Capacitor when you want that same "wrap the web app" approach but with real offline behavior and native device API access, and you're willing to work within static export's constraints. If neither is enough -- you need native navigation, native performance, or native APIs Capacitor doesn't cover -- that's the point to consider a full React Native app instead.