This specification defines a JSON-based file format that provides developers with a centralized place to put metadata associated with a web application. This metadata includes, but is not limited to, the web application's name, links to icons, as well as the preferred URL to open when a user launches the web application. The manifest also allows developers to declare a default screen orientation for their web application, as well as providing the ability to set the display mode for the application (e.g., in fullscreen). Additionally, the manifest allows a developer to "scope" a web application to a URL. This restricts the URLs to which the manifest is applied and provides a means to "deep link" into a web application from other applications.

Using this metadata, user agents can provide developers with means to create user experiences that are more comparable to that of a native application.

Web Application Manifest

An application manifest is a [[JSON]] document that contains startup parameters and application defaults for when a web application is launched.

A manifest has an associated manifest URL, which is the [[URL]] from which the manifest was fetched.

A [=manifest=] can have any of the following members at its root, all of which are optional. The members can appear in any order.

Examples

This section shows how developers can make use of the various features of this specification.

Typical structure

The following shows a typical manifest.

            {
              "lang": "en",
              "dir": "ltr",
              "name": "Super Racer 3000",
              "short_name": "Racer3K",
              "icons": [{
                "src": "icon/lowres.webp",
                "sizes": "64x64",
                "type": "image/webp"
              }, {
                "src": "icon/lowres.png",
                "sizes": "64x64"
              }, {
                "src": "icon/hd_hi",
                "sizes": "128x128"
              }],
              "scope": "/",
              "id": "superracer",
              "start_url": "/start.html",
              "display": "fullscreen",
              "orientation": "landscape",
              "theme_color": "aliceblue",
              "background_color": "red"
            }
          

Using a `link` element to link to a manifest

The example also shows how to use the link type "manifest" and how to use other [^meta^] and [^link^] elements to give the web application a fallback name and set of icons.

            <!doctype>
            <html>
            <title>Racer 3K</title>

            <!-- Startup configuration -->
            <link rel="manifest" href="manifest.webmanifest">

            <!-- Fallback application metadata for legacy browsers -->
            <meta name="application-name" content="Racer3K">
            <link rel="icon" sizes="16x16 32x32 48x48" href="lo_def.ico">
            <link rel="icon" sizes="512x512" href="hi_def.png">
          

Declaring multiple icons

In the following example, the developer has made the following choices about the icons associated with the web application:

  • The developer has included two icons at the same size, but in two different formats. One is explicitly marked as WebP through the `type` member. If the user agent doesn't support WebP, it falls back to the second icon of the same size. The MIME type of this icon can then be either determined via a HTTP header, or can be sniffed by the user agent once the first few bytes of the icon are received.
  • The developer wants to use an SVG for greater than or equal to 257x257px. They've found that the SVG file looks too blurry at small sizes, even on high-density screens. To deal with this problem, the developer includes an SVG icon that is only used when the dimensions are at least 257px. Otherwise, the user agent uses the ICO file (hd_hi.ico), which includes a gamut of raster icons individually tailored for small display sizes.
            {
              "icons": [
                {
                  "src": "icon/lowres.webp",
                  "sizes": "48x48",
                  "type": "image/webp"
                },{
                  "src": "icon/lowres",
                  "sizes": "48x48"
                },{
                  "src": "icon/hd_hi.ico",
                  "sizes": "72x72 96x96 128x128 256x256"
                },{
                  "src": "icon/hd_hi.svg",
                  "sizes": "257x257"
                }]
            }
          

Creating shortcuts

In the following example, the developer has included two shortcuts. Assuming the manifest's URL is https://example.com/manifest.webmanifest:

  • The first shortcut would be displayed with the text "Play Later". If the operating system supports icons for context menu items and it also supports SVG images for that purpose, the user agent would present https://example.com/icons/play-later.svg next to the text. When launched, the user agent would instantiate a new top-level browsing context and navigate to https://example.com/play-later.
  • The second shortcut would be displayed with the text "Subscriptions". When launched, the user agent would instantiate a new top-level browsing context and navigate to https://example.com/subscriptions?sort=desc.
            {
              "shortcuts": [
                {
                  "name": "Play Later",
                  "description": "View the list of podcasts you saved for later",
                  "url": "/play-later",
                  "icons": [
                    {
                      "src": "/icons/play-later.svg",
                      "type": "image/svg+xml"
                    }
                  ]
                },
                {
                  "name": "Subscriptions",
                  "description": "View the list of podcasts you listen to",
                  "url": "/subscriptions?sort=desc"
                }
              ]
            }
          

Understanding "scope"

The [=manifest/scope=] member tells the browser which documents are part of a web application, and which are not - and hence, to which set of web pages the manifest is "[=applied=]" when the user navigates around a web site.

For example, `{"scope": "/"}` means that the manifest applies to every document in an origin. On the other hand, `{"scope": "/racer/"}` means that only documents within the path "/racer/" are [=URL/within scope=]: so "/racer/race1.html", "/racer/race2.html", etc. would all be [=URL/within scope=], but "/elsewhere/" and anything at the root "/" would be "out of scope" and the manifest wouldn't apply to documents in those paths. Only one scope path is supported. See [[[#nav-scope]]] for the technical details.

[=Applying=] a manifest means that any members that affect presentation found in the manifest will come into effect, such as display "fullscreen", or applying a particular screen orientation. As long as the application is navigated to URLs that are [=URL/within scope=], the browser will continue to apply the manifest. However, navigating the web applications "out of scope" will cause the manifest to no longer be applied, and the browser will apply its own defaults. This will cause, for example, the application to no longer be displayed in fullscreen, and instead be displayed as a regular web page in a browser tab. It's left up to implementers to decide how to deal with web pages being navigated in and out of scope. See [[[#applying]]] for the technical details.

Finally, as it's possible that a user can install a web application from any document within an origin, it's good practice to always declare a [=manifest/scope=] member in a manifest. If the [=manifest/scope=] member is missing from the manifest, then the path of the [=manifest/start_url=] member is used as a fallback. And if the [=manifest/start_url=] member is also missing, then the document URL from which the web application is installed gets used as the scope. To be sure you don't get any unexpected navigation behavior, always include a [=manifest/scope=] member preferably set to `"/"`.

`dir` member

The [=manifest's=] dir member specifies the default direction for the [=localizable members=] of the [=manifest=]. The [=manifest/dir=] member's value can be set to a [=text-direction=].

The text-directions are the following, implying that the value of the [=localizable members=] is by default:

"ltr"
Left-to-right text.
"rtl"
Right-to-left text.
"auto" (default)
Text direction is unknown. The user agent should use heuristics to estimate the display of the text, for example the first-strong algorithm as described in [[UAX9]].

The text-direction list is the [=list=] « "[=text-direction/ltr=]", "[=text-direction/rtl=]", "[=text-direction/auto=]" ».

To process the `dir` member, given [=ordered map=] |json:ordered map| and [=ordered map=] |manifest:ordered map|:

  1. Set |manifest|["dir"] to "auto".
  2. If |json|["dir"] doesn't [=map/exist=] or if |json|["dir"] is not a [=string=], return.
  3. [=Strip leading and trailing ASCII whitespace=] from |json|["dir"].
  4. [=ASCII lowercase=] |json|["dir"].
  5. If [=text-direction list=] doesn't [=list/contain=] |json|["dir"], return.
  6. Set |manifest|["dir"] to |json|["dir"].

`lang` member

The [=manifest's=] lang member is a [=string=] in the form of a [=language tag=] that specifies the language for the values of the manifest's [=localizable members=]. If the `lang` member is not specified, the language is treated as unknown.

Specifying the language improves the user experience by helping user agents select the most appropriate processing or resources, such as fonts, styling, hyphenation, or text-to-speech voices for accessibility.

A language tag is a [=string=] that matches the production of a well-formed `Language-Tag` defined in [[BCP47]].

Language tags are case-insensitive. Examples of language tags include '`fr`' (French), '`en-AU`' (English as spoken in Australia), or '`zh-Hans-CN`' (Chinese as written in the Simplified Han script as spoken in China).

To process the `lang` member, given [=ordered map=] |json:ordered map| and [=ordered map=] |manifest:ordered map|:

  1. If |json|["lang"] doesn't [=map/exist=] or if |json|["lang"] is not a [=string=], return.
  2. [=Strip leading and trailing ASCII whitespace=] from |json|["lang"].
  3. If calling IsStructurallyValidLanguageTag with |json|["lang"] returns `false`, return.
  4. [=Map/Set=] |manifest|["lang"] to the result of calling the CanonicalizeUnicodeLocaleId abstract operation with |json|["lang"].

`name` member

The [=manifest's=] name member is a string that represents the name of the web application as it is usually displayed to the user (e.g., amongst a list of other applications, or as a label for an icon).

The [=manifest/name=] member is a [=localizable member=].

The [=manifest/name=] member serves as the accessible name of an [=installed web application=].

When [=processing a manifest=], the [=process a text member=] algorithm is used to process the [=manifest/name=] member.

`short_name` member

The [=manifest's=] short_name member is a string that represents a short version of the name of the web application. It is intended to be used where there is insufficient space to display the full name of the web application.

The [=manifest/short_name=] member is a [=localizable member=].

When [=processing a manifest=], the [=process a text member=] algorithm is used to process the [=manifest/short_name=] member.

`scope` member

The [=manifest's=] scope member is a string that represents the [=manifest/navigation scope=] of this web application's application context.

To process the `scope` member, given [=ordered map=] |json:ordered map| and [=ordered map=] |manifest:ordered map|:

  1. Set |manifest|["scope"] to the result of [=URL Parser|parsing=] "." with |manifest|["start_url"] as the base URL.
  2. If |json|["scope"] is the empty string, then return.
  3. Let |scope:URL| be the result of [=URL Parser|parsing=] |json|["scope"] with |manifest URL| as the base URL.
  4. If |scope| is failure, return.
  5. Set |scope|'s [=URL/query=] and [=URL/fragment=] to null.
  6. If |manifest|["start_url"] is not [=URL/within scope=] of |scope|, return.
  7. Otherwise, set |manifest|["scope"] to |scope|.

`icons` member

The [=manifest's=] icons member are images that serve as iconic representations of the web application in various contexts. For example, they can be used to represent the web application amongst a list of other applications, or to integrate the web application with an OS's task switcher and/or system preferences.

The [=manifest/icons=] member is a [=localizable member=].

`display` member

The [=manifest's=] display member represents the developer's preferred display mode for the web application. Its value is a [=display mode=].

To process the `display` member, given [=ordered map=] |json:ordered map| and [=ordered map=] |manifest:ordered map|:

  1. Set |manifest|["display"] to "browser".
  2. If |json|["display"] doesn't [=map/exist=] or |json|["display"] is not a a [=string=], return.
  3. [=Strip leading and trailing ASCII whitespace=] from |json|["display"].
  4. [=ASCII lowercase=] |json|["display"].
  5. If [=display modes list=] doesn't [=list/contain=] |json|["display"], return.
  6. Set |manifest|["display"] to |json|["display"].

`orientation` member

The [=manifest's=] orientation member is a string that serves as the default screen orientation for all top-level browsing contexts of the web application. The possible values are those of the {{OrientationLockType}} enum, which in this specification are referred to as the orientation values (i.e., "any", "natural", "landscape", "portrait", "portrait-primary", "portrait-secondary", "landscape-primary", or "landscape-secondary").

If the user agent supports the value of the [=manifest/orientation=] member as the default screen orientation, then that serves as the default screen orientation for the life of the web application (unless overridden by some other means at runtime). This means that the user agent MUST return the orientation to the default screen orientation any time the orientation is unlocked [[SCREEN-ORIENTATION]] or the top-level browsing context is navigated.

Although the specification relies on the [[SCREEN-ORIENTATION]]'s {{OrientationLockType}}, it is OPTIONAL for a user agent to implement the [[SCREEN-ORIENTATION]] API. Supporting the [[SCREEN-ORIENTATION]] API is, of course, encouraged.

Certain UI/UX concerns and/or platform conventions will mean that some screen orientations and cannot be used together. Which orientations and display modes cannot be used together is left to the discretion of implementers. For example, for some user agents, it might not make sense to change the default screen orientation of an application while in `browser` display mode.

Once the web application is running, other means can change the orientation of a top-level browsing context (such as via [[SCREEN-ORIENTATION]] API).

To process the `orientation` member, given [=ordered map=] |json:ordered map| and [=ordered map=] |manifest:ordered map|:

  1. If |json|["orientation"] doesn't [=map/exist=] or |json|["orientation"] is not a [=string=], return.
  2. [=Strip leading and trailing ASCII whitespace=] from |json|["orientation"].
  3. [=ASCII lowercase=] |json|["orientation"].
  4. If |json|["orientation"] doesn't [=list/contain=] any of the [=orientation values=], return.
  5. Set |manifest|["orientation"] to |json|["orientation"].

`start_url` member

The [=manifest's=] start_url member is a string that represents the start URL , which is URL that the developer would prefer the user agent load when the user launches the web application (e.g., when the user clicks on the icon of the web application from a device's application menu or homescreen).

The [=manifest/start_url=] member is purely advisory, and a user agent MAY ignore it or provide the end-user the choice not to make use of it. A user agent MAY also allow the end-user to modify the URL when, for instance, a bookmark for the web application is being created or any time thereafter.

To process the `start_url` member, given [=ordered map=] |json:ordered map|, [=ordered map=] |manifest:ordered map|, [=URL=] |manifest URL:URL|, and [=URL=] |document URL:URL|:

  1. Set |manifest|["start_url"] to |document URL|.
  2. If |json|["start_url"] doesn't [=map/exist=] or |json|["start_url"] is not a [=string=], return.
  3. If the type of |json|["start_url"] is not [=string=], or if |json|["start_url"] is the empty string, return.
  4. Let |start URL:URL| be the result of [=URL Parser|parsing=] |json|["start_url"], using |manifest URL| as the base URL.
  5. If |start URL| is failure, return.
  6. If |start URL| is not same origin as |document URL|, return.
  7. Otherwise, set |manifest|["start_url"] to |start URL|.

Privacy consideration: [=manifest/start_url=] tracking

It's conceivable that the [=manifest/start_url=] could be crafted to indicate that the application was launched from outside the browser (e.g., `"start_url": "index.html?launcher=homescreen"`). This can be useful for analytics and possibly other customizations. However, it is also conceivable that developers could encode strings into the start_url that uniquely identify the user (e.g., a server-assigned identifier, such as `"?user=123"`, `"/user/123/"`, or `"https://user123.foo.bar"`). This is fingerprinting/privacy sensitive information that the user might not be aware of.

It is bad practice for a developer to use the [=start URL=] to include information that uniquely identifies a user, as it would represent a fingerprint that is not cleared when the user clears site data. However, nothing in this specification can practically prevent developers from doing this.

Given the above, it is RECOMMENDED that, upon installation, or any time thereafter, a user agent allows the user to inspect and, if necessary, modify the [=start URL=] of an application.

A user agent MAY offer other protections against this form of fingerprinting. For example, if a user clears data from an origin, the user agent MAY offer to uninstall applications that are [=manifest/within scope=] of that origin, thus removing the potential fingerprint from the application's start URL.

`id` member

The [=manifest's=] id member is a string that represents the identity for the application. The [=identity=] takes the form of a URL, which is same origin as the [=start URL=].

The [=identity=] is used by user agents to uniquely identify the application universally. When the user agent sees a manifest with an [=identity=] that does not correspond to an already-installed application, it SHOULD treat that manifest as a description of a distinct application, even if it is served from the same URL as that of another application. When the user agent sees a manifest where |manifest|["id"] is [=url/equal=] (with [=URL/equals/exclude fragments=] OPTIONALLY set to true) to the [=identity=] of an already-installed application, it SHOULD be used as a signal that this manifest is a replacement for the already-installed application's manifest, and not a distinct application, even if it is served from a different URL than the one seen previously.

The [=identity=] can be used by a service that collects lists of web applications to uniquely identify applications.

The [=identity=] is processed like a URL but it doesn't point to a resource that can be navigated to, so it's not required to be [=URL/within scope=].

To process the `id` member, given [=ordered map=] |json:JSON|, [=ordered map=] |manifest:ordered map|:

  1. Set |manifest|["id"] to |manifest|["start_url"].
  2. If the type of |json|["id"] is not [=string=], return.
  3. If |json|["id"] is the empty string, return.
  4. Let |base origin| be |manifest|["start_url"]'s [=url/origin=].
  5. Let |id:URL| be the result of [=URL Parser|parsing=] |json|["id"] with |base origin| as the base URL.
  6. If |id| is failure, return.
  7. If |id| is not [=same origin=] as |manifest|["start_url"], return.
  8. Set |id|'s [=URL/fragment=] to null.
  9. Set |manifest|["id"] to |id|.

`theme_color` member

The [=manifest's=] theme_color member serves as the default theme color for an application context. What constitutes a theme color is defined in [[HTML]].

If the user agent honors the value of the [=manifest/theme_color=] member as the [=default theme color=], then that color serves as the [=theme color=] for all [=browsing contexts=] to which the manifest is [=applied=]. However, the user agent MAY override the [=default theme color=] if a [=document=] whose [=Document/URL=] is [=URL/within scope=] of the [=application context=]'s [=manifest=] includes a [^meta^] element whose [^meta/name^] attribute is "[^meta/name/theme-color^]". However, the user agent SHOULD NOT override the [=default theme color=] via a [^meta^] element whose [^meta/name^] attribute is "theme-color" for [=documents=]' [=Document/URL=] are not [=URL/within scope=], since the application has no control over these documents.

The user agent MAY ignore the theme color's [=alpha component=] based on the context. For example, in most environments, the theme color cannot be transparent.

Implementors MAY override the value defined by the [=manifest/theme_color=] member to support prefers-color-scheme.

When [=processing a manifest=], the [=process a color member=] algorithm is used to process the [=manifest/theme_color=] member.

`background_color` member

The [=manifest's=] `background_color` member describes the expected background color of the web application. It repeats what is already available in the application stylesheet but can be used by the user agent to draw the background color of a web application for which the manifest is known before the files are actually available, whether they are fetched from the network or retrieved from disk.

The [=manifest/background_color=] member is only meant to improve the user experience while a web application is loading and MUST NOT be used by the user agent as the background color when the web application's stylesheet is available.

Implementors MAY override the value defined by the [=manifest/background_color=] member to support prefers-color-scheme.

When [=processing a manifest=], the [=process a color member=] algorithm is used to process [=manifest/background_color=] member.

`shortcuts` member

The [=manifest's=] shortcuts member is an [=list=] of shortcut items that provide access to key tasks within a web application.

How shortcuts are presented, and how many of them are shown to the user, is at the discretion of the user agent and/or operating system.

To process the `shortcuts` member, given [=ordered map=] |json:ordered map|, [=ordered map=] |manifest:ordered map|, and [=URL=] |manifest URL:URL|:

  1. Let |processedShortcuts:list| be a new [=list=].
  2. [=Map/Set=] |manifest|["shortcuts"] to |processedShortcuts|.
  3. If |json|["shortcuts"] doesn't [=map/exist=] or |json|["shortcuts"] is not a [=list=], return.
  4. [=list/For each=] |entry:ordered map| of |json|["shortcuts"]:
    1. Let |shortcut:ordered map| be [=process a shortcut=] with |entry|, |manifest URL|, |manifest|["scope"], and |manifest|["dir"].
    2. If |shortcut| is failure, continue.
    3. [=list/Append=] |shortcut| to |processedShortcuts|.

A user agent SHOULD expose shortcuts via interactions that are consistent with exposure of an application icon's context menu in the host operating system (e.g., right click, long press). A user agent SHOULD render the shortcuts in the same order as they are provided in the manifest. A user agent SHOULD represent the shortcuts in a manner consistent with exposure of an application icon's context menu in the host operating system. A user agent MAY truncate the list of shortcuts presented in order to remain consistent with the conventions or limitations of the host operating system.

`*_localized` members

A localizable member is a [=manifest=] member that can be localized. Each [=localizable member=] of the [=manifest=] has a corresponding *_localized member, where `*` represents the member name.

A language map is an [=ordered map=] whose key is a [=language tag=] and whose value is a [=localized value=]. The localized value is content localized in the language given by the key.

The value assigned to the [=localizable member=] is the default representation. [=manifest/*_localized=] members contain a [=language map=] that defines [=localized values=] for the given [=localizable member=] in the application. The user agent SHOULD use the user's localization settings to select the [=localized value=] whose [=language tag=] key best matches the user's preference. When no such [=localized value=] is available, the [=localizable member/default representation=] is used.

Localizing text values

A localized text object is an [=ordered map=] with the following properties:

value
The localized [=string=].
dir (optional)
The [=text-direction=].
lang (optional)
A [=language tag=].

For [=localizable members=] that accept [=strings=], the [=manifest/*_localized=] member's [=language map=] accepts either a [=string=] or a [=localized text object=] as the [=localized value=].

When a [=string=] is used, or when the [=manifest/*_localized/dir=] member of the [=localized text object=] is missing, the [=default direction=] ([=manifest/dir=] member of the [=manifest=]) is applied.

When a [=string=] is used, or when the [=manifest/*_localized/lang=] member of the [=localized text object=] is missing, the [=language tag=] of the [=language map=] key is applied.

To process a `*_localized` text member, given [=ordered map=] |json:ordered map|, [=ordered map=] |map:ordered map|, [=string=] |member:string|, and [=text-direction=] |defaultDirection:string|:

  1. If |member| does not [=map/exist=] in |json|, return.
  2. Let |languageMap| be |json|[|member|].
  3. If |languageMap| is not an [=ordered map=], return.
  4. Let |languageTags:ordered set| be the [=map/keys=] of |languageMap:ordered map|.
  5. Set |map|[|member|] to a new [=ordered map=].
  6. [=Set/For each=] |languageTag:string| of |languageTags|, run [=process a localized text object=], passing |languageMap|[|languageTag|], |languageTag|, |map|, |member|, and |defaultDirection|.

To process a localized text object, given [=string=] or [=ordered map=] |localizedValue|, [=string=] |defaultLanguageTag:string|, [=ordered map=] |map:ordered map|, [=string=] |member:string|, and [=text-direction=] |defaultDirection:string|:

  1. Let |normalizedValue:ordered map| be an [=ordered map=].
  2. If |localizedValue| is a [=string=], [=strip leading and trailing ASCII whitespace=] from |localizedValue:string| and [=map/set=] |normalizedValue|["value"] to |localizedValue|.
  3. If |localizedValue:ordered map| is an [=ordered map=]:
    1. If "value" [=map/exists=] in |localizedValue| and |localizedValue|["value"] is a [=string=], [=strip leading and trailing ASCII whitespace=] from |localizedValue|["value"] and [=map/set=] |normalizedValue|["value"] to |localizedValue|["value"].
    2. If "lang" [=map/exists=] in |localizedValue| and |localizedValue|["lang"] is a [=string=], [=strip leading and trailing ASCII whitespace=] from |localizedValue|["lang"] and [=map/set=] |normalizedValue|["lang"] to |localizedValue|["lang"].
    3. If "dir" [=map/exists=] in |localizedValue| and |localizedValue|["dir"] is a [=string=]:
      1. [=Strip leading and trailing ASCII whitespace=] from |localizedValue|["dir"].
      2. If [=text-direction list=] [=list/contains=] |localizedValue|["dir"], [=map/set=] |normalizedValue|["dir"] to |localizedValue|["dir"].
  4. If "value" does not [=map/exist=] in |normalizedValue|, return.
  5. If "lang" does not [=map/exist=] in |normalizedValue|, [=map/set=] |normalizedValue|["lang"] to |defaultLanguageTag|.
  6. If "dir" does not [=map/exist=] in |normalizedValue|, [=map/set=] |normalizedValue|["dir"] to |defaultDirection|.
  7. If calling IsStructurallyValidLanguageTag with |normalizedValue|["lang"] or calling IsStructurallyValidLanguageTag with |defaultLanguageTag| returns `false`, return.
  8. [=Map/Set=] |map|[|member|][|defaultLanguageTag|] to |normalizedValue|.

The [=process a localized text object=] algorithm takes both a [=string=] or a [=localized text object=] for the [=localized value=] parameter, but the processed result will be normalized into a [=localized text object=] with the [=manifest/*_localized/value=], [=manifest/*_localized/lang=], and [=manifest/*_localized/dir=] members set.

Localizing image resources

For [=localizable members=] that accept a [=list=] of [=image resources=], the [=manifest/*_localized=] member's [=language map=] accepts a [=list=] of [=image resources=] as the [=localized value=].

To process a `*_localized` image resource member, given [=ordered map=] |json:ordered map|, [=ordered map=] |map:ordered map|, [=string=] |member:string|, and [=URL=] |manifest URL:URL|:

  1. If |member| does not [=map/exist=] in |json|, return.
  2. Let |languageMap| be |json|[|member|].
  3. If |languageMap| is not an [=ordered map=], return.
  4. Let |languageTags:ordered set| be the [=map/keys=] of |languageMap:ordered map|.
  5. [=Map/Set=] |map|[|member|] to a new [=ordered map=].
  6. [=List/For each=] |languageTag:string| of |languageTags|:
    1. If calling IsStructurallyValidLanguageTag with |languageTag| returns `false`, [=iteration/continue=].
    2. Run [=process image resources=], passing |languageMap|[|languageTag|] as the [=list=] of [=image resources=], |map|[|member|], |manifest URL|, and |languageTag| as the member.

Manifest life-cycle

This section defines algorithms for [=processing a manifest=], and applying a manifest.

A user agent MUST support the link type "manifest" and the associated steps for how to fetch and process the linked resource.

Processing the manifest

When instructed to ignore, the user agent MUST act as if whatever manifest, member, or value caused the condition is absent.

The following algorithm provides an processing extension-point: other specifications that add new members to the manifest are encouraged to hook themselves into this specification at this point in the algorithm. They SHOULD NOT modify the existing values already in the manifest object.

The [=application manifest/processing extension-point=] is meant to help avoid issues related to monkey patching.

The steps for processing a manifest are given by the following algorithm. The algorithm takes a [=URL=] |document URL:URL|, a [=URL=] |manifest URL:URL|, and a [=byte sequence=] |bodyBytes|.

  1. Let |json| be the result of [=parse JSON bytes to an Infra value=] passing |bodyBytes|.
  2. If the |json| is a parsing exception, or |json| is not an [=ordered map=]:
    1. Set |json:ordered map| to an empty [=ordered map=].
  3. Let |manifest:ordered map| be an empty [=ordered map=].
  4. [=Process the `dir` member=] passing |json| and |manifest|.
  5. [=Process the `lang` member=] passing |json| and |manifest|.
  6. [=Process a text member=] passing |json|, |manifest|, and "name".
  7. [=Process a `*_localized` text member=] passing |json|, |manifest|, "name_localized", and |manifest|["dir"].
  8. [=Process a text member=] passing |json|, |manifest|, and "short_name".
  9. [=Process a `*_localized` text member=] passing |json|, |manifest|, "short_name_localized", and |manifest|["dir"].
  10. [=Process the `start_url` member=] passing |json|, |manifest|, |manifest URL|, and |document URL|.
  11. [=Process the `id` member=] passing |json| and |manifest|.
  12. If the [=document=]'s [=document|processed manifest=] is not null, and [=document=]'s [=document|processed manifest=]'s id is not [=URL/equal=] to |manifest|["id"], return.
  13. [=Process the `scope` member=] passing |json|, |manifest|, and |manifest URL|.
  14. [=Process a color member=] passing |json|, |manifest|, and "theme_color".
  15. [=Process a color member=] passing |json|, |manifest|, and "background_color".
  16. [=Process the `display` member=] passing |json| and |manifest|.
  17. [=Process image resources=] passing |json|["icons"], |manifest|, |manifest URL|, and "icons".
  18. [=Process a `*_localized` image resource member=] passing |json|, |manifest|, "icons_localized", and |manifest URL|.
  19. [=Process the `orientation` member=] passing |json|, |manifest|.
  20. [=Process the `shortcuts` member=] passing |json|, |manifest|, and |manifest URL|.
  21. [=application manifest/Processing extension-point=]: process any proprietary and/or other supported members at this point in the algorithm.
  22. Let [=document=]'s processed manifest be |manifest|.

Processing color members

Only [=sRGB=] colors, and colors the user agent can convert to [=sRGB=] without any outside knowledge (e.g., `"AliceBlue"`), are supported. For example, `lab(…)` or `color(display-p3, …)` can be converted to [=sRGB=] without outside knowledge, but `color(--custom-profile, …)` would require finding a matching "@color-profile" rule which cannot be specified in the manifest.

To process a color member, using [=ordered map=] |json:ordered map|, [=ordered map=] |map:ordered map|, and [=string=] |member:string|:

  1. If |json|[member] doesn't [=map/exist=] or |json|[member] is not a [=string=], return.
  2. [=Strip leading and trailing ASCII whitespace=] from |json|[|member|].
  3. Let |color| be the result of [=CSS/parsing=] the value of |json|[member] as a CSS color.
  4. If |color| is failure, return.
  5. If |color| can be converted to [=sRGB=] using solely information the user agent inherently knows, then convert |color| to [=sRGB=].
  6. If |color| is not [=sRGB=] color, return.
  7. Set |map|[member] to |color|.

Processing text members

To process a text member, given [=ordered map=] |json:ordered map|, [=ordered map=] |map:ordered map|, and [=string=] |member:string|:

  1. If |json|[|member|] doesn't [=map/exists=] or |json|[|member|] is not a [=string=], return.
  2. [=Strip leading and trailing ASCII whitespace=] from |json|[|member|].
  3. Set |map|[member] to the value of |json|[|member|].

Processing the manifest without a document

The [=processing a manifest=] steps are invoked by [[HTML]]'s processing steps for the [^link^] element, but MAY also be invoked by the user agent to process a manifest without an associated [=document=].

In this case, to match the guarantees made by the corresponding steps in [[HTML]], the user agent SHOULD ensure that at least at some point in the past:

  • there was at least one [=document=] that is [=same origin=] as |document URL:URL| that has a [^link^] element |linkElement:HTMLLinkElement| with a [^link/rel^] of [^link/rel/manifest^] and a [^link/href^] that resolves to |manifest URL:URL|, and that
  • if |manifest URL| is not [=same origin=] as |document URL|, the |bodyBytes:byte sequence| data was [=fetch|fetched=] with a [=CORS Request=] whose `Origin` is |document URL|'s [=url/origin=], and whose [=Request/credentials mode=] is set to the [=CORS settings attribute credentials mode=] for |linkElement|'s [^link/crossorigin^] attribute.

Applying the manifest

A [=Document/processed manifest=] is applied to a [=top-level browsing context=], meaning that the members of the [=manifest=] are affecting the presentation and/or behavior of the browsing context. Whenever a [=top-level browsing context=] is created, the user agent MAY [=apply=] a manifest to it before [=navigate|navigation=] begins.

A top-level browsing context that has a manifest applied to it is referred to as an application context.

If an application context is created as a result of the user agent being asked to navigate to a deep link, the user agent MUST immediately navigate to the deep link with historyHandling set to "`replace`". Otherwise, when the application context is created, the user agent MUST immediately navigate to the start URL with historyHandling set to "`replace`".

Updating the manifest

As specified for [^link/rel/manifest^] link relation, the manifest is fetched and processed on every page load. When the [=processing a manifest=] is successful, user agents MAY apply updated manifest to any current and future application contexts associated with the application.

For the purpose of updating, the following member are security-sensitive members, as they are presented during installation and on launch surfaces:

  1. [=manifest/short_name=] and localized representations in `short_name_localized`,
  2. [=manifest/icons=] and localized representations in `icons_localized`,
  3. [=manifest/name=] and localized representations in `name_localized`.

[=Security-sensitive members=] SHOULD be displayed in a bidirectionally isolated way as described in [[UTS55]], regardless of their direction.

User agents SHOULD NOT automatically apply changes to [=security-sensitive members=] without [=express permission=] from the user.

Instead, user agents SHOULD present changes to [=security-sensitive members=] with appropriate management options, so the user can make an informed decision about updating the web application.

The user agent MAY automatically apply the changes if the update does not contain changes to [=security-sensitive members=].

If a user changes localization settings, the user agent MAY automatically adjust the [=security-sensitive members=] visible on launch surfaces to their localized representations specified in the [=manifest/`*_localized`=] members. These changes SHOULD be presented to users the next time they open the web application.

Manifest image resources

Each manifest image resource is an [=image resource=] that is conceptually part of a web application, suitable to use in various contexts depending on the semantics of the member that is using the object (e.g., an icon that is part of an application menu, etc.).

A [=manifest image resource=] differs from a [=image resource=] in that it can have an additional [=manifest image resource/purpose=] member.

User agents MAY modify the images associated with an [=manifest image resource=] to better match the platform’s visual style before displaying it to the user, for example by rounding the corners or painting it in a specific color. It is recommended that developers prepare their image resources for such scenarios to avoid losing important information through, e.g., change of color or clipped corners.

`purpose` member

The purpose member is an unordered set of unique space-separated tokens. The allowed values are the icon purposes.

When a [=manifest image resource=] is used as an icon, a developer can hint that the image is intended to serve some special purpose in the context of the host OS (i.e., for better integration). User agents SHOULD NOT use an icon other than for its stated icon purpose.

For example, an icon with purpose "[=icon purpose/monochrome=]" could be used as a badge or pinned icon with a solid fill, visually distinct from an application's full color launch icon. The user agent uses the value of the [=manifest image resource/purpose=] member as a hint to determine where and how an [=manifest image resource/purpose=] is displayed. Unless declared otherwise by the developer, a user agent can use an icon for [=icon purpose/any|any purpose=].

The icon purposes are as follows:

monochrome
A user agent can present this icon where a monochrome icon with a solid fill is needed. The color information in the icon is discarded and only the alpha data is used. The icon can then be used by the user agent like a mask over any solid fill.
maskable
The image is designed with icon masks and safe zone in mind, such that any part of the image that is outside the safe zone can safely be ignored and masked away by the user agent.
any (default)
The user agent is free to display the icon where no [=manifest image resource/purpose=] is required. For example, a [=manifest image resource=] with a "any" purpose wouldn't be used in a context where "[=icon purpose/monochrome=]" is required.

The icon purposes list is the [=list=] « "[=icon purpose/monochrome=]", "[=icon purpose/maskable=]", "[=icon purpose/any=]" ».

If an icon contains multiple purposes, it could be used for any of those purposes. If none of the stated purposes are recognized, the icon is totally ignored. For example, if an icon has purpose `"monochrome fizzbuzz"`, then it could be used as a monochrome icon, as `"monochrome"` is a valid purpose. However, if an icon just has the purpose `"fizzbuzz"`, then it will be ignored.

To determine the purpose of an image, given [=ordered map=] |json:image|:

  1. If |json|["purpose"] doesn't [=map/exist=] or if |json|["purpose"] is not a [=string=]:
    1. Return [=set=] « "any" ».
  2. Let |keywords:list<string>| be the result of [=split on ASCII whitespace=] |json|["purpose"].
  3. Let |purposes:set| be new [=set=].
  4. [=set/For each=] |keyword:string| of |keywords|:
    1. If [=icon purposes list=] doesn't [=list/contain=] |keyword|, then [=iteration/continue=].
    2. Otherwise, [=set/append=] |keyword| to |purposes|.
  5. If |purposes| [=list/is empty=], then return failure.
  6. Return |purposes|.

Content security policy

The security policy that governs whether a user agent can fetch an icon image is governed by the `img-src` directive [[CSP3]] associated with the manifest's owner {{Document}}.

Icon masks and safe zone

Some platforms have their own preferred icon shape, but as web applications should work across multiple platforms, it is possible to indicate that an icon can have a user-agent-specified mask applied by adding the [=icon purpose/maskable=] purpose. This allows the platform to ensure that the icon looks well integrated with the platform, and even apply different masks and background colors in different places throughout the platform.

The safe zone is the area within a [=icon purpose/maskable=] icon which is guaranteed to always be visible, regardless of user agent preferences. It is defined as a circle with center point in the center of the icon and with a radius of 2/5 (40%) of the icon size, which means the smaller of the icon width and height, in case the icon is not square.

Designers of [=icon purpose/maskable=] icons will want to make sure that all important parts are within the safe zone.

safe zone illustrated
The safe zone is a centrally positioned circle, with radius 2/5 (40%) of the minimum of the icon's width and height.

All pixels in this zone are guaranteed to be seen in all masks. Pixels outside the safe zone are not guaranteed to (but can) be visible depending on the applied mask.

The user agent MAY apply a mask of any size, making any pixels that are more than 2/5ths of the image size (minimum of width and height if non-square) away from the center (the safe zone) transparent.

The user agent MUST NOT make any pixel within the safe zone transparent.

The user agent MAY enlarge the icon by adding additional padding.

If the icon contains transparent pixels, the user agent MUST composite the icon onto a solid fill (e.g., white) of the user agent's choice.

It is suggested that designers avoid using transparent pixels in maskable icons.

Examples of masks

By staying inside the safe zone, most icons will have around 10% padding on the top, bottom, right and left with no content or non-essential content, such as an icon background. It is suggested that developers check their icon when all but the safe zone is masked out.

Icons with "maskable" purpose

An icon over a checkerboard background
Image The base image with transparent background
An icon in a purple circle (40% of the size) over a yellow background
Safe zone Circle with radius 2/5 (40%) of the icon size

Mask examples

An icon inside a rounded yellow square on a purple background
Rounded square Android
An icon inside an extremely rounded yellow square on a purple background
Squircle Android
An icon inside a rounded yellow circle on a purple background
Circle Android
An icon inside a somewhat rounded yellow square on a purple background
Rounded square iOS
An icon on a yellow background
Fullbleed Windows

Monochrome icons and solid fills

Some platforms enforce that icons be displayed with a solid fill such as a single color, where only the transparency of the icon can be declared in a [=manifest=]. As web applications need to work across multiple platforms, it is possible to indicate that an icon can have an user-agent-specified color applied by adding the [=icon purpose/monochrome=] purpose. This allows the platform to ensure that the icon looks well integrated with the platform, and even apply different colors and padding in different places throughout the platform.

When presenting a [=icon purpose/monochrome=] icon, the user agent MUST NOT independently display the red component, green component, or blue component of a pixel. The user agent SHOULD display each pixel with its original alpha value, but with a red, green, and blue value of the user agent's choosing. It is RECOMMENDED that the user agent use the same color value for all pixels.

Designers of [=icon purpose/monochrome=] icons could set all pixels to black and only use transparency to create a silhouette of their icon.

The user agent MAY enlarge the icon by adding additional padding.

The user agent MAY add a background of any color behind transparent pixels, and SHOULD ensure that the background has sufficient contrast with the icon.

Example usage of monochrome icons

Usage examples

A black icon over a checkerboard background
Image The base image with no color.
A dark gradient icon over a checkerboard background
Gradient fill The image filled in with a gradient.
A dark yellow icon over a light gray background
Solid color fill with padding Filled in with the theme color from the manifest.

Processing image resources

To process image resources, given [=list=] |images:list|, [=ordered map=] |map:ordered map|, |manifest URL:URL| and [=string=] |member:string|:

  1. Let |imageResources:List<Image Resources>| be a new [=list=].
  2. Set |map|[member] to |imageResources|.
  3. If |images| is not [=list=], return.
  4. [=list/For each=] |potential image:Manifest image resource| of |images|:
    1. Let |image:ordered map| be the result of running [=process an image resource from JSON=] given |potential image| and |manifest URL|.
    2. If |image| is failure, [=iteration/continue=].
    3. Let |purposes:set| be [=determine the purpose of an image=] passing |potential image|.
    4. If |purposes| is failure, [=iteration/continue=].
    5. Set |image|["purpose"] to |purposes|.
    6. [=list/Append=] |image| to |imageResources|.

Shortcut items

Each shortcut item is an [=ordered map=] that represents a link to a key task or page within a web app. It has the following members:

A user agent can use these members to assemble a context menu to be displayed by the operating system when a user engages with the web app's icon. When the user invokes a shortcut from the operating system menu, the user agent SHOULD run launching a shortcut.

`name` member

The [=shortcut item's=] name member is a string that represents the name of the shortcut as it is usually displayed to the user in a context menu.

The [=shortcut item/name=] member is a [=localizable member=].

`short_name` member

The [=shortcut item's=] short_name member is a string that represents a short version of the name of the shortcut. It is intended to be used where there is insufficient space to display the full name of the shortcut.

The [=shortcut item/short_name=] member is a [=localizable member=].

`description` member

The [=shortcut item's=] description member is a string that allows the developer to describe the purpose of the shortcut. User agents MAY expose this information to assistive technology.

The [=shortcut item/description=] member is a [=localizable member=].

`url` member

The [=shortcut item's=] url member is a URL [=manifest/within scope=] of a [=Document/processed manifest=] that opens when the associated shortcut is activated.

`icons` member

The shortcut item's icons member lists images that serve as iconic representations of the shortcut in various contexts.

The [=shortcut item/icons=] member is a [=localizable member=].

Launching a shortcut

When shortcut item shortcut having manifest is invoked, run the steps to [=launch a web application=] with manifest and shortcut.url.

Processing shortcut items

To process a shortcut, given [=ordered map=] |item:ordered map|, [=URL=] |manifest URL:URL|, [=URL=] |scope:URL|, and [=text-direction=] |defaultDirection:string|:

  1. Return failure if it's the case that:
    • |item| is not [=ordered map=].
    • |item|["name"] doesn't [=map/exist=].
    • |item|["name"] is the empty string.
    • |item|["url"] doesn't [=map/exist=].
    • |item|["url"] is not a [=string=].
  2. Let |url:URL| be the result of [=URL Parser|parsing=] |item|["url"] with |manifest URL| as the base URL.
  3. If |url| is failure, return failure.
  4. If |url| is not [=manifest/within scope=] of |scope|, return failure.
  5. Let |shortcut:ordered map| be |ordered map| «[ "url" → |url|, "name" → |item|["name"] ]».
  6. [=Process a `*_localized` text member=] passing |item|, |shortcut|, "name_localized", and |defaultDirection|.
  7. If "short_name" [=map/exists=] in |item|, and |item|["short_name"] is a [=string=], [=map/set=] |shortcut|["short_name"] to |item|["short_name"].
  8. [=Process a `*_localized` text member=] passing |item|, |shortcut|, "short_name_localized", and |defaultDirection|.
  9. If "description" [=map/exists=] in |item|, and |item|["description"] is a [=string=], [=map/set=] |shortcut|["description"] to |item|["description"].
  10. [=Process a `*_localized` text member=] passing |item|, |shortcut|, "description_localized", and |defaultDirection|.
  11. [=Process image resources=] passing |item|["icons"], |shortcut|, |manifest URL|, and "icons".
  12. [=Process a `*_localized` image resource member=] passing |item|, |shortcut|, "icons_localized", and |manifest URL|.
  13. Return |shortcut|.

Installable web applications

A common use case of a manifest is for a user agent to install a web application; whereby the user agent provides the end-user with a means of instantiating a new top-level browsing context that has the manifest's members applied to it. A web application that is installed is known as a installed web application. That is, the manifest's members, or their defaults, are in effect on the top-level browsing context. This distinguishes an installed web application from a traditional bookmark, as opening a web page from a traditional bookmark will not have the manifest's properties applied to it.

For example, on user agents that support installation, a web application could be presented and launched in a way that, to the end-user, is indistinguishable from native applications: such as appearing as a labeled icon on the home screen, launcher, or start menu. When [=launching a web application=], the manifest is applied by the user agent to the top-level browsing context prior to the start URL being loaded. This gives the user agent an opportunity to apply the relevant values of the manifest, possibly changing the display mode and screen orientation of the web application. Alternatively, and again as an example, the user agent could install the web application into a list of bookmarks within the user agent itself.

Application's name

The application's name is derived from either the [=manifest/name=] member or [=manifest/short_name=] member. The user agent SHOULD first resolve the localized values from their corresponding [=manifest/`*_localized`=] members.

When either the [=manifest/name=] member or the [=manifest/short_name=] member is missing, empty, or the wrong type, a user agent MAY use the [=manifest/name=] member as a fallback for the [=manifest/short_name=] member or [=manifest/short_name=] member as the fallback for the [=manifest/name=] member.

If the [=manifest/name=] and [=manifest/short_name=] members are missing, empty, or the wrong type, a user agent MAY fallback to the {{Document}} to find suitable replacements for missing manifest members (e.g., using `application-name` in place of [=manifest/name=] or [=manifest/short_name=]). Alternatively, the user agent SHOULD assign a default name (e.g., "Untitled") that follows platform conventions. Alternatively, a user agent MAY allow the end-user to input some text that can serve as the application's name.

When both the [=manifest/name=] and [=manifest/short_name=] members are present, it is left up to implementations to decide which member is best suited for the space available (e.g., the [=manifest/short_name=] member might be better suited for the space available underneath an icon).

Launching a web application

At the discretion of the operating system or user agent, run the steps to [=launch a web application=] with a [=Document/processed manifest=].

This would typically take place when the user selects an [=installed=] web app from an app launching UI surface e.g., a home screen, launcher or start menu.

The steps to launch a web application is given by the following algorithm. The algorithm takes a [=Document/processed manifest=] |manifest:processed manifest|, an optional [=URL=] |target URL:URL|, an optional [=POST resource=] |POST resource| and returns an [=application context=].

|target URL|, if given, MUST be [=manifest/within scope=] of |manifest|.

Other specifications MAY replace this algorithm's steps with their own steps. This replacement will take effect for all invocations of [=launch a web application=].

This algorithm is replaceable to allow an experimental launch_handler manifest field to configure the behavior of all web application launches. The replacement algorithm invokes [=create a new application context=] by default but under certain conditions behaves differently.

  1. Return the result of running the steps to [=create a new application context=] passing |manifest|, |target URL| and |POST resource|.

The steps to create a new application context is given by the following algorithm. The algorithm takes a [=Document/processed manifest=] |manifest:processed manifest|, an optional [=URL=] |target URL:URL|, an optional [=POST resource=] |POST resource| and returns an [=application context=].

  1. If |target URL| was not given, set |target URL| to [=start URL=].
  2. Let |traversable| be the result of running the steps to [=create a fresh top-level traversable=] with |target URL| and |POST resource|.
  3. Let |browsing context| be the |traversable|'s active browsing context.
  4. [=Apply=] |manifest| to |browsing context|.
  5. Return |browsing context|.

Privacy and security considerations

It is RECOMMENDED that UI that affords the end user the ability to install a web application also allows inspecting the icon, name, start URL, origin, etc. pertaining to a web application. This is to give an end-user an opportunity to make a conscious decision to approve, and possibly modify, the information pertaining to the web application before installing it. This also gives the end-user an opportunity to discern if the web application is spoofing another web application, by, for example, using an unexpected icon or name.

It is RECOMMENDED that user agents prevent other applications from determining which applications are installed on the system (e.g., via a timing attack on the user agent's cache). This could be done by, for example, invalidating from the user agent's cache the resources linked to from the manifest (for example, icons) after a web application is installed - or by using an entirely different cache from that used for regular web browsing.

Uninstallation

User agents SHOULD provide a mechanism for the user to remove an installed web application application.

It is RECOMMENDED that at the time of removal, the user agent also present the user with an opportunity to revoke other persistent data and settings associated with the application, such as permissions and persistent storage.

Display modes

A display mode represents how the web application is being presented within the context of an OS (e.g., in fullscreen, etc.). Display modes correspond to user interface (UI) metaphors and functionality in use on a given platform. The UI conventions of the display modes are purely advisory and implementers are free to interpret them how they best see fit.

This specification defines the following [=display modes=]:

fullscreen
Opens the web application with browser UI elements hidden and takes up the entirety of the available display area.
standalone
Opens the web application to look and feel like a standalone native application. This can include the application having a different window, its own icon in the application launcher, etc. In this mode, the user agent will exclude standard browser UI elements such as an URL bar, but can include other system UI elements such as a status bar and/or system back button.
minimal-ui
This mode is similar to [=display mode/standalone=], but provides the end-user with some means to access a minimal set of UI elements for controlling navigation (i.e., back, forward, reload, and perhaps some way of viewing the document's address). A user agent can include other platform specific UI elements, such as "share" and "print" buttons or whatever is customary on the platform and user agent.
browser (default)
Opens the web application using the platform-specific convention for opening hyperlinks in the user agent (e.g., in a browser tab or a new window).

The [=display mode/fullscreen=] display mode is orthogonal to, and works independently of, the [[[FULLSCREEN]]]. The [=display mode/fullscreen=] display mode affects the fullscreen state of the browser window, while the [[FULLSCREEN]] API operates on an element contained within the viewport. As such, a web application can have its display mode set to [=display mode/fullscreen=], while `document.fullScreenElement` returns `null`, and `fullscreenEnabled` returns `false`.

Once a user agent [=applies=] a particular display mode to an application context, it becomes the default display mode for the top-level browsing context (i.e., it is used as the display mode when the window is navigated). The user agent MAY override the default display mode for security reasons (e.g., the top-level browsing context is navigated to another origin) and/or the user agent MAY provide the user with a means of switching to another display mode.

When the [=manifest/display=] member is missing, or if there is no valid [=manifest/display=] member, the user agent uses the [=display mode/browser=] display mode as the default display mode. As such, the user agent MUST support the [=display mode/browser=] display mode.

Every [=display mode=] has a fallback chain, which is a list of [=display modes=]. The [=fallback chain=] for:

  1. [=display mode/browser=] is «».
  2. [=display mode/minimal-ui=] is « "[=display mode/browser=]" ».
  3. [=display mode/standalone=] is « "[=display mode/minimal-ui=]", "[=display mode/browser=]" ».
  4. [=display mode/fullscreen=] is « "[=display mode/standalone=]", "[=display mode/minimal-ui=]", "[=display mode/browser=]" ».

The steps for determining the web app's chosen display mode is given by the following algorithm. The algorithm takes a [=Document/processed manifest=] |manifest:processed manifest| and returns a [=display mode=].

  1. [=application manifest/processing extension-point=]: process any proprietary and/or other supported display modes at this point in the algorithm.
  2. If the user agent supports |manifest|["display"], then return |manifest|["display"].
  3. [=list/For each=] |fallback_mode| of the [=fallback chain=] of |manifest|["display"]:
    1. If the user agent supports the |fallback_mode|, then return |fallback_mode|.

The above loop is guaranteed to return a value before the assertion, due to the fact that [=display mode/browser=] is in every mode's [=fallback chain=], and the requirement that all user agents support the [=display mode/browser=] [=display mode=].

The display modes list is the [=list=] « "[=display mode/fullscreen=]", "[=display mode/standalone=]", "[=display mode/minimal-ui=]", "[=display mode/browser=]" ».

A user agent MUST reflect the applied display mode of the web application in the `display-mode` media feature [[MEDIAQUERIES-5]].

A user agent will expose the actual display mode being applied — not necessarily the one declared in the manifest — via the `display-mode` media feature, accessible through CSS or JavaScript. Note that this media feature will also reflect other display modes for a web page when a manifest is not being applied. For example, if the end-user puts the page into fullscreen, then the user agent would reflect this change to CSS and scripts via the `display-mode` media feature.

Privacy and security considerations

This specification does not directly deal with high-value data. However, installed web applications and their data could be seen as "high value" (particularly from a privacy perspective).

As the manifest format is JSON and will be encoded using [[UNICODE]], the security considerations described in [[JSON]] and [[UNICODE-SECURITY]] apply. In addition, because there is no way to prevent developers from including custom/unrestrained data in a manifest, implementors need to impose their own implementation-specific limits on the values of otherwise unconstrained member types, e.g. to prevent denial of service attacks, to guard against running out of memory, or to work around platform-specific limitations.

Web applications will generally contain ECMAScript, HTML, CSS files, and other media, which are executed in a sand-boxed environment. As such, implementors need to be aware of the security implications for the types they support. Specifically, implementors need to consider the security implications outlined in at least the following specifications: [[CSS-MIME]], [[ECMAScript-MIME]], [[HTML]].

As web applications can contain content that is able to simultaneously interact with the local device and a remote host, implementors need to consider the privacy implications resulting from exposing private information to a remote host. Mitigation and in-depth defensive measures are an implementation responsibility and not prescribed by this specification. However, in designing these measures, implementors are advised to enable user awareness of information sharing, and to provide easy access to interfaces that enable revocation of permissions.

As this specification allows for the declaration of URLs within certain members of a manifest, implementors need to consider the security considerations discussed in the [[URL]] specification. Implementations intending to display IRIs and IDNA addresses found in the manifest are strongly encouraged to follow the security advice given in [[UNICODE-SECURITY]].

Developers need to be aware of the security considerations discussed throughout the [[CSP3]] specification, particularly in relation to making `data:` a valid source for the purpose of inlining a manifest. Doing so can enable XSS attacks by allowing a manifest to be included directly in the document itself; this is best avoided completely.

It is RECOMMENDED that UI that affords the end user the ability to install a web application also allows inspecting the icon, name, start URL, origin, etc. pertaining to a web application. This is to give an end-user an opportunity to make a conscious decision to approve, and possibly modify, the information pertaining to the web application before installing it. This also gives the end-user an opportunity to discern if the web application is spoofing another web application, by, for example, using an unexpected icon or name.

It is RECOMMENDED that user agents prevent other applications from determining which applications are installed on the system (e.g., via a timing attack on the user agent's cache). This could be done by, for example, invalidating from the user agent's cache the resources linked to from the manifest (for example, icons) after a web application is installed - or by using an entirely different cache from that used for regular web browsing.

It's conceivable that a shortcut [=shortcut item/url=] could be crafted to indicate that the application was launched from outside the browser (e.g., `"url": "/task/?from=homescreen"`). It is also conceivable that developers could encode strings into the [=shortcut item/url=] that uniquely identify the user (e.g., a server assigned UUID). This is fingerprinting/privacy sensitive information that the user might not be aware of.

When the web application is running, it is RECOMMENDED that the user agent provides the end-user a means to access common information about the web application, such as the origin, start and/or current URL, granted permissions, and associated icon. How such information is exposed to end-users is left up to implementers.

Additionally, when applying a manifest that sets the display mode to anything except "[=display mode/browser=]", it is RECOMMENDED that the user agent clearly indicate to the end-user that their are leaving the normal browsing context of a web browser. Ideally, launching or switching to a web application is performed in a manner that is consistent with launching or switching to other applications in the host platform. For example, a long and obvious animated transition, or speaking the text "Launching application X".

The `display` member allows an origin some measure of control over a user agent’s native UI. After taking over the full screen, it could attempt to mimic the user interface of another application. This is also facilitated by the `'display-mode'` media feature [[MEDIAQUERIES-5]], through which a script can know the display mode of a web application.

IANA considerations

The mime type application/manifest+json is the application manifest media type. Both the mime type and the `.webmanifest` file extension are registered with the Internet Assigned Numbers Authority (IANA).

Media type registration

If the protocol over which the manifest is transferred supports the [[MIME-TYPES]] specification (e.g. HTTP), it is RECOMMENDED that the manifest be labeled with the [=application manifest media type=].

Type name:
application
Subtype name:
manifest+json
Required parameters:
N/A
Optional parameters:
N/A
Encoding considerations:
Same as for application/json ([[RFC7159]] section 8.1)
Privacy and security considerations:
See [[[#priv-sec]]].
Applications that use this MIME type:
Web browsers
Additional information:
Magic number(s):
N/A
File extension(s):
.webmanifest
Macintosh file type code(s):
TEXT
Person & email address to contact for further information:
The Web Applications Working Group can be contacted at public-webapps@w3.org.
Intended usage:
COMMON
Restrictions on usage:
none
Author:
W3C's Web Applications Working Group.
Change controller:
W3C.

Link relation type registration

Relation Name:
manifest
Description:
Links to a manifest. A manifest provides developers with a centralized place to put metadata associated with a web application.
Reference:
https://www.w3.org/TR/appmanifest/
Notes:
See link type "manifest" for details about how a web manifest is [=fetched=] [=processing a manifest|processed=].

There is only one class of product that can claim conformance to this specification: a [=user agent=].

Although this specification is primarily targeted at web browsers, it is feasible that other software could also implement this specification in a conforming manner. For instance, search engines, or crawlers, could find and process manifests to build up catalogs of sites that potentially work as installable web applications.

Extensibility

This specification is designed to be extensible. Other specifications are encouraged to define new members for the manifest. However, in doing so, please follow the conventions used in this specification. In particular, use the [=application manifest/processing extension-point=] to hook into the steps for processing a manifest. Also, be sure to specify the steps for processing your particular member in the manner set forth in this specification. This will help keep this part of the platform consistent.

To allow the community to easily find extensions, please add your extensions to the Extensions Registry.

When specifying a new member, don't override or monkey patch anything defined in this specification. Also, don't assume your member will be processed before or after any other member. Keep your new member, and its processing, atomic and self contained. Note also that implementations are free to ignore any member they do not recognize or support.

If you are writing a specification and temporarily want to patch this specification to help implementations along, file a bug so the community is informed of what you are trying to do.

Proprietary manifest members

Although proprietary extensions are undesirable, they can't realistically be avoided. If a user agent chooses to interpret a member in the manifest JSON that is not specified in this document, it can do so, but with care.

We encourage implementors adding proprietary extensions to consider whether they could become a standard (i.e. if it would make sense for a second user agent on a different platform to make use of that member, even if no other user agent has expressed interest right now). If so, we ask authors to design the API in a vendor-neutral way, and propose it as a standard (see [[[#incubations]]]). If the new member is truly proprietary (i.e. will only ever make sense in the context of a proprietary ecosystem), use this process, and prefix it with the short name of that proprietary ecosystem to avoid name collisions.

Do not use vendor prefixes that you intend to later remove once it becomes a standard (those tend to stick around forever). Only use prefixes that will make sense now and into the future.

We encourage implementors to add proprietary extensions to our Extensions Registry. This allows the community to track what extensions vendors and/or the web community have defined and documented. Periodically, we will consider those extensions for standardization.

The following is an example of three hypothetical proprietary extensions.

            {
              ...
              "kpl_fancy_feature": "some/url/img",
              "gmpc_awesome_thing": { ... },
              "blitzly_site_verification": "KEY_9864D0966935"
              ...
            }
          

In this example, we have deliberately chosen (made-up) names of things that could be external sites or services, not names of browsers or browser vendors. These are not vendor prefixes belonging to the browser that invented them; they are prefixes of proprietary services.

Incubations

Extensions to this specification are being incubated in parallel by the Web Community, some of which are shipping in multiple browsers. If two or more browser engines end up supporting an incubated feature, then those features will become part of this specification in the future - allowing them to become a standard the Web Platform:

`BeforeInstallPrompt` and `window.onappinstalled` event
The `BeforeInstallPrompt` event and `window.onappinstalled` event were originally part of this specification. However, they were removed from the specification because they did not have support from two or more implementers. You can now find them in the `BeforeInstallPrompt` event and `window.onappinstalled` repository at the WICG.
`share_target` member
The `share_target` member registers a web application as "target" for share actions (e.g., for sharing a text, a URL, or a file). The `share_target` member is part of the Web Share Target specification, being incubated at the WICG.

Application Information

Several members of the Web Application Manifest provide additional metadata related to how the web application may be presented in the context of a digital storefront, installation dialog, or other surfaces where the web application may be marketed or distributed. In an effort to support these use cases better, the following members have been moved into [[[manifest-app-info]]]:

Relationship to HTML's `link` and `meta` elements

An extensive discussion of why we chose to use JSON instead of HTML `meta`/`link` tags for this specification is available on GitHub and on the www-tag list. Below is a short summary of the key points raised in those discussions.

The document format defined in this specification provides a unified means of encapsulating metadata about a Web application in a way that we hope will avoid existing pitfalls with both proprietary and [[HTML]]'s `meta`/`link` tags. Those pitfalls include:

Although it would be unrealistic to think that this specification won't bring its own set of problems, externalizing this data in the form of a manifest solves the problems described above. These problems are solved by:

In addition, standardizing the functionality currently provided by the various `meta` tag-based solutions within the manifest solves the problem of having tproprietary and standard [[HTML]] tags that all achieve the same thing. Of course, this hinges on the standard actually getting implemented by browsers and those browsers getting widely deployed to users: if this happens, the Web community might be able to retire many of the proprietary `meta` tags plaguing the Web at the time of writing. More information about the proprietary tags can be found in the Use Cases and Requirements for Installable Web Apps .

Lastly, this specification does not make the standardized solutions found in [[HTML]] redundant. When members like the `name` or `icons` is missing from the manifest, user agents can search in a manifest's owner [[HTML]] document for things like icons and the application name (or a user agent might even fallback to proprietary tags/metadata, if they are present in a document).

JSON Schema

Developers interested in validating manifest documents can find an unofficial JSON schema for the manifest format at schemastore.org. It is licensed under Apache 2.0. It is kindly maintained by Mads Kristensen. If you find any issues with the JSON schema, please file a bug at the SchemaStore repository on GitHub.

Internationalization

It is expected that authors will localize the content of a manifest by using one of the following options:

Localized values in the manifest:
Authors can provide [=localized values=] for the [=localizable members=] of the [=manifest=]. The user agent passes all localized values to the host operating system. When the user changes the [=locale=] at the OS level, the OS can present the updated localized values of the [=installed web application=].
Dynamically setting the language:
This can include, for instance, asking the end-user what their preferred language is and dynamically adding or replacing the manifest link relationship to the document based on that language preference (e.g., using a URL like "manifest.php?lang=fr").
Using content-negotiation, or geotargeting, etc. on the server:
The server that hosts the web application could attempt to predetermine the end-user's language by using geotargeting or by using content negotiation (e.g., using an HTTP "`Accept-Language`" header [[RFC9110]], or even a custom HTTP header).

Given the options above, developers need to be mindful of the end-user's privacy with respect to their preferred language: When the end-user has explicitly indicated their language preference to a web application (i.e., when not just using the user-agent default language settings), sending the end-user's preferred language in the clear over the wire is generally not OK. Doing so would reveal personal information about an end-user. As such, developers are encouraged to use [[TLS]] to reduce the chances of pervasive monitoring of their Web applications [[RFC7258]].

Use Cases and Requirements

This document attempts to address the Use Cases and Requirements for Installable Web Apps.

Change log

The following are some significant changes that were made since First Public Working Draft:

Acknowledgements

This document reuses text from the [[HTML]] specification, as permitted by the license of that specification.

Dave Raggett and Dominique Hazael-Massieux contributed to this specification via the HTML5Apps project.

Claudio Gomboli for icon example images.

Indiana University Bloomington security researchers have contributed to this specification by reporting potential risks related to out-of-scope navigation.