DEV Community 👩‍💻👨‍💻

Cover image for Convert Next.js app to PWA
Jatin Sharma
Jatin Sharma

Posted on • Updated on

Convert Next.js app to PWA

To make Next.js app into PWA, we need the given things -

  • next-pwa package
  • Service Worker
  • Manifest & Icons
  • Maskable Icon
  • Meta Tags

1. next-pwa package

To convert your nextjs app into PWA you need to install this package via npm or yarn
to install this run -

npm i next-pwa # npm
yarn add next-pwa # yarn
Enter fullscreen mode Exit fullscreen mode

After installation go to your next next.config.js as update it as follows -

// next.confg.js

const withPWA  = require("next-pwa");
module.exports = withPWA({
 //...before
  pwa: {
    dest: "public",
    register: true,
    skipWaiting: true,
  },
  //...after
});

Enter fullscreen mode Exit fullscreen mode

2. Service Worker

We don't need to add external service worker the next-pwa will take care of that and it will auto generate the sw.js for us so we don't need to do anything in that

├── public
|  ├── sw.js
Enter fullscreen mode Exit fullscreen mode

3. Manifest and Icons

To gernerate Icon and Manifest Go to PWA Manifest

manifes

Fill all the details and attach the icon in 512x512 it will generate the icons and manifest for you and you can download the zip file.

Go to your public directory and create a folder icons and put all the icons in that folder like this

├── public
|  ├── icons
|  |  ├── icons.png
Enter fullscreen mode Exit fullscreen mode

after that create a manifest.json in you public/ which should be look like this -

// manifest.json

{
  "theme_color": "#000",
  "background_color": "#fff",
  "display": "standalone",
  "scope": "/",
  "start_url": "/",
  "name": "pwa",
  "short_name": "pwa",
  "description": "pwa",
  "icons": [
    {
      "src": "icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "icons/icon-256x256.png",
      "sizes": "256x256",
      "type": "image/png"
    },
    {
      "src": "icons/icon-384x384.png",
      "sizes": "384x384",
      "type": "image/png"
    },
    {
      "src": "icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

After that we need the favicon to get that go to Favicon Generator and upload your main icon and it will generate the rest of icon for you and download the zip after that from that we need only need two icon which is favicon.ico and apple-touch-icon put them into your public/

Here is the path -

├── public
|  ├── apple-touch-icon.png
|  ├── favicon.ico
|  ├── icons
|  |  ├── icon-192x192.png
|  |  ├── icon-256x256.png
|  |  ├── icon-384x384.png
|  |  ├── icon-512x512.png
|  |  └── maskable.png
|  ├── manifest.json
Enter fullscreen mode Exit fullscreen mode

4. Maskable Icon

To make the maskabel icon we need to visit Maskable Editor and upload your icon and edit it
masakable

after editing export the icon but be care full with the ratio
always choose the square ration and remember the ratio because we will need it in the manifest
sizes

After downloading the icon put it into the public/icons/

├── public
|  ├── icons
|  |  └── maskable.png
Enter fullscreen mode Exit fullscreen mode

and add that to the manifest.json

// manifest.json

"icons": [

// ...
    {
      "src": "maskable.png",
      "sizes": "48x48",      
      "type": "image/x-icon",
      "purpose": "maskable"
    },

//...
]
Enter fullscreen mode Exit fullscreen mode

Here you need to specify the size of the maskable image if the image size is 512x512 then in the json it should be "sizes": "512x512"

5. Meta Tags

Now to get all this work we need some meta tags put them wher is the Head of your application, which are given below

// index.js

<Head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  <meta name="description" content="description of your project" />
  <meta name="theme-color" content="#000" />
  <title>Title of the project</title>
  <link rel="manifest" href="/manifest.json" />
  <link rel="shortcut icon" href="/favicon.ico" />
  <link rel="apple-touch-icon" href="/apple-icon.png"></link>
</Head>;

Enter fullscreen mode Exit fullscreen mode

After all that Go to the Developer Console and Generate Resport for PWA in Lighthouse you will see the PWA and installable badge.

PWA

You need to push your website with https you can use Vercel or Netlify

Top comments (2)

Collapse
 
diegoazevedo profile image
Diego Azevedo

Thank you, your post helped me!
Now I need to learn how to control the material that is downloaded 😀

I had trouble with next.config.mjs because I'm using nextMDX, in the end everything went well, my next.config.mjs file looked like this:

import nextMDX from '@next/mdx'
import { remarkPlugins } from './mdx/remark.mjs'
import { rehypePlugins } from './mdx/rehype.mjs'
import { recmaPlugins } from './mdx/recma.mjs'
import withPWA from 'next-pwa'

const isProduction = process.env.NODE_ENV === 'production'
import runtimeCaching from 'next-pwa/cache.js'

const withMDX = nextMDX({
  options: {
    remarkPlugins,
    rehypePlugins,
    recmaPlugins,
  },
})

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'mdx'],
  experimental: {
    scrollRestoration: true,
  },
}

const nextMdxConfig = withMDX(
  withPWA({
    dest: 'public',
    disable: !isProduction,
    runtimeCaching,
  })(nextConfig)
)

export default nextMdxConfig

Enter fullscreen mode Exit fullscreen mode
Collapse
 
j471n profile image
Jatin Sharma

I am glad it helped you.

Timeless DEV post...

How to write a kickass README

Arguably the single most important piece of documentation for any open source project is the README. A good README not only informs people what the project does and who it is for but also how they use and contribute to it.

If you write a README without sufficient explanation of what your project does or how people can use it then it pretty much defeats the purpose of being open source as other developers are less likely to engage with or contribute towards it.