The manifest.json file provides metadata for your PWA, like its name, icons, and theme color.
-
In the root of your
public/folder, create amanifest.jsonfile:// public/manifest.json { "name": "Your App Name", "short_name": "App", "description": "Your app description", "start_url": "/", "display": "standalone", "background_color": "#ffffff", "theme_color": "#ffffff", "icons": [ { "src": "/icons/icon-48x48.png", "sizes": "48x48", "type": "image/png" }, { "src": "/icons/icon-72x72.png", "sizes": "72x72", "type": "image/png" }, { "src": "/icons/icon-96x96.png", "sizes": "96x96", "type": "image/png" }, { "src": "/icons/icon-144x144.png", "sizes": "144x144", "type": "image/png" }, { "src": "/icons/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/icons/icon-256x256.png", "sizes": "256x256", "type": "image/png" }, { "src": "/icons/icon-512x512.png", "sizes": "512x512", "type": "image/png" } ] }
-
Add Icons: Place the required icon files (e.g.,
icon-192x192.png,icon-512x512.png, etc.) in thepublic/iconsdirectory.
In a Next.js App Router project, use layout.tsx in the app directory to add the necessary tags.
-
Open your
app/layout.tsxfile and add the manifest link, theme color, and icon link in the<head>section.// app/layout.tsx import './globals.css'; import { Metadata } from 'next'; export const metadata: Metadata = { title: 'Your App Name', description: 'Your app description', themeColor: '#ffffff', }; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <head> <link rel="manifest" href="/manifest.json" /> <link rel="icon" href="/icons/icon-192x192.png" /> <meta name="theme-color" content="#ffffff" /> </head> <body>{children}</body> </html> ); }
This will allow users to manually trigger the PWA install prompt when they click a button.
-
Create an
InstallButtoncomponent that listens for thebeforeinstallpromptevent, which is triggered when the app meets the PWA installability criteria.// components/InstallButton.tsx import { useEffect, useState } from 'react'; const InstallButton = () => { const [deferredPrompt, setDeferredPrompt] = useState<Event | null>(null); const [isInstallable, setIsInstallable] = useState(false); useEffect(() => { const handleBeforeInstallPrompt = (e: Event) => { e.preventDefault(); setDeferredPrompt(e); setIsInstallable(true); }; window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt); return () => window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt); }, []); const handleInstallClick = async () => { if (deferredPrompt) { (deferredPrompt as any).prompt(); const { outcome } = await (deferredPrompt as any).userChoice; setDeferredPrompt(null); setIsInstallable(false); console.log(`User response to the install prompt: ${outcome}`); } }; return ( <> {isInstallable && ( <button onClick={handleInstallClick} className="install-button"> Install App </button> )} </> ); }; export default InstallButton;
-
Add
InstallButtonto your layout or any component where you’d like the install button to appear.// app/layout.tsx or another component import InstallButton from '@/components/InstallButton'; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <head> <link rel="manifest" href="/manifest.json" /> <meta name="theme-color" content="#ffffff" /> </head> <body> <InstallButton /> {children} </body> </html> ); }
To further optimize your PWA for offline capabilities, you can set up a service worker using next-pwa or another library. Here’s an example using next-pwa:
-
Install
next-pwa:npm install next-pwa
-
Configure
next-pwain yournext.config.jsfile:// next.config.js const withPWA = require('next-pwa')({ dest: 'public', }); module.exports = withPWA({ // other Next.js configurations });
-
After setting up
next-pwa, asw.jsfile will be generated automatically in thepublic/directory during the build process. This file enables caching for offline use.
Since service workers like sw.js and workbox-xxxxxx.js are generated during the build process, add them to .gitignore:
# .gitignore
/public/sw.js
/public/workbox-*.js
-
Build and serve the app in production mode:
npm run build && npm start -
Open your app in Chrome or another browser that supports PWAs, and check for the "Install" option in the browser’s address bar or try the custom install button.
-
Test the offline functionality by going offline after the initial load to see if the app is available.
guy, with nextjs 15 i made all of these configurations, and it works on pc and chrome mobile app, but not works in sansung internet...Sansung internet not Shows the pwa install button in the address bar and not shows my custon button too, i don't now how can I do