June 30, 2025
O. Wolfson
Progressive Web Apps offer app-like experiences directly in the browser: installable, offline-capable, and fast. With Next.js 15 and its App Router, you can turn a basic web app into a minimal PWA in just a few steps—no push notifications, no extras, just the core requirements.
Code: Minimal PWA with Next.js 15
Deployed: Minimal PWA with Next.js 15
If you don’t have a Next.js project yet:
shnpx create-next-app@latest my-minimal-pwa
cd my-minimal-pwa
Create the manifest file at app/manifest.json (not in /public, not /src/app):
json{
"name": "Minimal Next.js PWA",
"short_name": "MinimalPWA",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#317EFB",
"icons": [
{
"src": "/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
Tip: The manifest must include at least one 192x192 and one 512x512 PNG icon (add these to
/public).
Place your icons in /public:
/public/icon-192x192.png/public/icon-512x512.pngYou can generate these with realfavicongenerator.net or any image editor.
Create a file /public/sw.js:
js// public/sw.js
self.addEventListener("install", () => self.skipWaiting());
self.addEventListener("activate", () => self.clients.claim());
This is a no-op (doesn’t cache files), but registers the service worker, which is required for installability.
Create a simple registration component:
components/sw-register.tsx
tsx"use client";
import { useEffect } from "react";
export default function SWRegister() {
useEffect(() => {
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("/sw.js");
}
}, []);
return null;
}
Edit app/layout.tsx:
tsximport SWRegister from "@/components/sw-register";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<head>
<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="#317EFB" />
</head>
<body>
<SWRegister />
{children}
</body>
</html>
);
}
Edit app/page.tsx:
tsxexport default function Page() {
return (
<main>
<h1>Minimal Next.js PWA</h1>
<p>This is the simplest possible PWA using Next.js 15.</p>
</main>
);
}
pnpm dev or npm run dev./public/ so they’re accessible at the root.This is the absolute minimum you need for a true PWA in Next.js 15: manifest.json, two icons, a minimal service worker, and one registration component. From here, you can expand to add whatever features your users need—offline support, install prompts, push notifications, and more.