Web App Manifest and JavaScript PWA Install State
This article provides an overview of the Web App Manifest and explains how JavaScript interacts with Progressive Web App (PWA) installation states. You will learn the purpose of the manifest file, how to detect if a PWA is currently running as an installed application, and how to programmatically control and listen to the installation lifecycle using modern browser APIs.
What is the Web App Manifest?
The Web App Manifest is a JSON-based configuration file that informs the browser about how your Progressive Web App should behave when installed on a user’s mobile or desktop device. It provides essential metadata that gives a web application the look and feel of a native application.
To link a manifest to your HTML document, add a
<link> tag within the <head>
section:
<link rel="manifest" href="/manifest.json">Key Properties in the Manifest
nameandshort_name: The full application name displayed to users and an abbreviated version for spaces with limited character allowances (e.g., app launchers).start_url: The path the application should load when launched by the user from their home screen or desktop.display: Defines the browser UI mode. Common values includestandalone(removes default browser UI elements like the address bar),fullscreen,minimal-ui, andbrowser.icons: An array of image objects specifying paths, sizes, and formats for home screen and splash screen icons.theme_colorandbackground_color: Controls the color of the browser UI (such as the status bar) and the background color displayed during the initial launch splash screen.
How JavaScript Interacts with Installed PWA State
JavaScript provides several APIs and event listeners to detect installation status, handle installation prompts, and track changes to the app’s display state.
1. Detecting if the PWA is Running in Installed Mode
You can determine if a user is currently accessing the application
inside an installed window versus a standard browser tab using the
matchMedia API to query the display-mode media
feature.
function isRunningStandalone() {
const isStandalone = window.matchMedia('(display-mode: standalone)').matches;
const isIOSStandalone = window.navigator.standalone === true; // Fallback for iOS Safari
return isStandalone || isIOSStandalone;
}
if (isRunningStandalone()) {
console.log('App is running in standalone (installed) mode.');
} else {
console.log('App is running in a browser tab.');
}You can also listen for dynamic changes to the display mode:
window.matchMedia('(display-mode: standalone)').addEventListener('change', (evt) => {
if (evt.matches) {
console.log('App entered standalone mode');
}
});2. Handling the Custom Install Prompt
Supported Chromium-based browsers fire the
beforeinstallprompt event before showing the default
installation prompt. JavaScript can intercept this event to provide a
custom in-app install button.
let deferredPrompt;
const installButton = document.getElementById('install-btn');
window.addEventListener('beforeinstallprompt', (e) => {
// Prevent the default mini-infobar from appearing
e.preventDefault();
// Stash the event so it can be triggered later
deferredPrompt = e;
// Update UI to notify the user they can install the PWA
installButton.style.display = 'block';
});
installButton.addEventListener('click', async () => {
if (!deferredPrompt) return;
// Show the native install prompt
deferredPrompt.prompt();
// Wait for the user to respond to the prompt
const { outcome } = await deferredPrompt.userChoice;
console.log(`User response to the install prompt: ${outcome}`);
// Clear the saved prompt reference
deferredPrompt = null;
installButton.style.display = 'none';
});3. Detecting a Completed Installation
The appinstalled event fires immediately after the user
has installed the application, whether through the browser interface or
via a custom installation button.
window.addEventListener('appinstalled', () => {
console.log('PWA was successfully installed.');
// Log the event to analytics or hide installation-related UI elements
});4. Checking Related Installed Apps
The navigator.getInstalledRelatedApps() API allows a web
app to check if its corresponding native app or PWA is already installed
on the client machine. This requires corresponding
related_applications entries in the manifest.
if ('getInstalledRelatedApps' in navigator) {
navigator.getInstalledRelatedApps().then((relatedApps) => {
if (relatedApps.length > 0) {
console.log('App is already installed on the device:', relatedApps);
}
});
}