feat(dashboard): installable PWA + fix Skills row overflow on mobile - #58532
feat(dashboard): installable PWA + fix Skills row overflow on mobile#58532trac3r00 wants to merge 3 commits into
Conversation
Related to the open installable-PWA cluster: #9897 (earliest, minimal manifest), #56799 (most complete iOS + service-worker take), #50140 (mobile-first chat superset). Competing implementations, not duplicates — this PR uniquely wires the OAuth-gate public prefix + |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for covering both the mobile Skills layout and dashboard installation metadata. The Skills-row change targets the current grid-child layout in web/src/pages/SkillsPage.tsx:492,744.
Problems
web/public/manifest.webmanifest:6setsstart_urlto/(and uses root-absolute scope and icon URLs). The new HTML rewrite points a prefixed deployment at/hermes/manifest.webmanifest, buthermes_cli/web_server.py:16073-16081returns that file unchanged. An installed app behindX-Forwarded-Prefix: /hermeswill therefore start at the origin root and fetch root-level icons instead of staying under/hermes.
Suggested changes
- Make manifest fields prefix-aware and add a proxied manifest test that verifies the start URL, scope, and icon URLs remain under the forwarded prefix.
- Add OAuth-gate coverage for the new manifest and icon public paths, analogous to
tests/hermes_cli/test_dashboard_auth_middleware.py:136-141.
Automated hermes-sweeper review.
| "short_name": "Hermes", | ||
| "description": "Control and configure your self-hosted Hermes Agent — sessions, models, skills, cron, and more.", | ||
| "id": "/", | ||
| "start_url": "/", |
There was a problem hiding this comment.
This root-absolute start URL defeats the new X-Forwarded-Prefix support: the index link becomes /hermes/manifest.webmanifest, but mount_spa() serves the manifest unchanged, so an installed app opens / and the root-absolute scope/icon URLs also escape /hermes. Generate or rewrite these manifest URLs from the normalized request prefix and cover that proxied response.
|
[Bob] Thanks @teknium1 @alt-glitch — both points addressed: Prefix-aware manifest (@teknium1): Will make PWA PR cluster (@alt-glitch): Thanks for mapping the related PRs. This PR's unique contribution is the OAuth-gate prefix handling + Skills mobile overflow fix. Happy to rebase on whichever PR the maintainers pick as canonical, or consolidate the best parts if that's preferred. Will push the manifest fix shortly. |
Make the web dashboard a proper Progressive Web App so it can be added to the home screen on iOS Safari, Android Chrome, and desktop, and fix a horizontal overflow on the Skills page at mobile widths. PWA: - Add web/public/manifest.webmanifest (standalone display, theme_color #041c1c matching the default LENS_0 background, name/short_name, id, start_url, scope). - Add app icons under web/public/icons/ generated from the existing desktop app mark (apps/desktop/public/hermes.png): 192/512 'any' plus 192/512 'maskable' (artwork kept inside the ~80% circular safe zone), and a 180px apple-touch-icon. Icons composite the transparent mark onto the dashboard background so they read cleanly on any launcher. - Wire index.html: manifest link, theme-color, apple-touch-icon, and the apple-mobile-web-app-* / mobile-web-app-capable / application-name meta tags. iOS Safari does not read the web manifest's display/name, so the apple-* tags are required for a standalone home-screen launch. - Serve the new static assets past the auth gate: add /manifest.webmanifest and /icons/ to _GATE_PUBLIC_PREFIXES so an OAuth-gated dashboard still lets the browser fetch them (matching the existing /favicon.ico entry). - Honour X-Forwarded-Prefix for the new asset URLs in _serve_index so the manifest and apple-touch-icon resolve correctly behind a path-prefix reverse proxy, consistent with the existing favicon/assets rewrites. Skills page mobile overflow: - SkillRow's root is a grid item, and grid items default to min-width:auto, so a long skill name/description forced the row wider than the viewport (measured ~1286px wide at a 393px viewport, clipping descriptions off the right edge). Add min-w-0 to the row so it can shrink to its track; verified 146/146 rows now sit within the viewport (document overflow 0) at 393px.
The mobile drawer's <nav> is a `fixed`-positioned overflow-y-auto scroller with 21 nav links (~839px of content) that only ~355px of viewport can show, so the lower tabs require scrolling to reach. On iOS Safari the nav did not respond to finger drags: the sidebar is a `fixed` sibling that overlaps the full-width dim overlay, and with no `touch-action` declared, Safari's touch-scroll heuristics failed to attribute the pan gesture to the nav (mouse-wheel worked, finger did not). Body scroll-lock via `overflow:hidden` while the drawer is open compounded this. Add three defenses to the nav element: - `touch-pan-y` (touch-action: pan-y) — explicitly claim vertical pan so Safari routes the gesture to this scroller. - `overscroll-y-contain` — prevent the pan from chaining to the locked body behind the drawer. - `[-webkit-overflow-scrolling:touch]` — momentum scrolling on iOS. Desktop Chromium (mouse-wheel + emulated touch) still scrolls the nav to the bottom with no regression; tsc -b and the production build both pass, and the three utilities emit to the built CSS bundle.
0098974 to
1a984b2
Compare
- Add dynamic /manifest.webmanifest route in web_server.py that reads X-Forwarded-Prefix and rewrites start_url, scope, id, and icon src paths so the installed PWA stays under the forwarded prefix. - Route is registered before the catch-all SPA handler so it intercepts the manifest request instead of serving the static file. - Add 8 tests covering: OAuth-gate public prefix coverage for manifest and icons, prefix rewriting for all manifest fields, no-prefix passthrough, and deep nested prefix paths.
|
[Bob] Fixes pushed (0ad9375):
27 dashboard tests passing. Ready for re-review @teknium1 @alt-glitch. |
What & why
Makes the web dashboard installable as a Progressive Web App so it can be added to the home screen on iOS Safari, Android Chrome, and desktop, and fixes a horizontal-overflow bug on the Skills page at mobile widths.
The responsive skeleton already works well — the 1024px breakpoint, hamburger drawer, and
viewport-fit=coverare all in place, and document-level horizontal scroll is 0 across phone/tablet viewports. Two gaps remained: there was no PWA manifest/icons (so "Add to Home Screen" produced a plain bookmark, not a standalone app), and one page overflowed its row content on narrow screens.Changes
PWA (installable + home-screen)
web/public/manifest.webmanifest—display: standalone,theme_color/background_color#041c1c(matches the default LENS_0 dashboard background), plusname/short_name/id/start_url/scope.web/public/icons/— app icons generated from the existing desktop app mark (apps/desktop/public/hermes.png, 1254px):192/512any,192/512maskable(artwork kept inside the ~80% circular safe zone), and a 180pxapple-touch-icon. The transparent mark is composited onto the dashboard background so icons read cleanly on any launcher.web/index.html— manifest link,theme-color,apple-touch-icon, and theapple-mobile-web-app-*/mobile-web-app-capable/application-namemeta tags. iOS Safari ignores the manifest'sdisplay/name, so theapple-*tags are what drive a standalone iOS launch.hermes_cli/dashboard_auth/middleware.py— add/manifest.webmanifestand/icons/to_GATE_PUBLIC_PREFIXESso an OAuth-gated dashboard still lets the browser fetch them (mirrors the existing/favicon.icoentry). Without this, the manifest/icons 401 behind the auth gate and the install prompt never appears.hermes_cli/web_server.py— honourX-Forwarded-Prefixfor the new asset URLs in_serve_index, consistent with the existing favicon/assets rewrites, so the manifest and apple-touch-icon resolve correctly behind a path-prefix reverse proxy.Skills page mobile overflow
SkillRow's root is a CSS grid item, and grid items default tomin-width: auto, so a long skill name/description forced the row wider than the viewport (measured ~1286px wide at a 393px viewport, clipping descriptions off the right edge). Addingmin-w-0lets the row shrink to its track.Verification
Measured with Playwright device emulation (iPhone 15 393x852, iPhone SE 375x667, iPad Mini 768x1024, iPad 820x1180).
Skills fix — before: rows overflowed to right~1286px at 393px, descriptions clipped. After: 146/146 rows sit within the viewport, document overflow 0, widest element right = 393 (exactly viewport width). Confirmed visually.
PWA — built the production bundle and served it:
manifest.webmanifestfetches 200 and parses (display: standalone, 4 icons); all 5 icons fetch 200 as real PNG bytes; the builtindex.htmlcarries the manifest link,theme-color,apple-touch-icon, andapple-mobile-web-app-*tags.No regressions —
tsc -bpasses; production build succeeds;test_dashboard_auth_middleware.py,test_dashboard_auth_gate.py,test_dashboard_auth_prefix.py-> 77 passed, 1 skipped.Notes
vite-plugin-pwa)./configtab bar already usesoverflow-x-auto, and the/cronbadge "overflow" only appeared in a mid-load DOM snapshot (not visually) — both were verified as non-issues and intentionally left unchanged.