- Auto-restart: ProcessorManager detects fatal task crashes via done
callback and restarts with exponential backoff (2s-30s, max 5 attempts
in 5 min window). Manual stop disables auto-restart. Restart state
exposed in target state API and via WebSocket events.
- Remove "Running"/"Paused" badge label from sync clock dashboard cards
(pause/play button already conveys state).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add `tags: List[str]` field to all 13 entity types (devices, output targets,
CSS sources, picture sources, audio sources, value sources, sync clocks,
automations, scene presets, capture/audio/PP/pattern templates)
- Update all stores, schemas, and route handlers for tag CRUD
- Add GET /api/v1/tags endpoint aggregating unique tags across all stores
- Create TagInput component with chip display, autocomplete dropdown,
keyboard navigation, and API-backed suggestions
- Display tag chips on all entity cards (searchable via existing text filter)
- Add tag input to all 14 editor modals with dirty check support
- Add CSS styles and i18n keys (en/ru/zh) for tag UI
- Also includes code review fixes: thread safety, perf, store dedup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename all Python modules, classes, API endpoints, config keys, frontend
fetch URLs, and Home Assistant integration URLs from picture-targets to
output-targets. Store loads both new and legacy JSON keys for backward
compatibility with existing data files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add `startup` automation condition type that activates on server boot,
replacing the per-target `auto_start` flag
- Remove `auto_start` field from targets, scene snapshots, and all API layers
- Remove auto-start UI section and star buttons from dashboard and target cards
- Remove `color` field from scene presets (backend, API, modal, frontend)
- Add card color support to scene preset cards (color picker + border style)
- Show localStorage-backed card colors on all dashboard cards (targets,
automations, sync clocks, scene presets)
- Fix card color picker updating wrong card when duplicate data attributes
exist by using closest() from picker wrapper instead of global querySelector
- Add sync clocks step to Sources tab tutorial
- Bump SW cache v9 → v10
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sync clocks now appear as compact cards on the dashboard with
pause/resume/reset controls and click-to-navigate. Dashboard FPS
sparkline charts use the same blue/green colors as target card charts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- CardSection._animateEntrance: skip after first render to prevent
card fade-in replaying on every data refresh
- automations: use reconcile() on subsequent renders instead of full
innerHTML replacement that destroyed and recreated all cards
- streams: same reconcile() approach for all 9 CardSections
- targets/dashboard/streams: only show setTabRefreshing loading bar
on first render when the tab is empty
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use error.detail from API responses instead of generic i18n messages
so users see specific reasons for failures (e.g. "Device is referenced
by target(s): ...").
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename the "profiles" entity to "automations" throughout the entire
codebase for clarity. Updates Python models, storage, API routes/schemas,
engine, frontend JS modules, HTML templates, CSS classes, i18n keys
(en/ru/zh), dashboard, tutorials, and command palette.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Profiles now activate scene presets instead of individual targets, with
configurable deactivation behavior (none/revert/fallback scene). The
target checklist UI is replaced by a searchable combobox for scene
selection that scales well with many scenes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Feature 1 — Profile Conditions: time-of-day, system idle (Win32
GetLastInputInfo), and display state (GUID_CONSOLE_DISPLAY_STATE)
condition types for automatic profile activation.
Feature 2 — Scene Presets: snapshot/restore system that captures target
running states, device brightness, and profile enables. Server-side
capture with 5-step activation order. Dedicated Scenes tab with
CardSection-based card grid, command palette integration, and dashboard
quick-activate section.
Feature 3 — MQTT Integration: MQTTService singleton with aiomqtt,
MQTTLEDClient device provider for pixel output, MQTT profile condition
type with topic/payload matching, and frontend support for MQTT device
type and condition editor.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stability:
- Fix race condition: set _is_running before create_task in target processors
- Await probe task after cancel in wled_target_processor
- Replace raw fetch() with fetchWithAuth() across devices, kc-targets, pattern-templates
- Add try/catch to showTestTemplateModal in streams.js
- Wrap blocking I/O in asyncio.to_thread (picture_targets, system restore)
- Fix dashboardStopAll to filter only running targets with ok guard
Performance:
- Vectorize fire effect spark loop with numpy in effect_stream
- Vectorize FFT band binning with cumulative sum in analysis.py
- Rewrite pixel_processor with vectorized numpy (accept ndarray or list)
- Add httpx.AsyncClient connection pooling with lock in wled_provider
- Optimize _send_pixels_http to avoid np.hstack allocation in wled_client
- Mutate chart arrays in-place in dashboard, perf-charts, targets
- Merge dashboard 2-batch fetch into single Promise.all
- Hoist frame_time outside loop in mapped_stream
Usability:
- Fix health check interval load/save in device settings
- Swap confirm modal button classes (No=secondary, Yes=danger)
- Add aria-modal to audio/value source editors, fix close button aria-labels
- Add modal footer close button to settings modal
- Add dedicated calibration LED count validation error keys
i18n:
- Replace ~50 hardcoded English strings with t() calls across 12 JS files
- Add 50 new keys to en.json, ru.json, zh.json
- Localize inline toasts in index.html with window.t fallback
- Add data-i18n to command palette footer
- Add localization policy to CLAUDE.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace btn-icon with transparent flat dashboard-action-btn style
- Use Lucide power icon instead of square for stop/turn-off buttons
- Add accent-tinted hover backgrounds for start (green) and stop (amber)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Show CPU and GPU model names as overlays on performance chart cards
- Add cpu_name field to performance API with cross-platform detection
- Extract reusable color-picker popover module (9 presets + custom picker)
- Per-chart color customization for CPU/RAM/GPU performance charts
- Redesign header: compact toolbar container with icon-only buttons
- Compact language dropdown (EN/RU/ZH), icon-only login/logout
- Use accent color for FPS charts, range slider accent, dashboard icons
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace all emoji characters across WebUI with inline Lucide SVG icons
for cross-platform consistency (icon paths in icon-paths.js)
- Add accent color picker popover with 9 preset colors + custom picker,
persisted to localStorage, updates all CSS custom properties
- Remove subtab separator line for cleaner look
- Color badge icons with accent color for visual pop
- Remove processing badge from target cards
- Fix hardcoded #4CAF50 in FPS labels and active badges to use CSS vars
- Replace CSS content emoji (▶) with pure CSS triangle
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add sub-tutorials for Dashboard, Targets, Sources, and Profiles tabs
with ? trigger buttons, en/ru/zh translations, and hidden-ancestor
skip via offsetParent check
- Add expand/collapse all buttons to Profiles tab toolbar
- Move dashboard poll slider from section header to toolbar
- Fix cardEnter animation forcing opacity:1 on disabled profile cards
- Use data-card-section selectors instead of data-cs-toggle to avoid
z-index misalignment during tutorial spotlight
- Add tutorial sync convention to CLAUDE.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dashboard cards (targets, auto-start, profiles) are now clickable,
navigating to the full entity card on the appropriate tab. Card
sections support drag-and-drop reordering via grip handles with
localStorage persistence. Fix crosslink navigation scoping to avoid
matching dashboard cards, and fix highlight race on rapid clicks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DDP uses fire-and-forget UDP, so when a WiFi device becomes overwhelmed
by sustained traffic, sends appear successful while the device is
actually unreachable. This adds:
- HTTP liveness probe (GET /json/info, 2s timeout) every 10s during
streaming, exposed as device_streaming_reachable in target state
- Adaptive FPS (opt-in): exponential backoff when device is unreachable,
gradual recovery when it stabilizes — finds sustainable send rate
- Honest health checks: removed the lie that forced device_online=true
during streaming; now runs actual health checks regardless
- Target editor toggle, FPS display shows effective rate when throttled,
health dot reflects streaming reachability, red highlight when
unreachable
- Auto-backup scheduling support in settings modal
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Charts: blue filled area for fps_actual (rolling avg), green line for
fps_current (real-time sends/sec)
- Labels: fps_current/fps_target as primary, avg fps_actual as secondary
- Track fps_current in metrics history for dashboard chart preload
- Applied to both LED targets page and dashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add tab refresh loading bar animation for all 4 tab loaders
- Add profiles loading guard to prevent concurrent fetches
- Centralize theme colors into CSS variables (--text-secondary, --text-muted,
--bg-secondary, --success-color, --shadow-color) for both dark/light themes
- Replace hardcoded gray values across 10 CSS files with variables
- Fix duplicate .btn-sm definition in modal.css
- Fix z-index: toast 2001→2500 to safely clear modals at 2000
- Add :focus-visible keyboard navigation indicators for all interactive elements
- Add responsive breakpoints for tab bar and header on narrow screens
- Prevent background page scroll when command palette is open
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add loading guard to loadPictureSources to prevent concurrent fetches
- Pause perf chart polling and uptime timer when browser tab is hidden
- Disconnect KC and LED preview WebSockets when leaving targets tab
- Add error toasts to loadCaptureTemplates and saveKCBrightness
- Skip auto-refresh polling when document is hidden
- Widen auto-start dashboard cards for better text display
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add auto_start boolean field to PictureTarget model (persisted per-target)
- Wire auto_start through API schemas, routes, and store
- Auto-start targets on server boot in main.py lifespan
- Add star toggle button on target cards (next to delete button)
- Add auto-start section on dashboard between performance and profiles
- Remove auto-start section from profiles tab
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Keyboard shortcuts: Ctrl+1-4 for tab switching
- URL hash routing: #tab/subtab format with browser back/forward support
- Tab count badges: running targets and active profiles counts
- Cross-entity quick links: clickable references navigate to related cards
- Command palette (Ctrl+K): global search across all entities with keyboard navigation
- Expand/collapse all sections: buttons in sub-tab bars
- Sticky section headers: headers pin while scrolling long card grids
- Improved section filter: better styling with reset button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add uptime metric to both LED and KC target cards in the targets tab.
Move formatUptime() to shared ui.js module. Fix dashboard uptime freezing
when switching tabs by re-caching DOM element refs on early return paths.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Background task samples system (CPU/RAM/GPU) and per-target (FPS/timing) metrics
every 1s into a 120-sample ring buffer (~2 min). New API endpoint
GET /system/metrics-history returns the buffer. Dashboard charts now seed from
server history on load instead of sessionStorage, surviving page refreshes.
Also removes emoji from brightness source labels.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Segments are redundant now that the "mapped" CSS type handles spatial
multiplexing internally. Each target now references one color_strip_source_id
instead of an array of segments with start/end/reverse ranges.
Backward compat: existing targets with old segments format are migrated
on load by extracting the first segment's CSS source ID.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each target now has a segments list where each segment maps a color strip
source to a pixel range (start/end) on the device with optional reverse.
This enables composing multiple visualizations on a single LED strip.
Old targets auto-migrate from the single source format on load.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend: add batch endpoints for target states, metrics, and device
health to replace O(N) individual API calls per poll cycle.
Frontend: use batch endpoints in dashboard/targets/profiles tabs,
fix Chart.js instance leaks, debounce server event reloads, add
i18n active-tab guards, clean up ResizeObserver on pattern editor
close, cache uptime timer DOM refs, increase KC auto-refresh to 2s.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix Toggle All button always showing Start: /picture-targets list
endpoint does not include processing state; now fetches
/picture-targets/{id}/state per-target in parallel in both
loadProfiles() and toggleProfileTargets()
- Replace pause icons (⏸) with stop icons (⏹) in dashboard
- Change profile automation toggle tooltip from 'Disabled' (status)
to 'Disable' (action); add profiles.action.disable i18n key
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Disable Chart.js animations on real-time FPS and perf charts
- Dashboard: delta-update profile badges on state changes instead of full DOM rebuild
- Dashboard: cache querySelector results in Map for metrics update loop
- Dashboard: debounce poll interval slider restart (300ms)
- Calibration: debounce ResizeObserver and span drag via requestAnimationFrame
- Calibration: batch updateCalibrationPreview canvas render into rAF
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add static_color capability to WLED and serial providers with native
set_color() dispatch (WLED uses JSON API, serial uses idle client)
- Encapsulate device-specific logic in providers instead of device_type
checks in ProcessorManager and API routes
- Add HAOS light entity for devices with brightness_control + static_color
(Adalight/AmbiLED get light entity, WLED keeps number entity)
- Fix serial device brightness and turn-off: pass software_brightness
through provider chain, clear device on color=null, re-send static
color after brightness change
- Add global events WebSocket (events-ws.js) replacing per-tab WS,
enabling real-time profile state updates on both dashboard and profiles tabs
- Fix profile activation: mark active when all targets already running,
add asyncio.Lock to prevent concurrent evaluation races, skip process
enumeration when no profile has conditions, trigger immediate evaluation
on enable/create/update for instant target startup
- Add reliable server restart script (restart.ps1)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace hardcoded updateAllText() calls with languageChanged event
pattern so feature modules subscribe independently. Guard all API
calls behind apiKey checks to prevent unauthorized requests when not
logged in. Fix login modal localization, hide tabs when logged out,
clear all panels on logout, and treat profiles with no conditions as
always-true.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap running and stopped target lists under a parent Targets group.
Fix narrow-screen layout by keeping action buttons inline and hiding
metrics below 768px.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace text FPS labels with Chart.js sparklines on running targets,
use emoji icons for metrics, add in-place DOM updates to preserve
chart animations, and add a 1-10s poll interval slider that controls
all dashboard timers. Uptime now ticks every second via client-side
interpolation regardless of poll interval.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend: GET /api/v1/system/performance endpoint using psutil (CPU/RAM)
and nvidia-ml-py (GPU utilization, memory, temperature) with graceful
fallback. Frontend: Chart.js line charts with rolling 60-sample history
persisted to sessionStorage, flicker-free updates via persistent DOM
and diff-based dynamic section refresh.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each dashboard section (Profiles, Running, Stopped) now has a chevron
toggle that collapses/expands the section content. Collapsed state is
persisted in localStorage so it survives page reloads and WebSocket
re-renders. Stop All button uses event.stopPropagation() to avoid
triggering the section toggle.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fetch devices list alongside targets and profiles in loadDashboard,
then look up device_type from the devices map instead of relying on
state.device_name which is only available for running targets.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the single 7034-line app.js with 17 ES module files organized
into core/ (state, api, i18n, ui) and features/ (calibration, dashboard,
device-discovery, devices, displays, kc-targets, pattern-templates,
profiles, streams, tabs, targets, tutorials) with an app.js entry point
that registers ~90 onclick globals on window. No bundler needed — FastAPI
serves modules directly via <script type="module">.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>