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.json
file:// 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/icons
directory.
In a Next.js App Router project, use layout.tsx
in the app
directory to add the necessary tags.
-
Open your
app/layout.tsx
file 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
InstallButton
component that listens for thebeforeinstallprompt
event, 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
InstallButton
to 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-pwa
in yournext.config.js
file:// next.config.js const withPWA = require('next-pwa')({ dest: 'public', }); module.exports = withPWA({ // other Next.js configurations });
-
After setting up
next-pwa
, asw.js
file 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.
instead of manifest.json i use manifest.ts in the app folder can it work ?