Web app manifest
manifest.json describes your site as an installable app — name, icons, colors, and the on-ramp to PWAs.
A web app manifest is a JSON file that tells the browser "treat my site like an installable app". With the manifest in place, mobile browsers offer to add the site to the home screen, desktop browsers offer to install it as a standalone window, and the OS treats it like any other app — its own icon, its own task switcher entry, its own splash screen.
This lesson covers the minimum manifest, what makes the install prompt actually appear, and the few keys that decide what the installed experience looks like.
Linking the manifest
The manifest is a JSON file — typically manifest.json or site.webmanifest — referenced from the head with a <link rel="manifest"> tag.
<link rel="manifest" href="/manifest.json">
That is the entire HTML side. Every other detail lives in the JSON file.
The minimum manifest
The smallest manifest that browsers will accept and that earns an install prompt:
{
"name": "Daily Bread Bakery",
"short_name": "Bread",
"start_url": "/",
"display": "standalone",
"background_color": "#fdf6e3",
"theme_color": "#c96442",
"icons": [
{
"src": "/icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icon-512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "/icon-mask-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
]
}Each key is doing real work:
name— the full name of the app, shown on splash screens and in installation dialogs.short_name— the name shown under the icon on the home screen, kept short so it fits.start_url— the URL the app opens at when launched. Often/; sometimes/?source=pwaso you can track installs.display— how the app shows up.standaloneremoves browser chrome;browserkeeps the URL bar;minimal-uiis in between.background_color— the color of the splash screen the OS shows while the app loads.theme_color— same as the metatheme-colorfrom lesson 4; tints the title bar.icons— array of icon files in different sizes. 192px and 512px are the minimum. Themaskableicon is for Android adaptive icons (covered below).
That manifest plus the link tag in your HTML is enough for browsers to offer install on most platforms.
The 512×512 icon also drives the Android splash screen — the OS scales it to fill the splash before your page paints. Make it look good at large sizes; the user sees it briefly every time they launch.
What earns the install prompt
Just having a manifest is not enough to trigger an install prompt. Browsers have specific criteria.
For Chromium-based browsers (Chrome, Edge, Brave, Opera), all of these must be true:
- Manifest linked in the head.
- Manifest contains
name(orshort_name),iconsof at least 192×192 and 512×512,start_url, anddisplayset tostandalone,fullscreen, orminimal-ui. - Service worker registered with a
fetchhandler. (For some installable contexts, just the manifest is enough; for the install prompt, the service worker is the gating signal.) - HTTPS (or localhost for development).
- User engagement — the user has interacted with the page for at least a few seconds.
Safari (iOS) does not show an install prompt at all. Users add to home screen via the Share menu. The manifest still applies to the installed experience (icon, name, display mode).
If your install prompt is not appearing, the most common missing piece is the service worker. A web app manifest without a service worker is treated as "installable in a limited sense" — Lighthouse will tell you exactly what is missing.
The deeper service-worker story (offline caching, background sync, push notifications) is a course of its own; this lesson is about the manifest only. Many sites skip the service worker entirely and forgo the install prompt; the manifest still earns a better look on home screens that the user adds manually.
manifest.json with name, icons, start_url, and standalone display. You ship over HTTPS. The install prompt never appears in Chrome. What's the most likely missing piece?display and scope
display is the most-impactful manifest key for how the installed app feels.
browser— opens in a regular browser tab. Almost like not being installed.minimal-ui— minimal browser chrome (back button, sometimes a URL strip). Useful for sites that benefit from those controls.standalone— no browser chrome at all. The app looks like a native app. The most common choice for actual app-feeling sites.fullscreen— full screen, no status bar. Used by games and immersive apps.
scope defines which URLs are "inside the app". When the user navigates to a URL outside the scope, the browser opens it in a regular browser instead of inside the app.
{
"name": "Daily Bread Bakery",
"start_url": "/",
"scope": "/",
"display": "standalone"
}A scope of / includes every page on the site. A scope of /app/ only includes URLs under /app/. Useful when your site has both an app section and a marketing section, and you only want the app section to behave as an installed app.
The maskable icon in the example earlier is for Android. Android's adaptive icon system masks every app icon into a shape (circle, squircle, rounded square) chosen by the user's launcher. A regular icon may have important content cropped by the mask. A maskable icon has its key content inside the "safe zone" (the central 80%) so the mask never crops anything important.
If you want to ship one set of icons that works on Android, generate two versions per size: the standard one and the maskable one with the safe-zone padding.
Don't ship only maskable icons. Browsers and OSes that do not understand purpose: "maskable" will display the icon with the safe-zone padding visible, making it look small inside a big empty box. Always include a non-maskable version too.
A useful picture: the manifest is a small business card you hand the OS — "here is my name, my icon, my preferred opening URL, my colors". The OS files the card and uses it whenever the app comes up.
"display": "standalone" in the manifest. A user installs your site to their phone. They tap the home-screen icon. What do they see?/ and an app section at /app/. You want the installed PWA to feel like the app section only — links to /blog/ should open in a regular browser. The right manifest scope is: