← Chrome 152 reference

v152 · shipped · isolated web apps

Sub apps

Limited availability

  • Chrome · enabled by default 152 (developer trial in 150)
  • Edge · not separately reported
  • Firefox · no signal
  • Safari · no signal

Not on the Baseline register (no web-features entry at webstatus.dev). Chrome-only, and currently usable only on platforms that support Isolated Web Apps — presently ChromeOS (other desktops may work but are not officially supported). The Chrome 152 milestone listing (Enabled by default) and the current feature detail (chromestatus API, updated 2026-07-24) agree on desktop 152 as the default-on target, while the feature's status text remains “Proposed”.

Sub apps let a single Isolated Web App (IWA) installation present multiple distinct applications to the OS — each with its own name, icons, shelf window, and integrations such as protocol and file handlers — while sharing the parent IWA's origin, storage, permissions, Signed Web Bundle resources, and update lifecycle.

Ships in Chrome 152 — not reachable from ordinary websites

The Sub Apps API ships enabled by default in Chrome 152 (chromestatus milestone listing; it was in developer trial in Chrome 150). Even enabled by default, it is only exposed inside installed Isolated Web Apps. The documented setup (per the official sample) is:

Implementation/debug note: the runtime-enabled feature is SubApps (status: stable at trunk in runtime_enabled_features.json5), so --enable-blink-features=SubApps also gates the binding — but the flags-and-chrome://web-app-internals flow above is the documented complete setup.

Source: official subapps-demo README — how to try it; chromestatus.com/feature/6260680824061952

at a glance

At a glance
Milestone listingChrome 152 — Enabled by default (chromestatus listing, verified 2026-07-28; the feature was previously listed under Chrome 150 as In developer trial)
Default-on milestoneChrome 152, per two agreeing sources: the milestone listing (Enabled by default) and the feature detail (chromestatus API, updated 2026-07-24 12:57 UTC — shipping target desktop 152; active stage “Prepare to ship”, desktop_first 152). The feature's status text remains “Proposed”
InterfaceSubApps, reached via window.subApps
PlatformImplemented on desktop; end-user availability currently limited to platforms supporting Isolated Web Apps — presently ChromeOS (other desktops unofficial)
ContextInstalled Isolated Web Apps only (secure, isolated context)
Permission policysub-apps=(self) required on the parent IWA; policies declared for a sub app have no effect
Dev-trial flags#enable-isolated-web-apps, #enable-isolated-web-app-dev-mode, #enable-sub-apps, then install via chrome://web-app-internals
Runtime flag (impl. evidence)SubApps in runtime_enabled_features.json5 (status stable at trunk)
Standards bodyWICG — Sub Apps (unofficial draft)
ChromeStatus6260680824061952 — Sub apps
Source: chromestatus.com/feature/6260680824061952; Chromium runtime_enabled_features.json5

Syntax

The API hangs off Window as a single read-only attribute returning a SubApps instance with three asynchronous batch methods. IDL from the WICG draft:

[Exposed=Window, SecureContext, IsolatedContext]
partial interface Window {
  [SameObject] readonly attribute SubApps subApps;
};

// Represents the https://w3c.github.io/manifest/#id-member
typedef USVString ManifestId;

dictionary SubAppsAddResponse {
  record<USVString, ManifestId> installedApps;
  record<USVString, DOMException> failedApps;
};

dictionary SubAppsRemoveResponse {
  sequence<ManifestId> removedApps;
  record<USVString, DOMException> failedApps;
};

dictionary SubAppsListResult {
  required DOMString appName;
};

[Exposed=Window, SecureContext, IsolatedContext]
interface SubApps {
  Promise<SubAppsAddResponse> add(sequence<USVString> install_paths);
  Promise<SubAppsRemoveResponse> remove(sequence<ManifestId> manifest_ids);
  Promise<record<USVString, SubAppsListResult>> list();
};
Source: WICG Sub Apps draft — IDL index

add(install_paths)

Installs a batch of sub apps. Each install path is a relative URL (it must start with /) to the sub app's entry index.html, which must reference a web manifest. A single system prompt lists every requested sub app in one dialog (scrollable when batched).

add() — parameters, return value, exceptions
PartDetail
Parametersinstall_pathssequence<USVString> of same-origin absolute paths to sub-app entry documents
ReturnsPromise<SubAppsAddResponse>installedApps maps each install path to its new ManifestId; failedApps maps each failed path to a DOMException
Batch rejectionTypeError (invalid relative paths), SecurityError (policy missing), NotSupportedError (called inside a sub app), NotAllowedError (user declined the prompt), QuotaExceededError (platform limits exceeded), OperationError
Per-app failureConstraintError (scope prefix conflict, or path points at the parent's own manifest), DataError (manifest invalid/unparseable), InvalidStateError (already installed), OperationError

remove(manifest_ids)

Uninstalls a batch of previously installed sub apps, identified by the ManifestId values returned from add() or list().

remove() — parameters, return value, exceptions
PartDetail
Parametersmanifest_idssequence<ManifestId>
ReturnsPromise<SubAppsRemoveResponse>removedApps lists the removed ManifestId values; failedApps maps each failed id to a DOMException
Batch rejectionTypeError, SecurityError, NotSupportedError, OperationError
Per-app failureNotFoundError (no such sub app under this parent IWA, or already removed), OperationError

list()

Returns the sub apps currently installed under this parent IWA as a record keyed by ManifestId, so dictionary lookups (e.g. membership checks) work directly on the result. Each value is a SubAppsListResult whose appName is the name from the sub app's web manifest.

list() — return value, exceptions
PartDetail
ReturnsPromise<record<USVString, SubAppsListResult>>
RejectionSecurityError (policy missing), NotSupportedError (called inside a sub app), OperationError
Source: WICG Sub Apps explainer — API design

Sub app identity, resources, and limits

A sub app is not a separate security principal. It shares the parent IWA's origin, SignedWebBundleId, cookies, IndexedDB, localStorage, Cache Storage, and all granted permissions — the same-origin policy treats parent and sub apps as one entity. What distinguishes a sub app is its presentation and OS integration:

Identity fields (per the explainer's identity table)
IdentifierRule
Origin / bundle idIdentical to the parent IWA
start_urlRequired in the sub app's manifest; must be unique across sub apps and the parent
ScopeSub-app scopes must not be prefixes of one another, nor of the parent scope — otherwise install/update fails with ConstraintError
ManifestIdThe manifest id member; falls back to start_url without the fragment. Used by remove() and list()

Sub-app manifests can carry their own OS integrations — protocol_handlers, file_handlers, and launch_handler act per sub app. Resources can be provisioned statically (bundled in the parent IWA, updated when the parent updates) or dynamically (a service worker serves the sub app's HTML and manifest, so sub apps update without a parent bundle update).

Two platform quotas guard against launcher flooding: at most 50 installed sub apps per parent IWA, and at most 20 sub apps per installation prompt. Exceeding either rejects the whole add() call with QuotaExceededError.

Source: WICG Sub Apps explainer — identity, provisioning, quota

Enterprise policies

Three Chrome enterprise policies govern whether sub-app installs require a user prompt:

Sub apps enterprise policies
PolicyEffect
DefaultSubAppsWithoutPromptsSettingGlobally sets whether IWA sub-app installs require a user permission prompt
SubAppsWithoutPromptsAllowedForOriginsLists IWA URLs that may add or update sub apps without a prompt
SubAppsWithoutPromptsBlockedForOriginsLists IWA URLs that may only add sub apps with a prompt
Source: chromestatus.com/feature/6260680824061952

Examples

Live example from the Chrome Platform Showcase: probes each prerequisite (secure context, IWA binding, permission policy) and reports exactly which gate is closed. Source: chrome-platform-showcase
// Inside an installed IWA with Permissions-Policy: sub-apps=(self)
const { installedApps, failedApps } = await window.subApps.add(["/calc/", "/docs/"]);

for (const [installPath, manifestId] of Object.entries(installedApps)) {
  console.log(`installed: ${installPath} -> ${manifestId}`);
}
for (const [installPath, exception] of Object.entries(failedApps)) {
  console.error(`failed: ${installPath} — ${exception.name}`);
}

// Later: enumerate and remove
const all = await window.subApps.list();          // record<ManifestId, { appName }>
const calcId = Object.keys(all).find((id) => all[id].appName === "Calculator");
if (calcId) {
  const { removedApps } = await window.subApps.remove([calcId]);
  console.log("removed:", removedApps);
}
Source: WICG Sub Apps explainer — examples

Browser compatibility

There is no browser-compat-data (BCD) entry for this API yet, so the table below is an interim view built from ChromeStatus ship data and public vendor signals — not from BCD.

Interim compatibility — from ChromeStatus, not BCD
BrowserStatusNotes
Chrome150 (developer trial)Isolated Web Apps only — presently ChromeOS for end users. Default-on target desktop 152, per the agreeing v152 milestone listing (Enabled by default) and feature detail (API, 2026-07-24); status text “Proposed”
EdgeNot separately reportedNo Edge position is recorded on ChromeStatus; no public support evidence (Chromium engine equivalence is not a support commitment)
FirefoxNo signalRecorded on ChromeStatus
SafariNo signalRecorded on ChromeStatus
Source: chromestatus.com/feature/6260680824061952; mdn/browser-compat-data (no api/SubApps entry as of July 2026)

Specifications

Specifications
SpecificationStatus
Sub AppsWICG unofficial draft (incubation)
Web Application ManifestW3C Working Draft — sub apps reuse its id, start_url, scope, and OS-integration members
Source: spec links recorded on chromestatus.com/feature/6260680824061952

See also