webdevpuneet.com

App Badge API Demo — Free navigator.setAppBadge with On-Page Mock

App Badge API Demo · Buttons · Plain HTML, CSS & JS · Live preview

CategoryButtons

Copy & paste

Source Code

<section class="bad-wrap">
  <span class="bad-tag">navigator.setAppBadge · pwa icon badge</span>
  <h1>Unread count badge</h1>
  <p id="badStatus">The badge only shows on a real device icon once this page is installed as a PWA — the mock below shows what it would look like right now.</p>

  <div class="bad-mock-row">
    <div class="bad-icon-mock">
      <div class="bad-icon-glyph">◆</div>
      <span class="bad-icon-count" id="badIconCount" hidden>0</span>
    </div>
    <div class="bad-mock-caption">Mock home-screen / taskbar icon</div>
  </div>

  <div class="bad-card">
    <div class="bad-count-row">
      <button class="bad-step" id="badMinus">−</button>
      <span class="bad-count" id="badCount">0</span>
      <button class="bad-step" id="badPlus">+</button>
    </div>
    <div class="bad-actions">
      <button class="bad-btn primary" id="badSetBtn">Set badge</button>
      <button class="bad-btn" id="badClearBtn">Clear badge</button>
    </div>
  </div>

  <p class="bad-note">navigator.setAppBadge() is Chromium-only and, per spec, only visibly affects the OS icon when the page is running as an installed PWA — inside a normal tab or a sandboxed preview iframe the call may succeed silently with zero visible effect, which is why the on-page mock above exists.</p>
</section>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Real setAppBadge call
Genuinely calls the Badging API, not a simulation of it.
Honest success messaging
Explains a successful call may still be invisible.
Always-visible mock icon
Makes the effect observable regardless of install state.
Independent count stepper
Adjust a number before committing it as a badge.
Capability check first
Feature-detects setAppBadge before calling it.
Clear/set both wired
clearAppBadge mirrors setAppBadge's real and mock paths.
99+ overflow handling
Large counts collapse to a readable "99+" badge.
Named failure states
Surfaces the actual error name if the call throws.

About this UI Snippet

App Badge API Demo — Real setAppBadge Plus a Mock You Can Actually See

Screenshot of the App Badge API Demo snippet rendered live

The Badging API's navigator.setAppBadge(count) puts a small number on a Progressive Web App's home-screen or taskbar icon — the same kind of unread-count indicator native mail and messaging apps have shown for years. This snippet calls the real API, but it's built around an unusual honesty problem: even when the call succeeds perfectly, it's often completely invisible to whoever is looking at the demo, because badging only affects a page's OS-level icon, and this demo is neither installed nor, in most cases, being viewed as a PWA at all.

The real call, made honestly

setBadge() calls navigator.setAppBadge(count) for a positive count or navigator.clearAppBadge() at zero, behind a 'setAppBadge' in navigator capability check and a try/catch. Critically, a successful resolution here does not mean you'll see anything — the spec allows the call to succeed with zero visible effect if the page isn't running as an installed, standalone PWA. That's not a bug to work around; it's the API behaving exactly as designed, and the status text says so explicitly rather than declaring false success.

A mock that makes the invisible visible

Because the real effect is so often unobservable in a demo context, an on-page mock icon with its own badge overlay mirrors the count at all times, updated by syncMock() independent of whether the real API call succeeds, fails, or doesn't exist. This is the actual point of the snippet: it lets you understand and preview what setAppBadge(3) would put on a real taskbar icon, without needing to install anything.

Support is narrow, so the mock isn't optional

The Badging API is implemented only in Chromium-based browsers, and even there it requires the page to be an installed, standalone-display-mode PWA to have any visible effect — a plain browser tab, and especially a sandboxed preview iframe like the one likely rendering this demo, will never show a badge no matter how correctly the code calls the API. Building the mock as a first-class, always-functional part of the UI (rather than an apologetic fallback) is what keeps this demo meaningful. It follows the same principle as this library's canvas audio frequency bars snippet: assume the real capability might be invisible or unavailable, and make sure there's still something genuinely useful on screen.

Counting up and down

The +/− stepper is entirely independent of the API call — you can freely adjust the count and only commit it to setAppBadge/the mock when you click "Set badge," which keeps the demo's two concerns (choosing a number, and badging with it) cleanly separated. Pair this with a status pill for a non-PWA unread indicator, or a notification permission prompt for the companion notifications feature.

Customizing it

Wire the count to a real unread-messages or pending-tasks total, call setAppBadge without an argument for a flag-only badge (no number, just a dot), or debounce calls if the count changes frequently.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA mock app icon and a count stepper render.
  2. 2
    Adjust the count with +/−The stepper number updates independent of the badge.
  3. 3
    Click "Set badge"Calls the real setAppBadge() and updates the mock icon.
  4. 4
    Check the status lineIt explains whether the real badge would actually be visible.
  5. 5
    Click "Clear badge"Resets the count and clears both the real and mock badge.
  6. 6
    Install as a PWA to see it for realOnly then does the OS icon actually show the badge.

Real-world uses

Common Use Cases

Messaging and email PWAs
Show an unread count on the installed app icon with setAppBadge(), using a mock icon so the effect is visible even when the app is not installed.
Task and to-do apps
Badge the number of pending items on the home screen, with an independent count stepper before committing the number.
Notification-heavy dashboards
Pair with a notification permission prompt so people grant access before badges are expected to appear.
Support ticketing apps
Badge open tickets next to a status pill for each agent, clearing the badge with clearAppBadge() when the queue is empty.
PWA install education
Teach what installing a PWA changes, with honest messaging explaining that a successful call can still be invisible, and the mock pattern also useful without the API.
Related: Clipboard Paste Button
See the Clipboard Paste Button for a related buttons pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

navigator.setAppBadge() only has a visible effect when the page is running as an installed, standalone Progressive Web App — a badge set from a regular browser tab, or from inside a sandboxed preview iframe like the one likely rendering this demo, can succeed at the JavaScript level with zero visible result, because there's no home-screen or taskbar icon for the operating system to badge. That's exactly why the on-page mock icon exists: it shows you what the real badge would look like.

No — the Badging API is implemented only in Chromium-based browsers (Chrome, Edge, Opera) and has no support in Firefox or Safari as of this writing. This snippet checks 'setAppBadge' in navigator before calling it and clearly states in the status line when the API is unavailable, while the on-page mock keeps working identically either way.

You'd need to install this page as a PWA (which requires a real web app manifest and, typically, a service worker — beyond what a single-file demo provides) and open it in its own installed window rather than a browser tab. Only then does the operating system have an actual icon to place the badge number on, whether that's a taskbar icon on desktop or a home-screen icon on Android.

setAppBadge(count) sets a specific number badge (or a flag-style dot if called with no argument at all) on the installed app's icon. clearAppBadge() removes it entirely, equivalent to calling setAppBadge(0) in most implementations. This snippet calls clearAppBadge() automatically whenever the stepper count reaches zero and "Set badge" is clicked, keeping the two functions' behavior consistent with the spec.

Bind the count to component state driven by your +/− buttons, and call the same setBadge/clearBadge logic — the capability check, try/catch, and mock-icon sync — from your framework's click handlers. Since the real effect is entirely OS-level and outside the DOM, there's nothing framework-specific to worry about beyond keeping the mock icon's rendered count in sync with your state.