skip to content

What is the web app manifest, and which of its fields does the browser use to decide an installed app's launch URL, window appearance, and icon?

level: juniorimportance: should knowfreq 58%

answer

  1. JSON metadata, read only at install
  2. launch URL and its boundary
  3. window chrome versus plain tab
  4. two icon sizes plus maskable
  5. identity separate from the launch URL

basics

~20 s

A web app manifest is a JSON file that describes a site as an installable app. start_url sets the launch URL, scope bounds which pages stay in the app window, display picks standalone or browser chrome, and icons supply launcher artwork.

solid answer

~40 s

The manifest is a JSON document the browser reads when it evaluates or performs an install. Identity comes from `name` (install dialog), `short_name` (under the home-screen icon) and optionally `id`, which pins the app's identity so changing the launch URL does not create a second installed app. `start_url` is what opens when the user taps the icon; `scope` is a URL prefix, and navigations outside it are handed back to the normal browser instead of staying in the app window. `display` chooses the window: `standalone`, `minimal-ui`, `fullscreen`, or `browser` for a plain tab. `icons` is an array of `{src, sizes, type, purpose}`; Chromium wants a 192px and a 512px icon, and `purpose: "maskable"` supplies the safe-zone variant Android crops. `theme_color` and `background_color` colour the title bar and the launch splash.

code

json · 16 lines
json
{
  "id": "/?app",
  "name": "Fieldwork Reports",
  "short_name": "Fieldwork",
  "start_url": "/?source=pwa",
  "scope": "/",
  "display": "standalone",
  "display_override": ["window-controls-overlay", "standalone"],
  "theme_color": "#12263a",
  "background_color": "#ffffff",
  "icons": [
    { "src": "/icons/192.png", "sizes": "192x192", "type": "image/png" },
    { "src": "/icons/512.png", "sizes": "512x512", "type": "image/png" },
    { "src": "/icons/maskable.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
  ]
}

go deeper

for a junior

Be able to name the file, say it is JSON, and list what start_url, scope, display and icons each do. Interviewers want the vocabulary, not the edge cases.

for a middle

Explain how scope decides which navigations stay in the app window, why display_override exists as a fallback chain, and why background_color matters for the launch splash.

for a senior

Show you have debugged a real install: an app duplicated because start_url changed without a stable id, users bounced out of the window by a too-narrow scope, or a clipped logo from a missing maskable icon.

for a principal

Own the decision of what belongs in scope at all — auth redirects, third-party checkout and marketing pages each argue for a different boundary, and getting it wrong shows up as users leaving the installed experience without noticing.

## What the manifest is A web app manifest is a JSON document, served with the media type `application/manifest+json`, that tells the browser how to present a site when it is installed as an app. The document references it, and the browser fetches it when it evaluates installability or when the user installs. It changes nothing about how the page renders in an ordinary tab — a manifest with a typo does not break the site, it just quietly stops the install from working. ## Identity: name, short_name, id `name` is the full application name shown in the install dialog and app lists. `short_name` is the truncated label shown under a home-screen icon, so it should be a handful of characters. `id` is an explicit identity string for the app. Without it, the browser derives identity from `start_url`, which means that changing the launch URL later can be interpreted as a *different* app and produce a duplicate install rather than an update. Setting `id` once (`"id": "/?app"`, for example) makes identity independent of the launch URL. ## Launch and boundaries: start_url and scope `start_url` is resolved relative to the manifest's own URL and is what opens when the icon is tapped. Teams frequently add a marker query — `"start_url": "/?source=pwa"` — so analytics can separate launches from ordinary web traffic. `scope` is a URL prefix defining what counts as "inside" the app. Navigations within scope stay in the app window; a navigation outside it (an external link, a payment provider, an auth redirect on another origin) is handed to the browser, typically as an in-app browser view. If `scope` is omitted it defaults to `start_url` with its last path segment removed, which is why an app whose `start_url` is `/app/index.html` and whose real routes live at `/` can mysteriously bounce users out to a browser tab. ## Presentation: display, theme_color, background_color `display` takes one of four values, and the browser falls back down the list if it cannot honour the one you asked for: - `fullscreen` — no browser UI and no system UI where the platform allows it. - `standalone` — its own window, app title bar, no URL bar. - `minimal-ui` — standalone plus a minimal set of navigation controls. - `browser` — a normal tab; Chromium also treats this as not installable. `display_override` is an ordered array consulted before `display`, and is how you opt into newer modes such as `"window-controls-overlay"` while keeping `standalone` as the fallback. `theme_color` tints the app's title bar and the OS task-switcher entry; `background_color` paints the launch screen in the moment between tapping the icon and your first paint, so it should match your app's real background or users see a flash. In script you can detect the mode you were launched in: ```js const installed = window.matchMedia('(display-mode: standalone)').matches; ``` ## Icons `icons` is an array of objects with `src`, `sizes` (`"192x192"`, or `"any"` for SVG), `type`, and `purpose`. `purpose: "any"` is the default; `purpose: "maskable"` marks an icon drawn with a safe zone so Android can crop it into whatever shape the launcher uses — without one, an adaptive launcher may clip your logo. `purpose: "monochrome"` supplies a single-colour variant for badging. ## What the manifest does not do The manifest is metadata only. It does not cache anything, does not make the app work offline, and does not intercept requests — those are jobs for a service worker. Nor is any of it required for the site to function; a site without a manifest is simply a site that cannot be installed as an app. ## Debugging Browser devtools expose the parsed manifest, so the fastest check is to open the application panel and look at what the browser actually resolved: a manifest fetched with the wrong content type, blocked by an auth gate, or containing trailing-comma JSON produces an empty panel rather than an error in the console.

  • A user taps a link to an external payment provider from inside your installed app. What does the browser do with that navigation, and what controls it?
    The URL falls outside `scope`, so the browser takes the navigation out of the app window and shows it in an in-app browser view with visible origin information. That is deliberate: the standalone window has no URL bar, so the platform refuses to render a foreign origin inside it. Widening `scope` cannot cover another origin — scope is same-origin only.
  • Why would you set an explicit `id` in the manifest rather than letting the browser derive it?
    Identity defaults to being derived from `start_url`. If you later change `start_url` — moving from `/index.html` to `/`, say — the browser can treat the result as a new app, so an update installs alongside the old icon instead of replacing it. A stable `id` decouples identity from the launch URL and makes that change safe.
  • What is the practical difference between an icon with `purpose: "any"` and one with `purpose: "maskable"`?
    `any` icons are drawn as-is. `maskable` icons declare that the artwork keeps its important content inside a central safe zone, so a platform may crop them to a circle, squircle or rounded square. Ship both: a maskable-only icon looks over-padded where no mask is applied, and an `any`-only icon gets its edges clipped by adaptive launchers.

saying these in an interview costs you the question

  • Claiming the manifest is what makes an app work offline
  • Thinking scope can include a different origin
  • Assuming start_url is where the service worker caches from
  • Shipping only a 48px icon and expecting an install prompt
  • Treating short_name as optional decoration rather than the home-screen label

context