Repository navigation
feat: rebuild the web dashboard as a typed Preact app - #38
Merged
Merged
Conversation
Replace the string-built HTML in src/dashboard.ts and the global-function
JS/CSS in src/static/ (about 8.6k lines in all) with a TypeScript + Preact
single-page app in src/web, bundled in memory by esbuild at startup, so
there is still no separate build step.
- Shell: a top bar with live status, add account, search and a "Needs
you" inbox; an icon rail that expands to labels; one floating canvas;
a Cmd/Ctrl+K command palette; a profile menu with theme, privacy mask
and sign out. Light and dark themes, and phone layouts where the rail
is a slide-over sheet and the drawer a bottom sheet.
- Overview: routing state and account counts, an inline attention list
where every item carries its fix, and one row per quota pool (pooled
tier-weighted quota, the account serving it, next up with the policy's
pick first, next reset, runway) that expands into routing decisions.
- Accounts: cards or a compact sortable list with filters in the URL,
and a drawer at /dashboard/accounts/<email> with quota windows,
routing decisions, the health breakdown, budgets and every action.
- Requests (live tail plus PostgreSQL history with a payload inspector
and per-key totals), Usage (range-aware token chart, savings, latency,
60-day heatmap), Virtual keys, and Settings (routing controls and
policy, benchmark, configuration file, appearance).
- Data API: /api/dashboard/{snapshot,stream,usage,activity,usage/export}.
The stream sends a snapshot and then only what changed; countdowns are
absolute timestamps, so an idle rotator sends nothing. /api/status and
/api/events are unchanged.
- Auth: ?token= links and a sign-in screen exchange the admin token for
an HttpOnly, SameSite=Strict HMAC session cookie. Cookie-only writes
must be same-origin (403 otherwise) and sign-out revokes the session.
Strict CSP with no inline handlers or styles.
- Token usage: bucket keys are parsed as UTC, hours are kept 61 days for
the heatmap, and all-time totals count every tier, since rollups move
buckets rather than copy them.
- Docker: the image sets TUXEVIL_ROTATOR_CONTAINER=1, so the proxy
exposure warning becomes a note that points at the published port,
and the warning title names what is exposed.
- scripts/dashboard-dev.ts (npm run dashboard:dev) runs the real routes
against a simulated rotator with scenarios.
- Docs: new docs/dashboard.md with screenshots from the dev server;
README, CONTRIBUTING, API reference, deployment, troubleshooting and
the other guides updated for the new dashboard.
- Tests for session auth, live diffing, usage windows and rollups,
routes, exposure and the client view-model logic replace the node:vm
harness.
Owner
|
Huge thanks for this incredible WebUI overhaul. The redesign is exceptionally thoughtful and polished, and it makes Tuxevil Rotator much clearer and more pleasant to use. I really appreciate the care and effort you put into this contribution. I found one small session-revocation edge case and will take care of that before merging. |
tuxevil
added a commit
that referenced
this pull request
Oct 5, 2026
tuxevil
added a commit
that referenced
this pull request
Oct 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Replaces the string-built HTML in
src/dashboard.tsand the global-function JS and CSS insrc/static/(about 8.6k lines) with a TypeScript + Preact single-page app insrc/web. esbuild, which already ships with tsx, bundles it in memory at startup, so there is still no build step.The dashboard is now organized around one question: does routing work right now, and for how long?
Pages
/dashboard/accounts/<email>with its quota windows, routing decisions, health breakdown, budgets and every action.Across pages: a ⌘K command palette, light and dark themes, phone layouts and the privacy mask (
?mask=1). Every view, filter and open drawer is in the URL.The screenshots come from
npm run dashboard:dev, which serves the real dashboard against simulated accounts.Behavior changes
/api/dashboard/{snapshot,stream,usage,activity,usage/export}. The stream sends a snapshot, then only what changed. Countdowns are absolute timestamps, so an idle rotator sends nothing./api/statusand/api/eventsare unchanged.?token=links and a new sign-in screen exchange the admin token for anHttpOnly,SameSite=Strictsession cookie, and the token leaves the URL. Cookie-only writes must be same-origin, sign-out revokes the session, and dashboard pages get a strict CSP. Tokens the old dashboard kept inlocalStorageare migrated once and deleted.TUXEVIL_ROTATOR_CONTAINER=1. Inside a container the proxy exposure warning becomes a note that points at the published port, instead of a warning on every install./redirects to/dashboard, and/dashboard/logsredirects to the request history. Behind a reverse proxy, forward theHostheader or dashboard actions return 403.preactand@preact/signals, and makesesbuilda direct dependency.Testing
npm run checkpasses with 1031 tests passing, 0 failures and 2 skipped. Source, web and test typechecks pass. ESLint reports 0 errors.New tests cover session auth, the live diff stream, usage windows and rollups, the dashboard routes, the exposure warning and the client view-model logic. They replace the old node:vm harness.
I also built the Docker image from this branch and ran it locally:
docker stopand restartDocs
New
docs/dashboard.mdwalks through every page with screenshots.CONTRIBUTING.mddocuments the dev server, and the README, API reference, deployment, troubleshooting and account guides are updated for the new dashboard.