Build my web app

The web app manifest, field by field

Every field that affects installation and appearance — name, short_name, start_url, scope, display, icons, theme_color, screenshots, shortcuts, id — with what happens when you get each one wrong.

The manifest is a JSON file that describes your web app to the browser. The builder writes one for you; this guide is so you understand what it wrote and can change it with confidence. Fields are grouped by what they affect.

Identity

name

The full name. Shown on the install prompt, the splash screen and in settings. Up to about 45 characters display; longer is truncated. Use your brand as people know it: "Rosie's Bakery", not "Rosie's Bakery — Order Online".

short_name

Shown under the icon on home screens, where space is 11–12 characters before truncation. "Rosie's" beats "Rosie's Bakery". If you omit it, name is used and will likely be cut mid-word.

description

A sentence or two, shown in Chrome's richer install dialog (when screenshots are present) and used by Google Play for TWAs. Say what the app does for the user.

id

A stable identifier for the app, relative to the origin — e.g. "/" or "/app". Browsers use it to recognise the same app across manifest changes. Set it once and never change it; if you later change start_url, the id is what stops the browser treating your app as a new one. Older manifests without id default to start_url, which is why changing start_url used to "un-install" apps.

Where it opens

start_url

The page opened from the icon. Usually / or a dedicated app landing such as /app. Add a query string (/?source=pwa) to distinguish installed launches in analytics. Must be same-origin as the manifest and inside scope.

scope

The URL prefix that counts as "inside the app". Navigations within scope stay in the app window; navigations outside it open in a browser (a Custom Tab on Android). Set it to / for a whole site, or /app/ to exclude, say, your marketing pages. A scope that is too narrow is a common cause of "my app keeps opening the browser".

How it looks

display

ValueEffectUse for
standaloneOwn window, no browser UI, status bar visibleAlmost everything
fullscreenAlso hides the status barGames, kiosks. Falls back to standalone where unsupported (iOS)
minimal-uiOwn window with back/reload controlsRare; Android only
browserNormal tabDisables installability — don't

orientation

portrait, landscape, any, and their primary/secondary variants. Locks the installed app on Android and desktop; ignored by iOS Safari. Only lock what your layout truly supports.

theme_color

Colour of the status bar and window title bar. Needs legible contrast for white or black system text — see the palette tool. The page-level <meta name="theme-color"> overrides it per page and can vary by colour scheme.

background_color

Colour of the generated splash screen while the first page loads. Match your page background so the transition is seamless.

Icons

icons

An array of { src, sizes, type, purpose }. Requirements for installability: at least one 192×192 and one 512×512 PNG. Best practice:

"icons": [
  { "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png" },
  { "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png" },
  { "src": "/icons/maskable-192.png", "sizes": "192x192", "type": "image/png", "purpose": "maskable" },
  { "src": "/icons/maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
]

purpose: "maskable" tells Android it may crop the icon into its launcher shape; the icon must have padding for that (the safe zone is a circle 80% of the width). Marking an unpadded icon maskable clips it. The icon resizer previews the masks. iOS ignores this array and uses <link rel="apple-touch-icon"> instead.

Richer install UI

screenshots

An array of images with form_factor (narrow for phone, wide for desktop), sizes, type and a label. When present, Chrome shows a store-like install dialog with a carousel. Constraints: 320–3840 px per side, same aspect ratio within a form factor, at least one per form factor you want covered. The screenshot tool exports at compliant sizes.

categories

Free-text hints like ["shopping"] or ["games"]. Used by some install surfaces and stores; harmless to include.

Shortcuts and more

shortcuts

Long-press menu items on the app icon (Android, desktop): up to four { name, url, icons } entries such as "Order again" or "My account". Cheap to add, noticeably app-like.

related_applications and prefer_related_applications

Point at your Play Store listing if you have a native app and want Chrome to suggest it instead of installing the PWA. If you are the PWA, leave prefer_related_applications false or absent — setting it true suppresses the PWA install prompt.

lang, dir

Language and text direction of the manifest's strings. Set lang to your site's language code.

Linking it

<link rel="manifest" href="/manifest.json">

Serve it with Content-Type: application/manifest+json (or application/json, which browsers accept). Cross-origin manifests work if served with CORS and the crossorigin attribute; the start_url must still be on your origin.

Checking your work

Chrome DevTools → ApplicationManifest shows the parsed manifest, the icons as the browser sees them, the maskable preview, and — under Installability — the exact reason a prompt is not appearing. It is the single most useful debugging view for this whole topic.