Skip to content

Add manifest scope improvements doc#137

Open
LuHuangMSFT wants to merge 1 commit intogh-pagesfrom
manifest-scope-improvements
Open

Add manifest scope improvements doc#137
LuHuangMSFT wants to merge 1 commit intogh-pagesfrom
manifest-scope-improvements

Conversation

@LuHuangMSFT
Copy link
Copy Markdown
Collaborator

Describe problems app developers face with the current manifest scope model and propose a two-layer scope architecture to address them.

Describe problems app developers face with the current manifest scope model and propose a two-layer scope architecture to address them.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@LuHuangMSFT LuHuangMSFT self-assigned this Apr 9, 2026
@LuHuangMSFT LuHuangMSFT marked this pull request as ready for review April 9, 2026 23:06
@LuHuangMSFT LuHuangMSFT requested a review from dmurph April 9, 2026 23:06
@LuHuangMSFT LuHuangMSFT closed this Apr 9, 2026
@LuHuangMSFT LuHuangMSFT reopened this Apr 10, 2026
| # | Problem | Proposed Solution Area |
|---|---------|----------------------|
| 1 | Cannot exclude paths from scope | New manifest members for scope include/exclude lists |
| 2 | Navigation capture scope ≡ app scope | Separate "capture scope" concept (Layer 2) |
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if 2,3,4 could be combined into one thing?

E.g.:

"launch_handlers": [
  // Patterns are evaluated in order, until one applies to the url.
  { "url_pattern": <..pattern..>,
     "client_mode": "focus-existing" },
  { "url_pattern": <...pattern..>,
    "client_code": "never_capture" },
  ...
// the pattern could be for exteneded urls! so we could say that an
// extended scope, for example, never captures.

  // to maintain backwards compatibility, if none apply, the "launch_handler" entry is used as the default
],

IDK if this is better - to NOT capture something into the app, you have to specify a handler for it.

Questions here would be for backwards compatibility in general too - all solutions need to make sure that old versions or chrome don't break - e.g. the manifest parser doesn't 'throw away' the manifest if it fails to parse something here (I don't think that's the case for most of this)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. I've not thought about specifying capturing scope from launch_handlers before. Will investigate.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think this current doc is solution-agnostic enough to be merged?

| 1 | Cannot exclude paths from scope | New manifest members for scope include/exclude lists |
| 2 | Navigation capture scope ≡ app scope | Separate "capture scope" concept (Layer 2) |
| 3 | Single launch behavior for all URLs | URL-pattern-keyed launch handlers (Layer 2) |
| 4 | `scope_extensions` lacks feature annotations | Per-origin opt-in/out in association file |
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe another way to say what I said above is - maybe we can flatten the concept of the per-origin opt-in and opt-out into the same concept of specializing launch handling per url, by introducing a 'never-capture' value? But maybe there are reasons to not do that?


### Layer 2 — In-App Behavior (fine-grained)

This layer answers: *"Now that we know this URL is part of the app, how should the browser handle it?"* This is where richer pattern matching (potentially `URLPattern`) becomes appropriate, because evaluation happens inside the browser after the OS has already routed the URL to the app.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm following correctly, we're also talking about this 'layer' being where we think about a clicked link within the app, which we don't know yet if "this URL is part of the app". Small wording tweak suggestion:

Suggested change
This layer answers: *"Now that we know this URL is part of the app, how should the browser handle it?"* This is where richer pattern matching (potentially `URLPattern`) becomes appropriate, because evaluation happens inside the browser after the OS has already routed the URL to the app.
This layer answers: *"Now that we are in the app, how should the browser handle this URL?"* This is where richer pattern matching (potentially `URLPattern`) becomes appropriate, because evaluation happens inside the browser after the OS has already routed the URL to the app.


**Why it matters.** Different areas of an app have different interaction models. Forcing a single launch behavior leads to UX compromises: either users lose context when an existing window is reused for unrelated content, or they accumulate unnecessary windows when every launch opens a new one.

**What developers need.** The ability to specify **multiple launch handlers**, each associated with a set of URL patterns, so launch behavior can be tailored to the content being opened.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is URL scoping enough? I'm wondering if the app might want to factor in even more dynamic information, like "what URL is my current app page on"? (e.g. YouTube PWA wants to open a video link in the current window if nothing is playing, but if something is playing wants to pause it and open a new window).

If so, this might be more wholistically solved by giving the app more permissions within the context of its launch handler. Namely, letting it easily launch a new window of itself with params similar to the LaunchParams it received.

This layer answers: *"Does this URL belong to the application?"* It determines install-time registration with the OS, deep-link routing, and display-mode application. Because it must map to OS-level URL filtering (Android intent filters, Windows protocol/URI handling, etc.), it should remain **simple** — path prefixes, origin lists, and at most basic include/exclude patterns.

Design constraints:
- Must be expressible using primitives that operating systems support for URL filtering. Prior work on the (now-obsolete) [`pwa-url-handler` explainer](https://github.com/WICG/pwa-url-handler/blob/main/explainer.md#os-specific-implementation-notes) documented these OS mechanisms: Android [intent filters](https://developers.google.com/web/fundamentals/integration/webapks?hl=ro#android_intent_filters) via WebAPK, Windows ["Apps for Websites"](https://docs.microsoft.com/en-us/windows/uwp/launch-resume/web-to-app-linking), and iOS/macOS [Universal Links](https://developer.apple.com/ios/universal-links/). All are origin- or prefix-based — none support regex or complex pattern matching — which bounds the expressiveness of this layer.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW - A browser could choose to support a more complex syntax at this layer, and attempt to best-effort translate it to the OS it is on, erring on the side of a broader capture, with a fall-back of trying to have it handled in the browser. I wouldn't recommend it for a v1, but worth considering as a potential future while designing the API shape.

So for example, on Windows or iOS/macOS the browser might try to break it into include/exclude paths with basic wildcards, whereas on Android it wouldn't have an 'exclude' option. In any case the browser would always check the URL at launch time, and if it didn't match the more complex syntax provided by the PWA it would launch it in the browser mode instead. (Or if it wanted to be super fancy, it could attempt to look up the default browser and forward it along to that. Should be possible on at least Windows, though likely not on Android/iOS).


**Why it matters.** Navigation capturing is an all-or-nothing proposition today: it applies to every URL inside scope. Developers cannot differentiate between "this URL is part of my app" and "this URL should pull the user into the app window when clicked externally." These are distinct intents, and conflating them forces developers into workarounds (e.g., moving content to a different origin).

**What developers need.** A mechanism to define a **capture scope** that is a subset of (or different from) the application scope — controlling which URLs trigger navigation capturing independently of which URLs render in the app window.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would lean into the 'different' rather than 'subset' direction. Though a very contrived case, I could imagine wanting to capture a URL activation, but still show it as 'outside the scope of the app' in the UI. Possibly for something like an old URL location that now attempts to guide you to the new URL, but less aggressively than an automatic redirect.

Suggested change
**What developers need.** A mechanism to define a **capture scope** that is a subset of (or different from) the application scope — controlling which URLs trigger navigation capturing independently of which URLs render in the app window.
**What developers need.** A mechanism to define a **capture scope** that is different from the application scope — controlling which URLs trigger navigation capturing independently of which URLs render in the app window.

@dmurph
Copy link
Copy Markdown
Collaborator

dmurph commented Apr 20, 2026

Chat at blinkon:

  • Add background sectino on scope extensions, and highlight of the intention of ux impact, app exists cross-origins, but only for user ux / user agent usability
  • Maybe roll in scope extensinos mentions on problems 1,2,3, sahing that the solution must also be compatible with extended scope sitiuations
  • add 'Other Considersations' section or 'Problems' or whatever section
    • "Scope Extensinos T&S Considations - Can the manifest own these extra decisinos or do the exteneded scopes need to control all scope-related features impacting viewing their urls on the PWA"

proposal from me would likely put all controls in manifest and only delegate to the scope extension the 'scope filtering' part? eg.g the scope member field and any new fields we add to modify scope for exlucsion etc, but then the 'UX behavior' bits with capturing and launch customization etc be in the manifest, and just have it able to specify url patterns or whatever that include extendeds origin. BUT - alternative should be docujented to have this be in the scope extensions dict area. We then should consult with T&S about what they think. Is this blocking? or likely ok?

adding fields to better specify scope in both manifest and scope extensions dict sounds appropriate. other origins can specify the scope more fine-grained. but the actuall UX controls over launch handlign and capturing IN that scope can not make any situation "worse" for that extended scope origin than today (from a t&s point of view) -it's just making the app more UX-robust. So it seems fine to have all of that in the manifest not need to ,say, put a 'launch_handler' member field in the scope_extensions dict.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants