Full-app UI/UX refresh committing to a tech-instrument / studio-console
aesthetic inspired by hardware synths, Eurorack panels, and DAW layouts.
Design tokens and fonts:
- Embed Manrope (body), JetBrains Mono (labels/metrics), Big Shoulders
Display (numeric readouts) as local .woff2 variable fonts with
latin + latin-ext + cyrillic + cyrillic-ext subsets via unicode-range.
- New Lumenworks token layer in base.css: --lux-bg-0..3, --lux-line(-bold),
--lux-ink(-dim/-mute/-faint), --ch-signal/-cyan/-magenta/-amber/-coral/
-violet channel palette, --lux-signal-glow, --lux-shadow-rack, all
theme-aware for dark + light. Existing tokens untouched for compat.
Shell (header + sidebar):
- Header rebuilt as a 3-column CSS-grid transport bar (brand | center |
toolbar) with a glowing LED brand mark rendered via pseudo-elements on
.header-title. Gradient channel-color rule under the bottom border.
- New sidebar.css introduces a vertical channel-strip nav. Active tab
gets a glowing left stripe + radial tint + LED pip. .sidebar-foot
contains a live CPU/FPS meter plate.
- Sidebar collapses to a 56 px icon rail at <=1100 px and hides via
display:contents at <=600 px so mobile.css's fixed bottom tab-bar
flows through unchanged.
Cards and dashboard:
- .card gets channel stripe (data-card-type + .ch-* utilities auto-map
from data-target-id / data-stream-id / data-automation-id etc.), corner
bracket, gradient background, subtle rack shadow.
- .card-running replaces the old @property --border-angle conic-gradient
rotating border with a lightweight signalFlow linear-gradient strip on
the bottom edge (cheaper paint, no GPU layer compositing per card).
- Skeleton loaders rewritten: left hairline + corner bracket + gradient
shimmer instead of the old text-color opacity pulse.
- .dashboard-target rows pick up the same channel-stripe + signalFlow
treatment. Section headers use mono micro-caps with a channel-green
underline accent consistent across the app.
- .perf-chart-card: channel stripe replaces old border-top; per-metric
accents moved to the channel palette (CPU=coral, RAM=violet, GPU=green,
temp=amber). Metric values use tabular-nums + a soft glow.
Live bindings (no new endpoints):
- _updateSidebarMeter: binds the sidebar Load + FPS bars to the existing
/system/performance poll.
- _updateTransportStatus: toggles the transport chip between "Ready" and
"Armed - N live" whenever the dashboard's running-target set is
recomputed.
Tree-nav + sub-tabs:
- tree-nav.css trigger pill gets a channel-stripe left edge that glows
when open; panel has a gradient channel-accent rule across the top;
group headers use silkscreened micro-caps; active leaf has a pulsing
LED pip + channel tint.
- .stream-tab-btn / .subtab-section-header adopt the same mono-caps +
channel-underline language for consistency.
- Graph editor toolbar gets gradient + hairline + rack shadow + backdrop
blur. Canvas and nodes untouched.
Modals (40+ modals share modal.css):
- Radial-dim + 6 px blur backdrop. Content gets a gradient background,
hairline border, deep rack shadow, top channel-accent rule driven by
--modal-ch, bottom-right corner bracket (hidden on mobile fullscreen).
- Per-modal-ID channel lanes: target editors = green, source/input
editors = cyan, audio = magenta, automation/scene/game = violet,
settings/auth = amber, confirm = coral.
- Modal headers: vertical channel stripe left of the title + hairline
divider. Modal footers: hairline top border + subtle gradient wash.
Forms:
- Inputs use hairline borders; number inputs switch to mono + tabular-nums
for column alignment. Focus state: channel-green ring + soft glow.
- Buttons use mono-uppercase type with signal-glow on primary and coral-
glow on danger.
Mobile (<=600 px):
- Fixed bottom .tab-bar gets the full Lumenworks treatment: gradient fill,
top channel-accent rule matching the transport bar, backdrop blur.
Active tab has an LED pip above the icon + channel tint + icon recolor.
- Fullscreen modals: corner bracket hidden, header stripe slimmed.
Microcopy (en / ru / zh):
- "Targets" -> "Channels" / "Каналы" / "通道"
- "Sources" -> "Inputs" / "Входы" / "输入"
- Internal tab keys (dashboard/automations/targets/streams/integrations/
graph) kept stable so no JS or localStorage migration is needed.
- Added: sidebar.workspaces, sidebar.load, sidebar.fps,
transport.status.ready, transport.status.armed.
Compatibility:
- All existing class hooks preserved (.tab-bar, .tab-btn, .card,
.card-running, .tree-dd-*, .cs-*, .perf-chart-card, .modal-content,
.dashboard-target, etc.). No JS or API changes required for the new
look to take effect.
- Tour selectors survive (header .header-title, #tab-btn-*, onclick
markers on theme/settings/search, #cp-wrap-accent, etc.).
- Mobile <=600 px bottom tab-bar keeps working via display:contents
fall-through in the new sidebar.
Build: tsc --noEmit clean; npm run build clean. CSS bundle grew from
~177 KB to ~201 KB for the full new visual system. Fonts loaded lazily
per unicode-range subset (~98 KB critical path for English).
Phased plan + deferred follow-ups (dashboard hero strip, legacy-token
cleanup) recorded at the top of TODO.md.
Reference mockup: server/docs/ui-redesign-mockup.html.
- Replace truncated plaintext release notes with full-screen overlay
rendered via `marked` library
- Server reconnection does a hard page reload instead of custom event
- Rename all 54 .js files to .ts, update esbuild entry point
- Add tsconfig.json, TypeScript devDependency, typecheck script
- Create types.ts with 25+ interfaces matching backend Pydantic schemas
(Device, OutputTarget, ColorStripSource, PatternTemplate, ValueSource,
AudioSource, PictureSource, ScenePreset, SyncClock, Automation, etc.)
- Make DataCache generic (DataCache<T>) with typed state instances
- Type all state variables in state.ts with proper entity types
- Type all create*Card functions with proper entity interfaces
- Type all function parameters and return types across all 54 files
- Type core component constructors (CardSection, IconSelect, EntitySelect,
FilterList, TagInput, TreeNav, Modal) with exported option interfaces
- Add comprehensive global.d.ts for window function declarations
- Type fetchWithAuth with FetchAuthOpts interface
- Remove all (window as any) casts in favor of global.d.ts declarations
- Zero tsc errors, esbuild bundle unchanged
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add esbuild bundling: JS (IIFE, minified, sourcemapped) and CSS into
single dist/ files, replacing 15+ individual CSS links and CDN scripts
- Bundle Chart.js and ELK.js from npm instead of CDN (fully offline)
- Serve DM Sans and Orbitron fonts locally from static/fonts/
- Fix dashboard automation card stretching full width (max-width: 500px)
- Fix time_of_day condition not localized in automation cards
- Add Chrome browser tools context file for MCP testing workflow
- Update frontend context with bundling docs and Chrome tools reference
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>