- Home
- Skills
- Frontend & Web Apps
- pwa nextjs
pwa nextjs
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
Works with the AI Agents you already use
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: addedid,scope, the maskable icon and the self-referencingrelated_applicationsentry.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.jsandpublic/offline.html: worker with afetchhandler and a static offline page.app/layout.tsx: inline<script>in<head>that capturesbeforeinstallpromptbefore 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
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-referencingrelated_applicationsentry thatgetInstalledRelatedApps()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
fetchhandler 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>. AuseEffectlistener, andnext/scriptwithbeforeInteractive, both miss the event when Chrome fires it during hydration. - Install button that does not wait for
beforeinstallpromptto 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, orproxy.tson Next 16) so auth redirects do not swallow/manifest.webmanifestand/sw.js. - iOS metadata without duplicated meta tags.
How it works
- Build all seven pieces together. A PWA that is four-fifths done installs nowhere.
- Add the capture script to the root layout and mount the registration component.
- Exempt the manifest, the worker and the offline page from auth, then confirm protected routes still redirect.
- Run
verify-pwa.mjsagainst 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/testand 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 withconvert. 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