Next.js is my favorite JavaScript framework. It allows you to quickly build fully functional React-powered websites with amazing routing, support for SSR, and an excellent developer experience.

Next.js is also a great tool to build mobile experiences. Combined with a component library such as Material UI, you can create web apps that feel (almost) native.

To submit your Next.js apps to the Apple App Store / Google Play Store you'll need to package them in a real app. Capacitor is an elegant way of doing this. The fine folks behind Ionic created it, and it's the successor to Cordova (and PhoneGap).

Besides just packaging Capacitor also allows you to access platform-specific features through plugins.

Installing Capacitor

Installing Capacitor is as easy as typing:

cd my-app
npm install @capacitor/core @capacitor/cli
npx cap init --web-dir=out   

Building your Next.js app

After installing Capacitor in your Next.js project, you can simply build and export your project: npx next build && npx next export.

This will output your project into a folder called out. If you forgot to pass --web-dir to npx cap init you can include this folder in your Capacitor project by setting webDir in capacitor.config.json.

After this, you add the platforms you want to support:

npx cap add android
npx cap add ios

(Electron is also a supported platform)

Each time you build your app you'll want to copy the assets over to your iOS/Android projects by typing: npx cap sync.

An easy way to automate these steps is by including them in the scripts section of package.json:

  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "export": "next export",
    "build-mobile": "next build && next export && npx cap sync"

Opening and running your project

Opening the project inside Xcode or Android Studio is as easy as:

npx cap open android
npx cap open ios

You can now run your app.

404's in Android

The first time I ran my project on Android, it didn't work. I got 404's on all my resources. After a lot of debugging, I discovered that Android Studio doesn't copy assets starting with an underscore, like _next.

To fix this, find your app's build.gradle and add ignoreAssetsPatern inside Android>defaultConfig>aaptOptions:

android {
    defaultConfig {
        aaptOptions {
            ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~'

This will give you a working Next.js app inside a native app!