Published on

Adding PWA to Next.js with App Directory — Simple Guide

  • Name
Adding PWA to Next.js with App Directory — Simple Guide

Adding PWA to Next.js with App Directory — Simple Guide


PWA or Progressive Web App is a type of web application that makes use of modern web capabilities to deliver a more native app-like experience to users. PWAs aim to combine the best of web and native apps.

In this guide, we will see how we can make our Next.js with AppDir a PWA!

If you want to implement PWA using @Serwist, visit the following article:

Activating PWA in Next.js 13+ App Directory Using @Serwist — Simple Guide

Benefits of PWA:

There are a lot of benefits to using PWA and some of them are:

  1. Offline Access: Offline access is one of the biggest benefits as PWAs can work offline or in low-network conditions using service workers to cache essential assets and data.
  2. App-Like: PWAs are built to mimic native app interactions, making the user experience feel fluid and intuitive.
  3. Push Notifications: Just like native apps, PWAs can send push notifications to the end users.
  4. Discoverable: PWAs can be discovered by search engines, which is a significant advantage over native applications as inherently PWAs are web apps.
  5. Installable: Users can “install” a PWA on their device’s home screen without going through an app store, which makes the distribution more direct.
  6. Automatic Updates: PWAs update automatically when the user accesses them, ensuring that users always see the latest version without needing to go through an app store update process.

and much more…

Companies Using PWA:

To mention some of the companies that are using PWA:

  1. AliExpress
  2. Twitter Lite
  3. Forbes

and much more… 


Adding PWA support to Next.js:

Step 1 — Create the Next.js App:

To create a new Next.js Project run the following command:

    npx create-next-app@latest

Choose the prompts accordingly:

What is your project named? next-with-pwa
Would you like to use TypeScript? Yes
Would you like to use ESLint? Yes
Would you like to use Tailwind CSS? Yes
Would you like to use `src/` directory? Yes
Would you like to use App Router? (recommended) Yes
Would you like to customize the default import alias (@/*)? No

If you already have a Next project go to the next step.

Step 2 — Add the Required Package:

Now install the following package:

npm i @ducanh2912/next-pwa

Step 3 — Configure the Package:

Configure your next.config.js like:

const withPWA = require("@ducanh2912/next-pwa").default({
  dest: "public",
  cacheOnFrontEndNav: true,
  aggressiveFrontEndNavCaching: true,
  reloadOnOnline: true,
  swcMinify: true,
  disable: process.env.NODE_ENV === "development",
  workboxOptions: {
    disableDevLogs: true,
  // ... other options you like

/** @type {import('next').NextConfig} */
const nextConfig = {
  // ... other options you like

module.exports = withPWA(nextConfig);

You can add or remove options by using the following documentation:

> Docs - Next PWA

Step 4 — Add manifest.json to your app:

Go to /public folder of your app and create manifest.json with the following structure:

  "id": "any_id",
  "name": "Next.js PWA - Tutorial",
  "short_name": "Next PWA",
  "description": "This next.js app is a PWA.",
  "icons": [
      "src": "./logo72x72.png",
      "sizes": "72x72",
      "type": "image/png"
      "src": "./logo192x192.png",
      "sizes": "192x192",
      "type": "image/png"
      "src": "./logo384x384.png",
      "sizes": "384x384",
      "type": "image/png"
      "src": "./logo512x512.png",
      "sizes": "512x512",
      "type": "image/png"
  "theme_color": "#FFFFFF",
  "background_color": "#FFFFFF",
  "start_url": "/",
  "scope": ".",
  "display": "standalone",
  "orientation": "portrait"

Step 5 — Registering manifest.json in Metadata:

Update your layout.tsx/layout.jsx to register the manifest file in the metadata:

import { Metadata } from "next";
// ... other imports

export const metadata: Metadata = {
  manifest: "/manifest.json", // we are accessing our manifest file here
  title: "...",
  // ... other options    

const RootLayout = ({ children }: { children: React.ReactNode }) => {
  return (
    <html lang="en">

export default RootLayout;

Step 6 — Update the .gitignore file:

# all other ignore list

There is no further step and we are done here. Happy coding!