pwa nextjs

    1

    Ship an installable Next.js App Router PWA with a reliable install button, safe service worker caching, and a test harness that asks Chrome itself.

    Free

    Security scanned

    Works with the AI Agents you already use

    Claude CodeClaude CodeCursorCursorCodex CLICodex CLIMuseMuseDotsDots+22 more

    pwa nextjs

    Example session with this skill installed

    My Next.js App Router app already has a manifest, but the install button never shows up on Android. Users have to dig through the browser menu. The app has login handled in middleware.ts. Can you make it properly installable and add our own install button?

    • Read your context and instructions
    • Compiled the pwa nextjs
    • Generated the app files

    Why the button never showed up

    Your middleware.ts redirects every anonymous request to /login, including /manifest.webmanifest and /sw.js. Chrome fetches those files without your session, gets the login page, and silently gives up on installability. There was also no service worker with a fetch handler, which Chrome's automatic prompt still requires.

    What I changed

    • middleware.ts: exempted the manifest, the worker and the offline page from auth, each name anchored with $.
    • app/manifest.ts: added id, scope, the maskable icon and the self-referencing related_applications entry.
    • public/icon-192.png, icon-512.png, icon-maskable-512.png, app/apple-icon.png: generated from your logo on an opaque background, maskable checked against the safe zone.
    • public/sw.js and public/offline.html: worker with a fetch handler and a static offline page.
    • app/layout.tsx: inline <script> in <head> that captures beforeinstallprompt before React hydrates, plus the registration component.
    • components/install-button.tsx: renders without waiting for the browser event, hides once the app is installed, and shows "Add to Home Screen" instructions on iOS.

    Middleware matcher

    export const config = {
      matcher: [
        "/((?!_next/static|_next/image|favicon\\.ico$|manifest\\.webmanifest$|sw\\.js$|offline\\.html$|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
      ],
    }
    

    Service worker caching

    API routes are never cached, since this app is behind login. At runtime only /_next/static/ is cached, which is content-hashed and never user-specific. Old caches are deleted on activate, and only successful responses are stored.

    Verification against the production build

    PASS  home page loads
    PASS  chrome reports no installability errors
    PASS  /manifest.webmanifest is served anonymously
    PASS  /sw.js is served anonymously
    PASS  /offline.html is served anonymously
    PASS  /dashboard still requires auth
    PASS  service worker active and controlling
    PASS  install button renders without beforeinstallprompt
    PASS  install button hides when already installed
    PASS  offline navigation falls back to offline.html
    ...
    all green
    

    Next step

    Deploy and open the site on your phone. The button should appear right away. Chrome's own install prompt may still take a few visits, which is why the app has its own button.

    icon-192.png

    ZIP · project files

    Generated

    Example file from a real run - the skill writes it into your workspace.

    Connects securely to your tools. The creator never sees your data.

    About this skill

    Ship an installable PWA on the Next.js App Router in one pass, and find out why the install button does not show up. Chrome has two install paths with different requirements, and most guides describe only one. This skill covers the whole set and checks it against Chrome itself.

    What it does

    • Manifest through app/manifest.ts, including the self-referencing related_applications entry that getInstalledRelatedApps() needs, and no duplicate link tags.
    • Icons: 192, 512 and a separate maskable, plus an iOS apple-icon. ImageMagick commands included, with a preview step that crops the maskable to the real safe zone.
    • Service worker with the fetch handler that Chrome's automatic prompt requires. Runtime caching is limited to /_next/static/, so no API response, avatar or upload from a logged-in user is ever stored.
    • Install prompt capture with an inline <script> in <head>. A useEffect listener, and next/script with beforeInteractive, both miss the event when Chrome fires it during hydration.
    • Install button that does not wait for beforeinstallprompt to render and hides itself for people who already installed. Includes a banner that collapses into a small "Get app" chip, for public apps.
    • Middleware and proxy exemptions (middleware.ts, or proxy.ts on Next 16) so auth redirects do not swallow /manifest.webmanifest and /sw.js.
    • iOS metadata without duplicated meta tags.

    How it works

    1. Build all seven pieces together. A PWA that is four-fifths done installs nowhere.
    2. Add the capture script to the root layout and mount the registration component.
    3. Exempt the manifest, the worker and the offline page from auth, then confirm protected routes still redirect.
    4. Run verify-pwa.mjs against the production build.

    The verification harness

    verify-pwa.mjs boots your production build on a spare port, drives headless Chromium and asks Chrome directly through Page.getInstallabilityErrors. It runs up to 20 checks: manifest parsing, anonymous access to public files, worker state, duplicate meta tags, the install button shown and hidden, and the offline fallback with the server really down. It exits non-zero on failure, so it works in CI. An optional PROTECTED_PATH confirms that auth still redirects.

    Why not just prompt for it

    A generic PWA answer explains the manifest and the worker. It rarely mentions that the browser menu and the automatic prompt have different requirements, that an auth middleware silently redirects the manifest, or that the prompt event can fire before your code is listening. This skill also tells the agent how to measure, so it does not draw conclusions from a bot-protection page or from a server that never actually went down.

    Use cases

    • Making an existing Next.js App Router app installable.
    • Debugging a missing install button or install prompt.
    • Adding a safe offline fallback to an app behind login.
    • Checking PWA installability in CI.

    Requirements and limits

    • Written for the Next.js App Router (15 and 16), verified on Next.js 16.4.0. Not for the Pages Router, Workbox or Vite.
    • The harness needs Node, @playwright/test and Chromium installed in the project (npx playwright install chromium). Linux and macOS only.
    • ImageMagick is needed only to generate icons. The commands use magick (v7); on v6, replace it with convert.
    • getInstalledRelatedApps() works in Chrome only. Elsewhere the button stays visible, by design.
    • Headless Chromium never fires beforeinstallprompt, so the harness proves the button renders without it, not the native prompt itself.

    Source

    MIT licensed. Canonical source and issues: https://github.com/mpena2099/pwa-nextjs-skill

    How to use

    Skills on Agensi run inside your AI agent. Copy the prompt, paste it into your agent, and it connects to Agensi and installs this skill for you. If a payment is needed, your agent shows it to you first.

    Reviews

    No reviews yet

    Be one of the first to try it. Every listed skill passes our trust checks below.

    Security scanned

    Passed our 8-point scan before listing

    Fresh listing

    Recently published to Agensi

    Free forever

    No account required to browse

    Trust & safety

    Security scanned

    Verified clean 4 days ago

    • Free to download with an account

    Requires

    Node.js
    playwright

    Listed4 days ago

    What's inside

    Frequently Asked Questions