# Add PWA support to web frameworks

> Add a manifest and service worker to Next.js, Nuxt, SvelteKit, or Angular, then detect registration support and retain an online fallback.

This guide adds a web app manifest and a service worker to projects built with Next.js, Nuxt, SvelteKit, or Angular. Each framework keeps its own build integration, while the browser-facing result uses the same manifest and Service Worker APIs.

MDN marks the Service Worker API as widely available. Registration requires a secure context, and browsers treat `localhost` as secure for local development. The examples therefore keep the application usable over the network when registration is absent or fails.

## Examples

Choose the subsection for the framework that owns the application's build, then use the final subsection to preserve an online path when browser registration is unavailable.

### Add a manifest route in Next.js App Router

Next.js provides a typed manifest route through `app/manifest.ts`. Its PWA guide creates a custom service worker at `lib/service-worker.js` and registers it from a client component with `new URL("../lib/service-worker.js", import.meta.url)`.

Create the manifest with the fields used by the application. Put the referenced icon files in `public/`.

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

export default function manifest(): MetadataRoute.Manifest {
  return {
    name: "Field Notes",
    short_name: "Notes",
    start_url: "/",
    display: "standalone",
    background_color: "#ffffff",
    theme_color: "#12372a",
    icons: [
      { src: "/icon-192.png", sizes: "192x192", type: "image/png" },
      { src: "/icon-512.png", sizes: "512x512", type: "image/png" },
    ],
  };
}
```

Add `lib/service-worker.js`, then use the Next.js registration example below for capability detection and failure handling.

### Configure the Nuxt module

The Nuxt modules directory documents `@vite-pwa/nuxt` for Nuxt 3. Add the module, then put manifest data under `pwa`.

Install it with `npx nuxi@latest module add @vite-pwa/nuxt`, then keep the configuration in `nuxt.config.ts`.

```ts
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ["@vite-pwa/nuxt"],
  pwa: {
    registerType: "autoUpdate",
    manifest: {
      name: "Field Notes",
      short_name: "Notes",
      start_url: "/",
      display: "standalone",
      theme_color: "#12372a",
      icons: [
        { src: "/icon-192.png", sizes: "192x192", type: "image/png" },
        { src: "/icon-512.png", sizes: "512x512", type: "image/png" },
      ],
    },
  },
});
```

The module generates the service worker and injects the web app manifest from this configuration.

### Configure the SvelteKit plugin

The Vite PWA integration for SvelteKit supplies `SvelteKitPWA`. Its documentation configures the plugin in `vite.config.ts` and exposes manifest markup through `virtual:pwa-info`.

Install `@vite-pwa/sveltekit` as a development dependency, then add the plugin after `sveltekit()`.

```ts
// vite.config.ts
import { sveltekit } from "@sveltejs/kit/vite";
import { SvelteKitPWA } from "@vite-pwa/sveltekit";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [
    sveltekit(),
    SvelteKitPWA({
      manifest: {
        name: "Field Notes",
        short_name: "Notes",
        start_url: "/",
        display: "standalone",
        theme_color: "#12372a",
        icons: [
          { src: "/icon-192.png", sizes: "192x192", type: "image/png" },
          { src: "/icon-512.png", sizes: "512x512", type: "image/png" },
        ],
      },
    }),
  ],
});
```

Add the generated manifest link to the root layout as documented by the plugin.

```svelte
<!-- src/routes/+layout.svelte -->
<script>
  import { pwaInfo } from "virtual:pwa-info";
  $: webManifestLink = pwaInfo ? pwaInfo.webManifest.linkTag : "";
</script>

<svelte:head>
  {@html webManifestLink}
</svelte:head>
```

The empty-string fallback leaves the layout valid when the virtual module has no manifest information.

### Run the Angular schematic

Angular's `@angular/pwa` schematic adds the service-worker package, build support, registration, manifest link, icons, and `ngsw-config.json`.

Apply the schematic from the project directory and create a production build.

```bash
ng add @angular/pwa
ng build
```

Review the generated `manifest.webmanifest`, icons, and `ngsw-config.json` rather than treating their starter values as application metadata. Angular's guide uses a production configuration when demonstrating the service worker locally.

### Register the Next.js worker and preserve the network path

Framework plugins automate build output, but the browser still exposes service-worker capability through `navigator.serviceWorker`. This Next.js Client Component follows the framework guide's worker URL and leaves normal network navigation in place when registration is unavailable or fails.

Save the component as `app/service-worker-registration.tsx`, alongside the `lib/service-worker.js` file named above, and render `<ServiceWorkerRegistration />` from a layout or page.

```tsx
// app/service-worker-registration.tsx
"use client";

import { useEffect, useState } from "react";

export default function ServiceWorkerRegistration() {
  const [status, setStatus] = useState("Checking service worker support…");

  useEffect(() => {
    if (!("serviceWorker" in navigator)) {
      setStatus("Service worker registration is unavailable; the app remains online.");
      return;
    }

    let cancelled = false;

    navigator.serviceWorker
      .register(
        new URL("../lib/service-worker.js", import.meta.url),
        { scope: "/", updateViaCache: "none" },
      )
      .then(() => {
        if (!cancelled) setStatus("Service worker registration is ready.");
      })
      .catch((error) => {
        if (!cancelled) {
          setStatus("Service worker registration failed; the app remains online.");
        }
        console.error(error);
      });

    return () => {
      cancelled = true;
    };
  }, []);

  return <p role="status">{status}</p>;
}
```

Use this direct registration for the Next.js custom worker. Nuxt and SvelteKit plugins, and Angular's schematic, provide their own registration path; keep the same support and error states in the interface they initialize.

:::caution
The [Angular service worker guide](https://angular.dev/ecosystem/service-workers/getting-started) documents that its worker can serve an installed application version while an update is available. Test a second deployment and choose an update experience instead of assuming a refresh immediately returns the newest files.
:::

## See also

- [Getting started](/guides/getting-started/)
- [Offline support](/guides/offline/)
- [Update strategies](/guides/update-strategies/)
- [How to build a Progressive Web Application with Next.js](https://nextjs.org/docs/app/guides/progressive-web-apps) (nextjs.org)
- [Getting started with Angular service workers](https://angular.dev/ecosystem/service-workers/getting-started) (angular.dev)