Introduction
A Progressive Web App (PWA) should gracefully handle offline scenarios. Instead of showing the default browser error page, you can provide a custom offline page. This improves the user experience by giving them a clear, branded message when they lose internet connection.
Why Offline Page Matters?
Imagine a user opens your app while offline. Without a fallback page, they’ll face the generic “No Internet” error screen from the browser. With a custom offline.html
, you can show them helpful instructions, keep your app branding consistent, and reassure them that the app will work again when the internet is back.
⚠️ Note: Your offline page must be included in the final dist
build (e.g., dist/offline.html
) for vite-plugin-pwa
to serve it properly as a fallback.
Vite Config for Offline Page
To enable the offline page, update your vite.config.js
file. The navigateFallback
option ensures that whenever a user is disconnected and tries to load a page, your offline.html
is displayed.
import path from "path";
import { fileURLToPath } from "url";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import { VitePWA } from "vite-plugin-pwa";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default defineConfig({
plugins: [
react(),
VitePWA({
registerType: "autoUpdate",
includeAssets: [
"favicon.ico",
"apple-touch-icon.png",
"pwa-192x192.png",
"pwa-512x512.png",
"offline.html", // ✅ make sure offline page is added
],
manifest: {
name: "Quran App",
short_name: "Quran",
start_url: "/",
display: "standalone",
background_color: "#ffffff",
theme_color: "#16a34a",
icons: [
{ src: "pwa-144x144.png", sizes: "144x144", type: "image/png" },
{ src: "pwa-192x192.png", sizes: "192x192", type: "image/png" },
{ src: "pwa-512x512.png", sizes: "512x512", type: "image/png" },
{ src: "pwa-512x512.png", sizes: "512x512", type: "image/png", purpose: "any maskable" },
],
screenshots: [
{ src: "screenshot-desktop.png", sizes: "1280x720", type: "image/png", form_factor: "wide" },
{ src: "screenshot-mobile.png", sizes: "540x720", type: "image/png", form_factor: "narrow" },
],
},
workbox: {
navigateFallback: "/offline.html", // 👈 key setting
globPatterns: ["**/*.{js,css,html,ico,png,svg}"],
runtimeCaching: [
{
urlPattern: ({ url }) => url.pathname.startsWith("/data/"),
handler: "CacheFirst",
options: {
cacheName: "quran-json",
expiration: {
maxEntries: 200,
maxAgeSeconds: 60 * 60 * 24 * 365, // 1 year
},
},
},
],
},
}),
],
resolve: { alias: { "~": path.resolve(__dirname, "./src") } },
server: { host: "localhost", port: 4000 },
});
Creating offline.html
Add a simple offline.html
file inside your public/
directory. This page will be served whenever your app is offline.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Offline - Quran App</title>
<style>
body {
display: flex;
height: 100vh;
align-items: center;
justify-content: center;
background: #f0f0f0;
font-family: sans-serif;
text-align: center;
}
</style>
</head>
<body>
<div>
<h1>You’re offline 😕</h1>
<p>Please reconnect to continue using the app.</p>
</div>
</body>
</html>
Testing the Offline Page
After building the app with npm run build
and starting it with npm run preview
, disable your internet connection (or use DevTools → Network → Offline) and try refreshing the app. You should now see your custom offline page instead of the default browser error.
Conclusion
By adding a custom offline page, your PWA delivers a polished and professional experience. Instead of confusing browser errors, users get a helpful, branded message. With PWA setup, Install Button, and now Offline Page, your React app is a complete Progressive Web App ready for real-world users.