# Firefox taskbar web apps on Windows

> How Firefox 143 pins a site to the Windows taskbar, which platforms the taskbartabs component covers, and what the pinned window inherits from the profile.

Firefox 143 on Windows can pin a site to the taskbar and run it in a simplified window,
a feature Mozilla ships under the name web apps and calls taskbar tabs in its own source.
The pin is made from the address bar rather than from the site, and the window it opens
keeps the profile and the container it was created with.

## How it works

The feature is one browser component, documented in the Firefox source tree as
[Web Apps in Firefox](https://firefox-source-docs.mozilla.org/browser/components/taskbartabs/docs/index.html).
That page states the feature is enabled by the preference `browser.taskbarTabs.enabled`,
and describes its entry point as a button on the URL bar rather than a manifest member or
a page API. The architecture document assigns that button to a module it calls the page
action, which shows and hides itself depending on whether the page has an HTTP or HTTPS
scheme.

### Creating and removing the pin

The component documentation gives both halves of the flow. Clicking the "Add tab to
taskbar" button on the URL bar creates a new window and prompts the user to pin it to the
taskbar. Clicking "Remove tab from taskbar" turns that window back into a normal tab and,
if that was the last window, unpins it from the taskbar. Firefox keeps information about
each web app in `taskbartabs/taskbartabs.json` inside the user's profile, a file the same
page marks as intended for use internally by Firefox.

The icon is chosen the first time a web app is created, by iterating through sources
(manifests, favicons) until a valid icon is found, and an existing web app saves its icon
on the filesystem and loads it when needed. So the manifest and the favicon are where a site
can influence what the taskbar shows.

:::note
Mozilla avoids the name PWA for this feature, for two reasons the documentation gives: the
term is vague, referring both to the APIs that support web apps and to the ability to
install them; and Firefox web apps, by design, still appear like a browser instead of
appearing as a completely separate application.
:::

### What the pinned window carries over

A pinned window is still the same browser. The "External Interactions" section of
[Web Apps in Firefox](https://firefox-source-docs.mozilla.org/browser/components/taskbartabs/docs/index.html)
records the consequences that matter when you test an app there:

- Web apps are tied to the profile they are created with, so web app pages have the same
  access, controls and add-ons as a normal tab. The
  [Firefox 143.0 release notes](https://www.firefox.com/en-US/firefox/143.0/releasenotes/)
  (September 16, 2025) describe this as pinning sites that run "without losing access to
  your installed add-ons".
- Web apps are tied to the container, called a contextual identity in the source, they are
  created with, and launching via the taskbar reopens them in that container. The
  documentation presents this as a way for users to isolate sites without requiring a new
  profile per web app.
- Web app windows are not tied to the lifetime of normal browser session restore. They are
  not restored for users who have enabled "Open previous windows and tabs", and they do not
  prevent the restoration of windows that session restore does handle.

### Launching from the taskbar shortcut

Clicking the taskbar shortcut starts Firefox with a command line, which the
[architecture document](https://firefox-source-docs.mozilla.org/browser/components/taskbartabs/docs/architecture.html)
gives as:

```text
firefox -taskbar-tab <id> -new-window <start url> -profile <profile path> -container <usercontextid>
```

The same document records what happens when the referenced web app is absent: a new one is
created, though not with that ID. When the web app exists its start URL is used, and
otherwise the start URL from the shortcut opens instead, as a fallback.

## Platform availability

The component documentation lists web apps as available on Windows, both MSIX and
non-MSIX, enabled by default, and on Linux, unsandboxed and under Flatpak, disabled by
default. It states that macOS support is not available and gives the reason: macOS assumes
that two different visible applications will be in two different processes, while Firefox
web apps are in the same profile and process as the rest of the browser, so the Dock is
not able to distinguish them. The architecture document adds that Linux under Snap is not
supported.

The Firefox 143.0 release notes scope the shipped feature more narrowly than the component
does. They describe it as a Windows feature and exclude Firefox installs from the Microsoft
Store. Read the release notes for what Firefox 143 does, and the component documentation
for where the component has reached since.

## Examples

A site cannot create the pin, so the code worth writing is the code that makes the
simplified window a reasonable place to land.

### Reacting when a window stops being a web app

The architecture document puts "ejecting" web apps back into the tabs they came from in
`TaskbarTabsWindowManager`, so one window can change from an app surface back to a tab
while the page is loaded. A layout that keys on the
[`display-mode` media feature](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode)
should therefore listen rather than read once.

The mode a Firefox taskbar web app reports is `minimal-ui`, not `standalone`:
[`TaskbarTabsWindowManager.sys.mjs`](https://searchfox.org/firefox-main/source/browser/components/taskbartabs/TaskbarTabsWindowManager.sys.mjs)
sets `browser.browsingContext.displayMode = "minimal-ui";` on each tab of the window it
opens, and sets it to `"browser"` when the app is ejected. A check written against
`standalone` alone therefore reports a browser surface inside the window it meant to
detect, so test the installed modes as a set.

```js
// Firefox taskbar web apps report minimal-ui. Other installed display modes depend
// on the mode requested by the manifest and browser support.
const APP_MODES = ['minimal-ui', 'standalone', 'window-controls-overlay'];

function trackAppSurface(onChange) {
  if (!('matchMedia' in window)) {
    // No matchMedia: render the browser layout and stop here.
    onChange('browser');
    return () => {};
  }
  const queries = APP_MODES.map((mode) => window.matchMedia(`(display-mode: ${mode})`));
  const apply = () => onChange(queries.some((query) => query.matches) ? 'app' : 'browser');
  apply();
  queries.forEach((query) => query.addEventListener('change', apply));
  return () => queries.forEach((query) => query.removeEventListener('change', apply));
}

const stop = trackAppSurface((surface) => {
  document.documentElement.dataset.surface = surface;
});
```

Read the individual queries instead of the `some()` result when the distinction matters to
the layout: `minimal-ui` is the Firefox taskbar window, while the effective mode elsewhere
depends on the mode requested by the manifest and browser support. Keep the returned teardown function, because a single-page app
that re-runs this on every route change otherwise stacks one listener per navigation.

### Serving the icon and name the pin will use

Firefox uses the manifest's name, start URL, scope, and icons. When no manifest icon is
available, it also tries a favicon.

```json
{
  "name": "Example Reader",
  "short_name": "Reader",
  "start_url": "/app/",
  "scope": "/app/",
  "display": "standalone",
  "icons": [
    { "src": "/icons/app-192.png", "sizes": "192x192", "type": "image/png" },
    { "src": "/icons/app-256.png", "sizes": "256x256", "type": "image/png" },
    { "src": "/icons/app-512.png", "sizes": "512x512", "type": "image/png" }
  ]
}
```

`name`, not `short_name`, is the string the registry entry carries:
[`TaskbarTabsRegistry.sys.mjs`](https://searchfox.org/firefox-main/source/browser/components/taskbartabs/TaskbarTabsRegistry.sys.mjs)
creates it with `name: manifest.name ?? generateName(aUrl)`, deriving a name from the URL
when the manifest has none. Keep `short_name` for the platforms that use it, and write a
`name` short enough to read under an icon.

The icon pass asks for 256 px: `findBestManifestIcon` in
[`TaskbarTabs.sys.mjs`](https://searchfox.org/firefox-main/source/browser/components/taskbartabs/TaskbarTabs.sys.mjs)
discards icons whose `purpose` does not include `any`, sorts the rest by width, returns the
first candidate whose size is at least 256, and falls back to the largest candidate when
that search finds none. The same function substitutes `Infinity` for an empty or `any`
`sizes` value, so such an entry sorts above every pixel size. In the manifest above the
256 px icon is the one that search reaches, so serve a real asset at that size rather than
relying on a small favicon.

## Observed behaviour

The preference that gates the feature is set per platform in Firefox's own default
preference file, which is where the per-platform defaults above come from.

:::observed
Firefox default preferences (firefox-main, `browser/app/profile/firefox.js`) contain
`pref("browser.taskbarTabs.enabled", true);` inside `#if defined(XP_WIN)` and
`pref("browser.taskbarTabs.enabled", false);` in the `#else` branch
([searchfox](https://searchfox.org/firefox-main/source/browser/app/profile/firefox.js)).
:::

The address-bar entry point is drawn by the page action module, so a user whose build reads
the `#else` default has no button to click until the preference is changed. That is the
mechanism behind the Linux "disabled by default" line in the component documentation.

## See also

- [PWAs on Firefox](/reference/platforms/firefox/)
- [PWAs on Windows](/reference/platforms/windows/)
- [PWAs on desktop](/reference/platforms/desktop/)
- [display manifest member](/reference/manifest/display/)
- [Web Apps in Firefox](https://firefox-source-docs.mozilla.org/browser/components/taskbartabs/docs/index.html) (firefox-source-docs.mozilla.org)
- [Firefox 143.0 release notes](https://www.firefox.com/en-US/firefox/143.0/releasenotes/) (firefox.com)
- [@media display-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode) (developer.mozilla.org)