First slice of the app.js split (#406). Pure utility / infrastructure code that both /index.html and /flow.html use lifts out of the IIFE into a sibling ES module: - DOM helpers: `$`, `el`, `esc`, `form`, `fmtAgeSecs` - Side-panel singleton (`Panel.open` / `openNamed` / `refresh` / `close` / `bind`). The `ensure()` lazy-init makes it tolerate being imported before the DOM element exists — `bind()` still needs to be called once the host page is ready. - Path linkification + file-preview side panel: `appendLinkified`, `appendText`, `makePathLink`, plus the internal `openFilePanel` + `fetchStateFile` + `mdNode` / `svgImage` / `buildTabbedPreview` it depends on. - Browser-notification module `NOTIF` (`bind`, `show`, `renderControls`). `app.js` now imports these from `./common.js` and the duplicated definitions are gone. Each removal is replaced by a one-line breadcrumb comment so a reader chasing a name from the bundled output can find where it landed. `truncate`, `fmtAgo`, `fmtElapsed`, `fmtDuration` stay in app.js for now — each has caller-specific phrasing ("X running", "X ago") that doesn't generalise cleanly. Lift them when a second consumer needs the same shape. ## Next steps (separate PRs) - Step 2: split app.js into `tabs.js` (entry for /index.html — tab renderers + tab routing + refreshState) and `flow.js` (entry for /flow.html — broker terminal + inbox derived store + compose), both importing from common.js. Updates `build.mjs` for multiple entry points and switches each HTML file's `<script src>`. - Step 3 (#408 follow-up): backend-side stream split so /flow.html doesn't have to subscribe to the dashboard's mutation events at all. ## Validation - `npm run build` clean. - Build deltas: `app.js` 154.3kb (was 153.6kb) — bundle size bumped slightly due to per-module overhead; same code under the hood. Source: app.js 2603 → 2287 lines (-316); common.js 367 lines (new). - No HTML / CSS changes. Both pages still load `/static/app.js` as before. Browser smoke test isn't possible from inside iris's container. Worth eyeballing post-deploy: - Notification toggle + send still works (NOTIF.bind, NOTIF.show) - Side panel still opens for diff / file preview / logs (Panel) - Path tokens in messages still render as clickable anchors that open the file in the side panel (appendLinkified → makePathLink → openFilePanel) |
||
|---|---|---|
| .. | ||
| packages | ||
| .gitignore | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
hyperhive frontend
npm workspaces project for the hyperhive browser-facing assets:
packages/shared/— shared modules used by both surfaces (terminal pane, Catppuccin palette + body typography).packages/dashboard/— the hive-c0re dashboard SPA.packages/agent/— the per-container web UI (default agent page, stats, screen).
Build
npm install # one-off; uses the checked-in package-lock.json
npm run build # builds every workspace into packages/*/dist/
The Rust binaries serve packages/dashboard/dist/ and
packages/agent/dist/ via tower_http::ServeDir at runtime; the
build derivation is wired up in nix/modules/frontend.nix. Per-agent
additions are layered on top of the default agent dist via the
hyperhive.frontend.extraFiles option in agent.nix.
Why npm + esbuild
- Hermetic: dependencies vendored via the checked-in lockfile;
buildNpmPackagein nix uses it as the source-of-truth so the output is reproducible without network access at build time. - esbuild: vanilla-JS bundler, no framework runtime overhead.
Each workspace's
build.mjsis ~30 lines. - Single-PR migration: see issue #273 for the design proposal and the four-commit shape (npm scaffold → nix derivations → container plumbing → Rust cutover).