A Progressive Web App without a manifest is just a website. The manifest.json file (officially the Web Application Manifest) tells the browser that your site can be installed as an app. It sets the name, icons, colors, display mode, and the properties that control how the installed app looks and behaves.
Without a valid manifest, the browser's "Install" prompt never appears. Your site cannot land on the home screen with a proper icon. It opens in a regular browser tab instead of a standalone window. The manifest is the minimum for the PWA experience.
The spec itself is small, but the details trip people up. Icon sizes must match exactly. Some fields are required in some browsers but not others. Display modes behave differently on iOS and Android. This guide covers the full spec with working examples and the common mistakes that block install.
The Minimum Viable Manifest
A manifest that triggers the browser install prompt needs at minimum these fields:
`json
{
"name": "My App",
"short_name": "App",
"start_url": "/",
"display": "standalone",
"icons": [
{
"src": "/icons/icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icons/icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
`
name: the full name displayed in the install dialog and app launcher. Keep it under 45 characters.
short_name: used where space is limited (home screen label). Keep it under 12 characters.
start_url: the page that opens when the user launches the app. Usually / or /app. Include any URL parameters you need for analytics tracking.
display: how the app window appears. standalone removes the browser chrome (address bar, navigation buttons) and makes the app look native.
icons: at minimum, provide 192x192 and 512x512 PNG icons. The 192px icon is used for the home screen. The 512px icon is used for the splash screen on Android.
Validate your manifest JSON with the JSON Formatter to catch syntax errors before deploying. A single misplaced comma or missing quote breaks the entire manifest.
Generate the icon set with the Favicon Generator. A single high-resolution source image can produce all the sizes you need.
Complete Manifest Fields Explained
Beyond the minimum, additional fields improve the installation experience.
background_color: the color of the splash screen background while the app loads. Use the same color as your app's background for a seamless transition:
`json
"background_color": "#ffffff"
`
theme_color: controls the color of the browser's UI elements (status bar on mobile, title bar on desktop). Match your brand:
`json
"theme_color": "#3b82f6"
`
description: a brief description of the app. Shown in some install dialogs and app stores:
`json
"description": "Track your daily habits and build lasting routines"
`
scope: limits which URLs are considered part of the app. URLs outside the scope open in the browser:
`json
"scope": "/app/"
`
orientation: locks the app to a specific orientation. Useful for games or media apps:
`json
"orientation": "portrait"
`
categories: helps app stores categorize your PWA:
`json
"categories": ["productivity", "utilities"]
`
screenshots: shown in the install dialog on supported browsers (Chrome on Android):
`json
"screenshots": [
{
"src": "/screenshots/home.png",
"sizes": "1080x1920",
"type": "image/png",
"form_factor": "narrow"
}
]
`
Format your manifest consistently with the Code Formatter to keep it readable during development. Minification is not necessary for manifests since they are small files.

Display Modes: Choosing the Right Experience
The display field controls how much browser UI is visible when the app is running.
fullscreen: takes over the entire screen with no browser or system UI. Used for games and immersive media apps. The app must handle its own navigation and status indicators.
standalone: looks like a native app. No address bar or browser navigation. The system status bar (time, battery, signal) is still visible. This is the most common choice for utility and productivity PWAs.
minimal-ui: similar to standalone but includes a minimal set of browser controls (typically a back button and URL indicator). Useful for content-heavy apps where users might want to navigate back.
browser: the default. Opens in a regular browser tab. No PWA-specific behavior. Rarely used intentionally.
window-controls-overlay (desktop only): gives you control over the title bar area. Your app content extends into the title bar space, and you can place custom controls there. Useful for desktop PWAs that want a more integrated look.
The fallback chain works automatically: if the browser does not support the requested display mode, it falls back to the next less immersive mode. fullscreen falls back to standalone, which falls back to minimal-ui, which falls back to browser.
iOS Safari behavior: as of 2026, iOS supports standalone and fullscreen modes for PWAs added to the home screen. The minimal-ui mode falls back to standalone on iOS. Push notifications for PWAs arrived on iOS in 2023 and have improved since, but some limitations compared to Android remain.
Icon Requirements and Maskable Icons
Icons are the most common source of manifest problems. Different platforms need different icon sizes, formats, and shapes.
Required sizes (PNG, at minimum): - 192x192 px: home screen icon on Android - 512x512 px: splash screen and PWA install dialog
Recommended additional sizes: - 48x48, 72x72, 96x96, 128x128, 144x144, 256x256, 384x384 - Including more sizes gives the OS the best option for each context
Maskable icons: Android applies different shaped masks (circle, rounded square, squircle) to icons depending on the device manufacturer. A maskable icon has extra padding around the important content so nothing gets clipped.
`json
{
"src": "/icons/icon-maskable-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
`
The safe zone for maskable icons is a circle with a diameter of 80% of the icon size, centered. Place all important content (logo, text) within this circle. The outer 10% on each side may be clipped.
Provide both regular and maskable versions:
`json
"icons": [
{ "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" },
{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" },
{ "src": "/icons/icon-maskable-192.png", "sizes": "192x192", "type": "image/png", "purpose": "maskable" },
{ "src": "/icons/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
]
`
Do not set "purpose": "any maskable" on a single icon. This was previously allowed but causes quality issues because the same icon is used for both masked and unmasked contexts.
Icons are the most common source of manifest problems.
Testing and Debugging Your Manifest
Chrome DevTools is the primary tool for manifest debugging.
Application panel: open DevTools, go to the Application tab, click "Manifest" in the sidebar. Chrome shows all parsed manifest fields, validates the icon sizes, and reports any errors or warnings.
Installability check: in the same panel, the "Installability" section shows whether your app meets the criteria for the install prompt. Common failure reasons: - Missing required icon sizes (192 and 512) - No service worker registered - Not served over HTTPS - Invalid start_url
Lighthouse PWA audit: run a Lighthouse audit with the PWA category enabled. It checks manifest completeness, icon sizes, offline capability, and more. A 100 PWA score means your app meets all installability criteria.
Testing on real devices: always test on actual Android and iOS devices. The install experience differs significantly between platforms: - Android Chrome: shows an "Add to Home Screen" prompt automatically or via the menu - iOS Safari: requires the user to tap Share, then "Add to Home Screen." No automatic prompt. - Desktop Chrome/Edge: shows an install icon in the address bar
Common debugging issues:
- Manifest not loading: check the tag in your HTML. Verify the path is correct.
- Icons not showing: icon paths in the manifest are relative to the manifest file location, not the HTML page.
- Start URL mismatch: the start_url must be within the scope. If scope is /app/, start_url cannot be /.
- Caching issues: manifests and icons are aggressively cached. Use cache-busting during development.

Service Workers: The Other Half of PWA
A manifest alone does not make a PWA installable in all browsers. Chrome also requires a registered service worker with a fetch event handler. This is the minimum service worker that satisfies the requirement:
`javascript
self.addEventListener('fetch', (event) => {
event.respondWith(fetch(event.request));
});
`
This pass-through service worker does not add offline capability but meets the technical requirement for installability.
For a useful service worker, implement a caching strategy:
`javascript
const CACHE_NAME = 'v1';
const ASSETS = ['/index.html', '/styles.css', '/app.js', '/icons/icon-192.png'];
self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE_NAME).then(cache => cache.addAll(ASSETS)) ); });
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then(cached => cached || fetch(event.request))
);
});
`
This caches specified assets during installation and serves them from cache first, falling back to the network. This provides basic offline support.
For modern frameworks:
- Next.js: use next-pwa or @serwist/next for automatic service worker generation
- Vite: vite-plugin-pwa generates the manifest and service worker from configuration
- Create React App: built-in service worker template (opt-in)
These tools handle the complexity of cache management, update flows, and asset versioning automatically.
A manifest alone does not make a PWA installable in all browsers.
FAQ
Does Apple support PWA manifests on iOS?
Partially. iOS Safari reads the manifest for name, short_name, start_url, display, and icons. However, Apple still uses its proprietary tags for some features. For full iOS support, include both the manifest and Apple-specific meta tags (apple-mobile-web-app-capable, apple-touch-icon, apple-mobile-web-app-status-bar-style).
Can I update the manifest after users have installed the PWA?
Yes. When the user opens the installed PWA, the browser checks for manifest changes. Most changes (name, icons, theme_color) take effect on the next launch. Some changes may require the user to reinstall. Browsers are inconsistent about which changes trigger automatic updates versus requiring reinstallation.
Do I need a service worker if I just want an installable web app?
Chrome requires a service worker with a fetch handler for the install prompt to appear. Firefox and Edge have similar requirements. Safari on iOS does not require a service worker for Add to Home Screen but does require one for offline capability. For cross-browser installability, include a service worker.
Can my PWA be listed in app stores?
Yes. Google Play Store accepts TWAs (Trusted Web Activities) that wrap PWAs in an Android package. Microsoft Store lists PWAs directly. Apple's App Store has more restrictions but allows PWA wrappers through tools like PWABuilder. The manifest is the foundation that makes these store listings possible.
JSON Guide: Format, Validate, and Convert JSON Files
JSON guide for developers: syntax rules, common parse errors, formatting and schema validation, plus how to convert between JSON and CSV files.
Base64, URL Encoding & HTML Entities Explained
Encode and decode Base64, URLs, and HTML entities in your browser. Learn when to use each format, with clear examples and free converter tools.
Regular Expressions for Beginners: A Practical Guide
Learn regular expressions from scratch: basic syntax, character classes, quantifiers, and practical patterns for matching emails, URLs, and phone numbers.
