PWANext.jsMobile

Shipping installable PWAs with Next.js 16: the 2026 guide

What it takes to ship a real, installable PWA on Next.js 16 today. Manifest, icons, service worker, push notifications, and the iOS quirks that trip teams up. With Quicktalog as the worked example.

By Reactify Solutions10 min read
Shipping installable PWAs with Next.js 16: the 2026 guide

A PWA is a website that can install itself onto your home screen. On iOS and Android, an installed PWA launches in its own window, works offline if you built it to, and can receive push notifications. Done right, users will not know it is not a native app. This guide covers what you need to ship a real, installable PWA in Next.js 16 today.

Why a PWA instead of React Native

Three reasons we still reach for PWAs in 2026:

  • Distribution is a URL. No App Store review. No TestFlight. Ship, share a link, users install.
  • One codebase, three platforms. Your existing Next.js app is most of the way there.
  • Updates are instant. Push a deploy, every user is on the new version on their next open.

The tradeoff is platform integration. iOS still does not support every Web Push feature. Some native APIs, like rich widgets or complex background processing, are limited or missing in browsers. For content, tools, and most business apps, a PWA is plenty. For a game or a deeply integrated system app, it is not.

What makes an app installable

A web app becomes installable when it has:

  • A web manifest with the right fields.
  • A service worker registered on the page.
  • HTTPS, or localhost for development.
  • Proper icons at the sizes iOS and Android expect.

Miss any of these and the install prompt will not appear.

The manifest, the Next.js way

In App Router, the manifest is a file at app/manifest.ts. No JSON file, no link tag in the head. Next.js picks it up automatically and serves it at /manifest.webmanifest.

app/manifest.ts
typescript
import { MetadataRoute } from "next";

export default function manifest(): MetadataRoute.Manifest {
  return {
    name: "Reactify Solutions",
    short_name: "Reactify",
    description: "Web, mobile, AI, and analytics for modern businesses.",
    start_url: "/",
    display: "standalone",
    background_color: "#000000",
    theme_color: "#1b998b",
    icons: [
      {
        src: "/icon-192x192.png",
        sizes: "192x192",
        type: "image/png",
      },
      {
        src: "/icon-512x512.png",
        sizes: "512x512",
        type: "image/png",
      },
      {
        src: "/icon-maskable-512x512.png",
        sizes: "512x512",
        type: "image/png",
        purpose: "maskable",
      },
    ],
  };
}

Three fields do the heavy lifting:

  • display: "standalone" is what makes the app open without browser chrome.
  • start_url: "/" controls what loads on launch. Match the entry screen of your app.
  • icons must include a 192x192 and 512x512 at minimum, and the maskable purpose for Android adaptive icons.

Icons, where iOS makes you work

Android is forgiving. iOS is not. For a clean install experience on iPhone:

  • 180x180 apple-touch-icon in app/apple-icon.png. Next.js picks it up automatically.
  • A splash screen for each iPhone resolution, linked via apple-touch-startup-image meta tags.
  • A transparent-background icon will show a black background on iOS. Use a solid fill.

Yes, it is more work than Android. No, you cannot skip it without your app looking broken on iPhone.

Service workers without losing a week

For most Next.js apps, the right answer is Serwist or next-pwa plugins. Both wrap Workbox, which handles the annoying parts of service worker lifecycle, cache management, and update flow.

Pick a caching strategy per route type:

  • Static assets (JS, CSS, images): cache-first with a long expiry. They are hashed, so cache misses are not a concern.
  • HTML pages: stale-while-revalidate. Users get an instant response and the next visit is fresh.
  • API calls: network-first with a short timeout, falling back to cache if offline.

Resist the urge to cache everything. Users hate stale data more than they hate loading spinners.

Push notifications

Web Push works on Chrome, Firefox, and since iOS 16.4 on Safari for installed PWAs. The flow has four steps.

  1. Ask permission with Notification.requestPermission().
  2. Subscribe to the push service with your VAPID public key.
  3. Save the subscription server-side.
  4. Send push payloads via the web-push library from Node.
lib/push.ts
typescript
// client: subscribe
async function subscribeToPush() {
  const registration = await navigator.serviceWorker.ready;
  const subscription = await registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY,
  });
  await fetch("/api/push/subscribe", {
    method: "POST",
    body: JSON.stringify(subscription),
  });
}

// server: send
import webPush from "web-push";

webPush.setVapidDetails(
  "mailto:ops@reactify-solutions.com",
  process.env.VAPID_PUBLIC_KEY!,
  process.env.VAPID_PRIVATE_KEY!,
);

export async function sendPush(subscription: webPush.PushSubscription, body: string) {
  await webPush.sendNotification(subscription, body);
}

iOS quirks to remember:

  • Only installed PWAs can receive push. A browser tab cannot.
  • The user must interact with the page before the permission prompt can fire.
  • Silent notifications are not supported.

Install prompts

On Android, you can show a custom install button by capturing the beforeinstallprompt event:

components/InstallButton.tsx
tsx
"use client";
import { useEffect, useState } from "react";

export function InstallButton() {
  const [evt, setEvt] = useState<any>(null);

  useEffect(() => {
    const handler = (e: Event) => {
      e.preventDefault();
      setEvt(e);
    };
    window.addEventListener("beforeinstallprompt", handler);
    return () => window.removeEventListener("beforeinstallprompt", handler);
  }, []);

  if (!evt) return null;

  return (
    <button onClick={() => evt.prompt()}>Install this app</button>
  );
}

On iOS there is no programmatic prompt. Users install via Safari's Share menu, then "Add to Home Screen." Your job is to tell them that, preferably only when you are sure they are on iOS and not already installed.

Offline strategy

True offline support is more than caching. Decide what your app should do when the network is gone:

  • Read-only content: cache pages, show them offline. Easy.
  • Forms and writes: queue the submission and replay it when the network comes back. Background Sync helps on Chrome. On iOS, you are on your own.
  • Realtime-critical features: show a clear offline state and disable them. Do not pretend.

Most apps need a thin offline layer, not a full offline-first architecture.

Testing

Before you ship, run:

  • Lighthouse PWA audit in Chrome DevTools. It will flag every missing manifest field.
  • Real device install on iPhone and Android. Emulators lie about install behavior.
  • Airplane mode test. Toggle offline and see what breaks.
  • Update test. Deploy a new version and verify the service worker picks it up. This is where most PWAs silently fail.

A worked example: Quicktalog

Quicktalog is a PWA. We did not build it as one. We made it installable after the fact because half our users asked for "an app." The work came in three chunks:

  1. One day to add the manifest, icons, and a minimal service worker.
  2. Half a day to add the install prompt and the iOS instructions.
  3. Two days to handle push notifications and the offline-friendly catalog viewer.

The conversion rate on the install prompt sits around 8%. For an app distributed as a link, on a product used by 1,400+ businesses, that is meaningful retention.

When to go native instead

Reach for React Native or native when you need:

  • Widgets, Siri shortcuts, or deep Apple Wallet integration.
  • Background tasks that run without the app open for long stretches.
  • A UI that needs frame-perfect platform-native feel.

Everything else, try a PWA first. Shipping is faster, the team stays smaller, and the maintenance story is the same as your web app.

If you are weighing PWA against React Native for a product you are about to build, we would be happy to compare notes.

ready when you are

Want to build something amazing? Let's bring it to life.

At Reactify Solutions, we turn your ideas into exceptional applications. From concept to deployment, we are here to make your vision a reality.