How To Create A Progressive Web App (PWA) Using Next - Js
How To Create A Progressive Web App (PWA) Using Next - Js
js
Spruce Emmanuel
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 1/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
Have you ever wanted to create a web app that works smoothly on any device—whether it's
on the web, mobile, or desktop? Imagine if your app could load quickly, work without an
internet connection, and feel like a native app, all without needing to be installed from an app
store. That’s exactly what Progressive Web Apps (PWAs) can do.
In this tutorial, you’ll learn how to build a PWA using Next.js. We’ll start by creating a
functional movie search website with these tools. Once we have the basics set up, we’ll
transform this app into a PWA, adding offline support and faster load times. By the end, you’ll
have a powerful PWA that offers a smooth user experience across all platforms—all from a
single codebase.
Turning the App into a PWA: Next, we’ll walk through the steps to convert the app
into a Progressive Web App, covering the key features and best practices of PWAs.
Adding Offline Support: Finally, we’ll ensure your app stays functional even when
there’s no internet connection by implementing offline capabilities.
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 2/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
Audience
This tutorial is for React developers of all levels, whether you’re just starting out or already
experienced. If you want to enhance your web apps with PWA features, this guide will take
you through the necessary steps.
Prerequisites
Before you begin, make sure you’re familiar with React.js and Next.js. If you’re new to
PWAs, you might want to read some introductory articles to get a quick overview.
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 3/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
What makes PWAs special is their ability to work offline, send push notifications, and be
installed on a user’s device without an app store. In short, a PWA makes your web app feel
like a native app while keeping the flexibility and wide reach of the web.
Cross-Platform Availability: A PWA works on any device with a browser, so you only
need to develop and maintain one codebase for web, mobile, and desktop apps. This
saves time and ensures a consistent experience across all platforms.
Offline Capabilities: PWAs can work offline or in areas with poor connectivity by
caching essential resources, keeping your app functional even without internet access.
Improved Performance: PWAs are built to load quickly and run smoothly, even on
slow networks, thanks to techniques like service workers and caching.
Increased User Engagement: Users can add PWAs directly to their home screen
without needing an app store. This easy access, along with features like push
notifications, helps keep users engaged and coming back.
Disadvantages of PWAs
Limited Access to Device Features: PWAs don’t have full access to certain device
features like Bluetooth or advanced camera controls. For apps that need deep
hardware integration, this can be a limitation.
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 4/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
Less Visibility: Since PWAs don’t go through app stores, they miss out on the visibility
that app stores offer. Some users might also prefer downloading apps from app stores
rather than directly from the browser.
Limited iOS Support: Some features of PWAs, like push notifications, don’t work as
well on iPhones and iPads compared to Android devices, which can limit engagement
with iOS users.
Next.js is a top choice for building React apps in 2024. It offers features like server-side
rendering and static site generation, making it easier to create fast and reliable web apps.
These features ensure your app performs well on all devices and even works offline.
Project Installation
cd your-repo
npm install
4. Configure Environment Variables: Create a .env.local file in the root directory and add
your OMDB API key:
NEXT_PUBLIC_OMDB_API_KEY=your-api-key
You can obtain your API key from the OMDB API website.
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 5/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
MovieMaster, as it provides up-to-date information for users without you having to store all
the data yourself.
In a PWA, using an API like OMDB ensures that the app can deliver fresh content to users,
even when it's installed on their devices. Combined with the PWA's caching and offline
features, users can still view movie details that were previously fetched, even if they lose
internet connectivity.
Note: Make sure Node.js and npm are installed on your system. If they are not, you can
download them from nodejs.org.
/src/app: Houses the main application files, including global styles (globals.css), the
main page (page.tsx), layout configurations (layout.tsx), and client-side logic
(RootLayoutClient.tsx).
/src/lib: Contains utility functions and data-fetching code, such as fetchMovies.ts and
useMediaQuery.ts.
Understanding Layouts
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 6/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
1. layout.tsx: Manages server-side rendering and sets the application’s metadata. It uses
the RootLayoutClient component to handle client-side functionality. Here’s how it
looks:
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 7/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
"use client";
This will start the development server, and you can view the application by navigating to
http://localhost:3000 in your browser.
2. Web Manifest File: A web manifest file provides metadata about your app, such as its
name, icons, and start URL. This file is crucial for making your app installable on a
user's device.
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 8/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
3. Service Worker with a fetch Event: Your app must register a service worker with at
least a fetch event. Registering a service worker with at least a fetch event is essential
for your app to be recognized as a PWA and be installable. Beyond that, service
workers enhance your app's performance and reliability, allowing it to cache resources
and handle network requests even when offline.
To add a web manifest file in your Next.js app, place it in the public/ directory and reference
it in your layout file. Ensure that all the images you include in your manifest file are also in
the public/ directory.
{
"name": "Movie Master",
"short_name": "Moviemaster",
"theme_color": "#8936FF",
"background_color": "#333333",
"start_url": "/",
"id": "MovieMaster",
"display": "standalone",
"description": "MovieMaster PWA helps you find the latest movies with an easy
search by genre, year, and more. It works smoothly on any device, even offline,
giving you a great movie browsing experience.",
"icons": [
{
"purpose": "maskable",
"sizes": "512x512",
"src": "icon512_maskable.png",
"type": "image/png"
},
{
"purpose": "any",
"sizes": "512x512",
"src": "icon512_rounded.png",
"type": "image/png"
}
],
"screenshots": [
{
"src": "screenshot1.png",
"type": "image/png",
"sizes": "1080x1920",
"form_factor": "narrow"
}
]
}
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 9/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
Required Fields
short_name: A shorter version of the app’s name, displayed when there isn’t enough
space for the full name.
display: Defines the display mode (for example, standalone for a full-screen
experience).
Recommended Fields
theme_color: Sets the theme color of the browser’s UI, such as the address bar. This
color enhances the native feel of your PWA.
This example shows how the theme color (#8936FF) is applied to the browser's UI, giving
your PWA a native feel.
background_color: Defines the background color for the splash screen when your app
is launched.
This example illustrates how screenshots are displayed during the installation process,
enhancing the user experience, especially on Android devices.
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 10/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 11/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
Registering a service worker with at least a fetch event is essential for your app to be
recognized as a PWA and be installable.
Create a service-worker.js file in the public/ directory with the following code:
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 12/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
"use client";
return (
<div className="text-white flex flex-col">
<div className="container mx-auto px-4 max-w-[1024px]">
{children}
</div>
</div>
);
}
Once your app meets all the criteria, users can easily install it on their devices. For example,
when using the Edge browser, an install option will appear in the browser’s menu, allowing
users to add your app directly to their desktop or home screen.
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 13/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
With a PWA, you can intercept every request made by your app using a service worker. This
gives you the flexibility to decide how to serve content—from the network or from a cache.
This control allows you to ensure that users can still access the app, even without an internet
connection.
Let’s start by looking at how our app currently behaves, which is similar to any standard web
application:
This code simply fetches resources directly from the network. If the network is unavailable,
the request will fail, leading to an error. This is the default behavior for a standard web app.
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 14/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
What to Cache?
The decision on what to cache depends on the needs of your application. For a movie
search app like ours, we’ll want to cache the essential resources required to render a basic
version of the application:
Note: While you can cache almost anything, be mindful of storage limitations, as all cached
items are stored on the user’s device. Use storage wisely to avoid taking up too much space.
When to Cache?
Once we know what to cache, the next thing to consider is when to cache. Should you cache
everything during the service worker installation, or should you cache resources as they are
requested?
The answer depends on the app's needs, but a good practice is to cache the core files
required to render a basic version of the app during the service worker installation.
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 15/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
In this code, self.skipWaiting() ensures that the new service worker activates
immediately after installation, bypassing the waiting phase.
It’s also important to delete old caches when a new service worker is activated:
The self.clients.claim() method ensures that the new service worker takes control of all
pages as soon as it activates.
Dynamic Caching
Dynamic caching is particularly useful for React apps like ours, where static files are
automatically generated. With dynamic caching, you don’t need to know all the files in
advance. Instead, it handles the caching process for you as files are requested.
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 16/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
try {
const response = await fetch(request);
const responseClone = response.clone();
await cache.put(request, responseClone);
return response;
} catch (error) {
console.error("Dynamic caching failed:", error);
return caches.match(request);
}
}
With dynamic caching, files requested by the app are cached as they are fetched, ensuring
that they are available for future offline use.
IndexedDB is more powerful than the Cache Storage API, especially for storing and
retrieving structured data like JSON. This makes it an excellent choice for apps that require
storing complex data or handling large amounts of information efficiently.
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 17/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
First, create a function to open the database and create an object store:
function openDb() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(DB_NAME, DB_VERSION);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
request.onupgradeneeded = (event) => {
const db = event.target.result;
db.createObjectStore(DB_STORE_NAME, { keyPath: "url" });
};
});
}
Next, create functions to add data to and retrieve data from the database:
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 18/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
const data = {
url,
response: JSON.stringify(jsonData),
};
return null;
} catch (error) {
console.error("Error retrieving from IndexedDB:", error);
return null;
}
}
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 19/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
In the cache-first strategy, we check if a resource is available in the cache. If it is, we serve it
from the cache; if not, we fetch it from the network. This is particularly useful for serving
static assets like HTML, CSS, and JavaScript files:
if (cachedResponse) {
return cachedResponse;
}
In this setup, the cache-first strategy is applied when navigating to new pages, while
dynamic caching handles other requests.
The network-first strategy is the opposite: it attempts to fetch resources from the network
first, and if the network is unavailable, it falls back to the cache. This strategy is particularly
useful for API requests where you want the most up-to-date data:
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 20/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
if (networkResponse.ok) {
const responseClone = networkResponse.clone();
const responseData = await responseClone.json();
await addData(request.url, responseData);
return networkResponse;
}
if (cachedResponse) {
console.log("Using cached response:", cachedResponse);
return new Response(JSON.stringify(cachedResponse), {
status: 200,
headers: { "Content-Type": "application/json" },
});
}
In our app, we use the network-first strategy for API calls, ensuring that the user gets the
latest data when online, while falling back to cached data in IndexedDB when offline.
Here’s the complete service-worker.js file that incorporates everything we’ve discussed:
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 21/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
try {
const response = await fetch(request);
const responseClone = response.clone();
await cache.put(request, responseClone);
return response;
} catch (error) {
console.error("Dynamic caching failed:", error);
return caches.match(request);
}
}
function openDb() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(DB_NAME, DB_VERSION);
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 22/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
const data = {
url,
response: JSON.stringify(jsonData),
};
return null;
} catch (error) {
console.error("Error retrieving from IndexedDB:", error);
return null;
}
}
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 23/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
try {
const cache = await caches.open(CACHE_NAME);
const cachedResponse = await cache.match(request);
if (cachedResponse) {
return cachedResponse;
}
if (networkResponse.ok) {
const responseClone = networkResponse.clone();
const responseData = await responseClone.json();
await addData(request.url, responseData);
return networkResponse;
}
if (cachedResponse) {
console.log("Using cached response:", cachedResponse);
return new Response(JSON.stringify(cachedResponse), {
status: 200,
headers: { "Content-Type": "application/json" },
});
}
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 24/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
event.respondWith(networkFirstStrategy(request));
} else if (event.request.mode === "navigate") {
event.respondWith(cacheFirstStrategy(request));
} else {
event.respondWith(dynamicCaching(request));
}
});
With this setup, your PWA is now fully equipped to handle both static and dynamic content,
provide an offline experience, and cache API data intelligently.
Further Reading
There are many more strategies and nuances to building a robust offline experience with
service workers. If you want to dive deeper into this topic, consider reading more about:
Advanced service worker features like background sync and push notifications.
By understanding and implementing these concepts, you can ensure that your app remains
functional and user-friendly, even in challenging network conditions.
Even with caching strategies in place, there may be times when users try to access a
resource that isn’t available offline and in the network. To handle these situations gracefully,
we can create a fallback page. This page will be shown whenever a user tries to access
content that can't be retrieved from either the cache or the network.
If you cloned the example project for this tutorial, you should already have a fallback page
located in the app directory. This page is designed to handle offline scenarios gracefully and
includes a simple Tic-Tac-Toe game for users to play while waiting for the connection to be
restored. Here’s what the fallback page looks like:
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 25/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
"use client";
import TicTacToe from "@/components/TicTacToe";
import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
useEffect(() => {
const handleOnline = () => {
setIsOnline(true);
// Redirect to homepage if online
router.push("/");
};
window.addEventListener("online", handleOnline);
window.addEventListener("offline", handleOffline);
return () => {
window.removeEventListener("online", handleOnline);
window.removeEventListener("offline", handleOffline);
};
}, [router]);
return (
<div className="flex mx-auto h-screen max-w-[500px] w-full flex-col items-center
justify-center h-screen bg-foreground text-black p-6 mt-12 text-white">
<h1 className="text-3xl font-bold mb-6">
{isOnline ? "You are online!" : "You are offline"}
</h1>
<p className="text-lg text-center mb-6">
{isOnline
? "You are back online."
: "Please check your internet connection and try again."}
</p>
<div className="">
<TicTacToe />
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 26/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
</div>
{isOnline ? (
<Link
href={"/"}
className="mt-6 px-4 py-2 bg-blue-500 text-white rounded shadow hover:bg-
blue-600"
>
Return to Homepage
</Link>
) : (
<button
onClick={handleRefresh}
className="mt-6 px-4 py-2 bg-blue-500 text-white rounded shadow hover:bg-
blue-600"
>
Refresh
</button>
)}
</div>
);
};
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 27/28
12/1/24, 12:09 PM How To Create a Progressive Web App (PWA) Using Next.js
Note: You can customize this fallback page to suit your application’s needs, whether that’s
displaying helpful offline content, providing a message, or offering a small interactive feature
like the Tic-Tac-Toe game included here.
Next, ensure that the fallback page is cached when the service worker is installed:
Finally, modify the cacheFirstStrategy to serve the offline.html page when a request fails:
if (cachedResponse) {
return cachedResponse;
}
This approach ensures that users always see a meaningful message instead of an error
when they’re offline or when a resource is unavailable.
Conclusion
With our Next.js app set up, we’ve successfully transformed it into a fully functional
Progressive Web App (PWA), making it better and more user-friendly.
https://www.freecodecamp.org/news/how-to-create-a-nextjs-pwa/ 28/28