This specification defines an API that allows [=installed web applications=] to set an application badge, which is usually shown alongside the application's icon on the device's home screen or application dock.

This is a work in progress.

Usage examples

        async function updateMailBadge() {
          // Check if the API is supported.
          if (!navigator.setAppBadge) return;

          const unreadCount = await getUnreadMailCount();

          // Try to set the app badge.
          try {
            await navigator.setAppBadge(unreadCount);
          } catch (e) {
            // The badge is not supported, or the user has prevented the app
            // from setting a badge.
          }
        }
      

The badge might show up on the application's icon in the operating system. If multiple API calls within the same application [=badge/set=] or [=badge/clear=] a badge, the most recent one takes effect, and may continue being seen even after an application is closed.

        async function showPlayerTurn(playerTurnId) {
          if (playerTurnId === localPlayerId)
            await navigator.setAppBadge();
          else
            await navigator.clearAppBadge();
        }
      

On some operating systems [=badge/setting=] a badge can require permission from the user. In this case, a developer need to query the "[=notifications=]" permissions status before [=badge/setting=] a badge. If the permission is not granted, the developer will need to prompt for permission via the {{Notification}}.{{Notification/requestPermission()}}.

        async function checkPermission() {
          permission = await navigator.permissions.query({
            name: "notifications",
          });
          const button = document.getElementById("permission-button");
          if (permission.state === "prompt") {
            // Prompt the user to grant permission.
            button.hidden = false;
            button.addEventListener("click", async () => {
              await Notification.requestPermission();
              checkPermission();
            }, { once: true });
            return;
          }
          button.hidden = true;
        }
      

Model

A badge is intended as a mechanism for [=installed web applications=] to notify the user that there is some new activity that might require their attention, or as a way of indicating a small amount of information, such as an unread count.

A [=badge=] can have one of the following values:

The special value "nothing":
Indicates that there is no badge currently [=badge/set=].
The special value "flag":
Indicates that the badge is [=badge/set=], but contains no specific value.
A number value:
Indicates that the badge is [=badge/set=] to a numerical value greater than `0`.

An [=installed web application=] has an associated [=badge=], which is initialized to [="nothing"=].

The user agent MAY (re)[=set=] an application's badge to [="nothing"=] at its discretion (for example, following system conventions).

Displaying a badge

When the application's badge is set, the [=user agent=] or operating system SHOULD display the application's [=badge=] alongside the primary iconic representation of the application in the user's operating system (for example, as a small overlay on top of the application's icon on the home screen on a device).

A user agent MAY require [=express permission=] from the user to [=badge/set=] the badge. When a user agent requires such [=permission=], it SHOULD tie the permission grant to the "[=notifications=]" permission.

When the [=badge=] is [=badge/set=] to [="flag"=], the [=user agent=] or operating system SHOULD display an indicator with a non-specific symbol (for example, a colored circle).

When a [=badge=]'s value is [=badge/set=] to [="nothing"=], the [=user agent=] or operating system SHOULD clear the [=badge=] by no longer displaying it.

When the [=badge=] is [=badge/set=] to a [=number=], the [=user agent=] or operating system:

Extensions to the `Navigator` and `WorkerNavigator` interfaces

        [SecureContext]
        interface mixin NavigatorBadge {
          Promise<undefined> setAppBadge(
            optional [EnforceRange] unsigned long long contents
          );
          Promise<undefined> clearAppBadge();
        };

        Navigator includes NavigatorBadge;
        WorkerNavigator includes NavigatorBadge;
      

User agents that never display application badges SHOULD NOT [=interface/include=] {{NavigatorBadge}}.

setAppBadge() method

When the {{NavigatorBadge/setAppBadge()}} method is called, the user agent MUST [=set the application badge=] of [=this=] to value of the |contents:unsigned long long| argument.

clearAppBadge() method

When the {{NavigatorBadge/clearAppBadge()}} method is called, the user agent MUST [=set the application badge=] of [=this=] to 0.

Setting the application badge

To set the application badge of platform object |context:platform object| to an optional {{unsigned long long}} |contents:unsigned long long| value:

  1. Let |global| be |context|'s [=relevant global object=].
  2. If |global| is a {{Window}} object, then:
    1. Let |document| be |global|'s [=associated `Document`=].
    2. If |document| is not [=Document/fully active=], return [=a promise rejected with=] a {{"InvalidStateError"}} {{DOMException}}.
  3. Let |promise| be [=a new promise=].
  4. [=In parallel=]:
    1. If [=this=]'s [=relevant settings object=]'s [=origin=] is not [=same origin=] with [=this=]'s [=relevant settings object=]'s [=environment/top-level origin=], [=queue a global task=] on the [=DOM manipulation task source=] given |global| to [=reject=] |promise| with a {{"SecurityError"}} and terminate this algorithm.
    2. If the [=user agent=] requires [=express permission=] to [=badge/set=] the application badge, then:
      1. Let |permissionState| be the result of [=getting the current permission state=] with "[=notifications=]".
      2. If |permissionState| is not {{PermissionState/"granted"}}, [=queue a global task=] on the [=user interaction task source=] given |global| to [=reject=] |promise| with a {{NotAllowedError}} and terminate this algorithm.
    3. Switching on |contents|, if it happens to be the case that:
      |contents| was not passed:
      [=badge/Set=] |badge| to [="flag"=].
      |contents| is 0:
      [=badge/Set=] |badge| to [="nothing"=].
      |contents|:
      [=badge/Set=] |badge| to |contents|.
    4. [=Queue a global task=] on the [=DOM manipulation task source=] given |global| to [=resolve=] |promise| with `undefined`.
  5. Return |promise|.

Privacy considerations

The API is write-only by design. There is no way for a site to read back the value of a badge that was previously set, to ensure that the application badge cannot be used as a storage or fingerprinting mechanism.

Security considerations

The [=user agent=] or operating system MAY [=badge/clear=] a [=badge=] at its discretion, and to follow any system conventions (for example, when the system is reset).

Accessibility considerations