The gateway answered every non-page request without a session with a login
redirect, which fetch and EventSource cannot follow across origins, so polls,
forms and streams failed with errors that said nothing about the session. It
now answers anything that does not ask for text/html with a 401 and a
WWW-Authenticate header, and the swarm UI reloads on that 401, from a wrapped
fetch (one place for every call) and from a probe after a stream dies. A second
reload within ten seconds is skipped so a page that keeps answering 401 cannot
loop. The proxy test and the docs follow.
Closes#4282. mara: "scope looks good" — approving the plan posted
there (manifest + icons + minimal shell-only service worker + iOS meta
tags) and both explicit questions (network-first-with-offline-fallback,
never cache /api/*).
docs/web-ui/design-guide.md's "Layout & viewport" section already
asserted swarm-ui is installable as a PWA — this is what actually backs
it.
- manifest.webmanifest: name/icons/start_url/standalone display, theme
#cba6f7 / background #1e1e2e matching the mocha --purple/--bg values.
- sw.js: plain JS, not TypeScript — the DOM lib swarm-ui's own tsconfig
uses and the WebWorker lib a service worker's globals need are
mutually exclusive in one tsc program, not worth a second tsconfig for
a self-contained ~100-line file. Scoped to the app shell only, never
touches /api/* at all, network-first with offline-fallback-to-cache
(not cache-first) since main.js/main.css are unhashed filenames and a
cache-first SW would risk wedging an operator on stale JS after a
deploy.
- index.html: manifest link, theme-color meta, iOS
apple-mobile-web-app-* tags (Safari ignores the manifest spec).
- main.tsx: feature-detected SW registration.
- branding/hyperhive-maskable.svg: hyperhive.svg's own artwork already
fills nearly its whole canvas, so a maskable icon needs a padded
variant or an OS mask crops the outer ring/corner brackets — embeds
the original via a scaled <image> ref rather than duplicating markup.
- nix/packages/swarm-ui.nix: rasterizes icon-192/512/512-maskable.png
from the branding SVGs at build time via librsvg, rather than
checking in static PNGs.
Verified for real: typecheck+build green, and a real headless-chromium
tab driven over CDP confirms the service worker registers and becomes
the active controller, and a simulated-offline reload still serves the
full cached shell rather than a browser error page. nix build .#swarm-ui
also verified green, including the rasterized icon output.
Pure `nix fmt` output from the commit before this one — no hand edits.
203 files: 52 md, 42 tsx, 32 js, 32 css, 21 ts, 13 html, 8 json, 3 mjs.
Reproduce with `nix develop -c nix fmt` on the parent commit; the result
should be byte-identical to this tree.
None of the 13 `.prettierignore` entries appears here — verified by
intersecting the changed-file list against the ignore file, with a
control proving the intersection finds a match when one exists.
Project-bootstrap scope per the issue: static build as a nix pkg,
empty start page for now, functionality deferred until auth against
authelia is figured out. Stack (Preact + wouter + TypeScript + JSX)
matches the shell decision from the earlier framework-paths thread —
a real SPA shell with a router and deep links, distinct from the
per-hive dashboard's vanilla-JS + custom-element MPA.
- New npm workspace frontend/packages/swarm-ui: one route (/), a
wouter Switch/Route shell, a 404 fallback. Reuses @hive/shared's
colors.css/theme.css/base.css for visual consistency; no other
shared JS (the vanilla-JS el()/dom.js helpers are superseded by
Preact in this shell).
- nix/packages/swarm-ui.nix: its own buildNpmPackage derivation
(scoped to just this workspace via an explicit buildPhase), not
folded into nix/packages/frontend.nix's packages.default closure —
same reasoning swarm-controller/swarmctl already use for staying out
of daemonBins: a hive that doesn't run the swarm controller
shouldn't carry swarm-ui bytes.
- npmDepsHash recomputed in both frontend.nix and swarm-ui.nix (same
shared lockfile, new deps: preact, wouter-preact, typescript).
- Added swarm-ui to nix/checks.nix alongside frontend, for the same
FOD-staleness reason plus being the only thing that actually builds
it in CI (not in packages.default's closure like frontend is, so
nix flake check wouldn't otherwise touch it).
- npm run typecheck (tsc --noEmit) is available locally; not yet wired
into CI — esbuild transpiles TS without type-checking, so that's a
real gap, left as a follow-up rather than growing this bootstrap PR
with a new CI workflow step.
Verified: nix build .#swarm-ui and .#frontend both succeed; npm run
build (root, all workspaces) succeeds; tsc --noEmit clean;
scripts/check-issue-refs.sh clean.