PWA install conflict: hub scope: '/' blocks standalone installs on same origin #41
Labels
No labels
app:activities
app:chat
app:events
app:forum
app:libra
app:market
app:restaurant
app:tasks
app:wallet
app:webapp
bug
enhancement
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
aiolabs/webapp#41
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Symptom
Installing
app.${domain}as a PWA, then trying to install any standalone (e.g.libra.${domain}) makes Chrome say the app is already installed — no separate home-screen entry, no separate install prompt.Reproduced on Chrome with
app.ariege.io(hub) andlibra.ariege.io(standalone).Diagnosis
The standalone subdomains 301-redirect to the path-mount on the hub origin (intentional,
mkRedirectVhostinmodules/services/standalones.nix:140-143):So Chrome resolves the libra manifest at
app.ariege.io/libra/manifest.webmanifest. The standalone's manifest declaresscope: '/libra/', but the hub's manifest atapp.ariege.io/manifest.webmanifestdeclaresscope: '/', which claims the entire origin — including/libra/. Once the hub PWA is installed, Chrome treats every page underapp.ariege.io/as "inside an installed PWA" and suppresses the install affordance for nested manifests.The standalones'
idfields are unique (aio-community-hub,libra-accounting,market-app, etc.), so this is not anidcollision — it's purely the hub's overly-broad scope.The 301 redirect is intentional (best-of-both-worlds: subdomain and path-mount both reach the standalone) and should stay. The fix is on the hub side.
(Aside: the redirect target also has a double slash —
https://app.ariege.io/libra//manifest.webmanifest— worth fixing in passing.)Fix options
Option 1 — drop the hub PWA install (simpler)
Remove the manifest
<link>and theVitePWA({ manifest })block fromvite.config.tsso the hub is just a regular launcher page. Standalones at/libra/,/market/, etc. become independently installable.Trade-off: users lose the ability to install the launcher itself on the home screen. But the hub is just an 8-tile chooser that hands off to standalones — most users would install the standalones they actually use, not the chooser.
Option 2 — move the hub to
/hub/(preserves hub install)VITE_BASE_PATH=/hub/.vite.config.tsmanifest:start_url: '/hub/',scope: '/hub/'./→/hub/onapp.${domain}(root only — exact match, not prefix; standalones at/libra/,/market/, etc. continue to serve their dist).services.castle-standalones.parentDomainredirect targets unchanged (/libra/etc. still mount where they did).Hub stays installable on its own scope; standalones are siblings, not children — each installable independently. No PWA UX collision.
Trade-off: users see a 301 hop on first visit; bookmarks pointing at bare
app.${domain}still work via the redirect. Slightly more nginx config.Recommendation
Option 1 unless we have a specific reason to keep the hub installable. Option 2 if we want both the hub and the standalones home-screen-installable.
Acceptance
libra.${domain}as a PWA produces a separate home-screen entry from the hub PWA.mkRedirectVhostno longer emits the//double-slash inLocation:.References
vite.config.ts(hub manifest,scope: '/',id: 'aio-community-hub')vite.libra.config.ts:85-87(libra manifest,scope: process.env.VITE_BASE_PATH || '/',id: 'libra-accounting')modules/services/standalones.nix:140-143(intentional subdomain → path-mount redirect, target of fix is on the hub side, not here)/cannot avoid claiming child paths.Live verification on production via Playwright
Confirmed the diagnosis end-to-end against
https://libra.ariege.io/from a headed Chromium session.Redirect chain captured:
(Plus a follow-on redirect to
/libra/login— auth gate, irrelevant to install behaviour.)Live manifest served at
https://app.ariege.io/libra/manifest.webmanifest:Live manifest served at
https://app.ariege.io/manifest.webmanifest:Service worker registration on the libra side:
So once a user installs the hub PWA at
app.ariege.io/, every navigation underapp.ariege.io/libra/falls inside both the hub'sscope: '/'AND libra'sscope: '/libra/'. Chrome's install affordance treats the page as "inside an installed PWA" and suppresses install for the more-specific libra manifest. The PWAidmismatch isn't enough to break the tie because scope ownership is evaluated first.This rules out any other hypotheses (icon hash collision, manifest URL mismatch, SW scope misregistration). The fix has to be on the hub side, exactly as proposed in the original report. Recommendation stands: option 1 (drop hub PWA install) unless we have a specific reason to keep the launcher home-screen-installable.