28 KiB
28 KiB
UX Review Test Plan — Pi Multi-FX Pedal Web UI
Date: June 14, 2026 Scope: Full web UI — React SPA + legacy Jinja2 pages Target URL: http://pedal.local:8080 Methodology: Nielsen's 10 Usability Heuristics + Flow Analysis + Visual Cohesion Audit
1. Scope & Personas
Personas
| Persona | Goal | Context |
|---|---|---|
| Session Guitarist | Dial in a tone fast during a live session or recording | On a phone/tablet near the amp, tweaking EQs and effects between takes. Wants minimal taps to hear results. |
| Preset Tweaker | Browse, load, save, and edit presets from a laptop | Sitting at a desk building a pedalboard. Wants deep control over FX chain, NAM models, IR cab sims. |
| Headless Stage User | Switch presets, toggle bypass, check tuner — with footswitches only | Never touches the web UI during performance. Uses it only for setup/config behind the scenes. |
| Admin / Integrator | Configure WiFi, Bluetooth MIDI, audio profiles, hotspot | Technical user connecting the pedal to different environments (studio, stage, rehearsal space). |
Flows to Test
| # | Flow | Steps | Priority |
|---|---|---|---|
| F1 | Load pedal dashboard → check status | 2 | Critical |
| F2 | Browse preset banks → load a preset | 4 | Critical |
| F3 | Edit preset parameters (name, volume, FX chain) | 5 | High |
| F4 | Toggle bypass and adjust master volume | 3 | Critical |
| F5 | Browse and install a NAM model from Tone3000 | 6 | High |
| F6 | Upload and load an IR cab sim file | 4 | High |
| F7 | Switch audio latency profile | 3 | Medium |
| F8 | Configure and enable WiFi hotspot | 5 | Low |
| F9 | Scan for, connect to WiFi network | 4 | Low |
| F10 | Bluetooth scan, pair, and view MIDI status | 5 | Low |
| F11 | Toggle 4CM routing mode and set breakpoint | 3 | Medium |
| F12 | Check tuner display with guitar input | 2 | Medium |
| F13 | Save/recall snapshot slots | 4 | Medium |
| F14 | Empty state: unload model, view dashboard with no presets | 2 | High |
UI Surfaces Reviewed
- React SPA (
/— root URL) - Legacy Dashboard (
/— fallback without React build) - Presets page (
/presets) - Models page (
/models) - IRs page (
/irs) - Settings > Connection tab
- Settings > Audio tab
- Settings > 4CM Routing tab
- Settings > Network tab (WiFi scan, hotspot)
- Settings > Bluetooth tab
- Settings > About tab
- Preset Edit modal
- WiFi Connect modal
- Connection status indicator (global header)
2. Heuristic Walkthrough
H1 — Visibility of System Status
| # | Test | Action | Expected | Method |
|---|---|---|---|---|
| H1.1 | Page load indicator | Navigate to / |
Loading placeholder or skeleton while API/WS connects | Browser |
| H1.2 | Connection status | Open page when pedal is off | "Disconnected" badge (red) in header | Browser |
| H1.3 | Connection status | Open page when pedal is on | "Connected" badge (green) in header | Browser |
| H1.4 | Preset activation feedback | Click a preset card | Card highlights, dashboard preset name updates, WS broadcast visible | Browser |
| H1.5 | Volume slider feedback | Drag volume slider | Value % text updates in real time | Browser |
| H1.6 | Bypass toggle feedback | Click bypass button | Button text toggles BYPASSED/ACTIVE, color changes | Browser |
| H1.7 | Tuner toggle feedback | Click tuner button | Button toggles ON/OFF, color changes | Browser |
| H1.8 | WebSocket reconnection | Kill server, wait, restart | "Disconnected" → "Connected" after auto-reconnect | Browser |
| H1.9 | Model load progress | Click Load on a NAM model | Loading state on the button, list refreshes after | Browser |
| H1.10 | Tone3000 search feedback | Search Tone3000 for models | "Searching..." spinner shown, results appear, offline warning shown if 503 | Browser |
| H1.11 | Tone3000 install feedback | Install a model from Tone3000 | Button shows "Downloading...", then "✓ Done", list refreshes | Browser |
| H1.12 | File upload feedback | Upload a .nam or .wav file | Input clears, list refreshes with new entry | Browser |
| H1.13 | Audio profile switch | Switch to low latency profile | "restarted: true" in response, brief JACK restart pause | API + Browser |
| H1.14 | RSSI/connection data in settings | Open Network tab | WiFi SSID, IP, signal % shown, visible from refresh | Browser |
| H1.15 | BT status indicators | Open Bluetooth tab | Power, discoverable, adapter name visible | Browser |
| H1.16 | WS client count | Open Settings → Connection | Connected clients count shows active WS sessions | Browser |
Grep for verification:
# Loading states in source
grep -n "loading\|spinner\|skeleton\|Loading" src/web/static/*.js src/web/static/style.css
# Connection status toggle
grep -n "connection-status\|Connected\|Disconnected" src/web/static/*.js src/web/templates/base.html
# Button disabled states on async actions
grep -n "\.disabled\|disabled =" src/web/static/*.js
H2 — Match Between System and Real World
| # | Test | Action | Expected | Method |
|---|---|---|---|---|
| H2.1 | FX type labels in UI | View FX chain, preset edit modal | Labels use real-world names (e.g., "Noise Gate" not "noise_gate") | Source + Browser |
| H2.2 | Model/IR list readability | View Models or IRs page | File names appear as human-readable labels | Browser |
| H2.3 | 4CM routing description | Enable 4CM in Settings | Plain language: "Input 1 (Guitar) → Pre blocks → Send | Input 2 (Return) → Post blocks → Output" | Browser |
| H2.4 | Tuner note display | Enable tuner with guitar plugged in | Shows musical note names (A, A#, Bb...) not frequencies only | Browser |
| H2.5 | Preset meta labels | View preset card | Shows "Bank 0 · Program 2" — accessible musician language | Browser |
| H2.6 | Audio profile names | View profiles list | "Standard", "Low" — musician-friendly not technical | Browser |
| H2.7 | NAM architecture info | View model details | Shows "featherwave-v2" or architecture name, not internal paths | Browser |
Grep for verification:
# Check for snake_case / internal names leaking into UI
grep -n "fx_type\|replace.*_/g\|FXType" src/web/static/presets.js | head -20
# presets.js line 92: const label = block.fx_type.replace(/_/g, ' '); — detects raw fx_type
H3 — User Control and Freedom
| # | Test | Action | Expected | Method |
|---|---|---|---|---|
| H3.1 | Modal close options | Open preset edit modal | Close on ✕ button, close on overlay click, close on Cancel button | Browser |
| H3.2 | Modal close on Escape | Open modal, press Escape | Modal closes | Browser |
| H3.3 | Delete preset confirmation | Click Delete in preset modal | confirm() dialog appears before deletion |
Browser |
| H3.4 | Cancel WiFi connect | Open WiFi modal, click Cancel | Modal closes, no connection attempted | Browser |
| H3.5 | Back navigation | Navigate to any page, press Back | Browser back works, returns to previous page | Browser |
| H3.6 | Tab navigation persists | Switch to Network tab, navigate away and back | Active tab remembered via URL hash | Browser |
| H3.7 | Tuner toggle graceful | Toggle tuner ON while playing | Audio mutes or tuner activates without loud pop/clip | Browser + Audio |
| H3.8 | Bypass toggle graceful | Toggle bypass ON while playing | Clean DI signal, no pop/clip | Browser + Audio |
| H3.9 | Unload model without issues | Click Unload on loaded model | Model unloads, dashboard shows "None loaded", audio still flows | Browser |
H4 — Consistency and Standards
| # | Test | Action | Expected | Method |
|---|---|---|---|---|
| H4.1 | Navigation active state | Click each nav link | Active link highlighted, consistent style across all pages | Browser |
| H4.2 | Button style consistency | Compare primary/secondary/danger across pages | Same styles everywhere (colors, padding, font size) | Browser |
| H4.3 | Toggle button pattern | Compare bypass, tuner, 4CM toggles | Same ON/OFF pattern, same active/inactive colors | Browser |
| H4.4 | Slider pattern | Compare volume sliders on Dashboard vs Settings | Same visual, same behavior, synced values | Browser |
| H4.5 | Connection status in header | Navigate through all pages | Connection indicator always present, same position | Browser |
| H4.6 | Page header pattern | Visit Presets, Models, IRs, Settings pages | Consistent page-header with h1, same spacing | Browser |
| H4.7 | Card structure | Compare all card components | Uniform header/body/footer pattern — identical padding, border, radius | Browser |
| H4.8 | Danger button meaning | Compare Delete preset, Unload model/IR | All red danger buttons are destructive actions | Browser |
| H4.9 | Tab pattern (Settings) | Switch between all 6 settings tabs | Underline active indicator, same transition | Browser |
H5 — Error Prevention
| # | Test | Action | Expected | Method |
|---|---|---|---|---|
| H5.1 | Disabled submit during load | Click Load on model rapidly | Button disabled after first click, no duplicate load | Browser |
| H5.2 | Disabled submit during upload | Upload a file, click multiple times | Button disabled during upload | Source |
| H5.3 | Delete preset confirmation | Click Delete | Confirm dialog: "Delete this preset?" | Browser |
| H5.4 | File type validation on upload | Try uploading a .txt file | Rejected at client or server level | Browser |
| H5.5 | Audio profile double-switch | Switch to same profile twice | restarted: false, no unnecessary JACK restart |
API |
| H5.6 | 4CM breakpoint bounds | Drag breakpoint slider min/max | Clamped 0–16 | Browser |
| H5.7 | Volume clamping | Set volume > 100% or < 0% via API | Clamped to 0.0–1.0 | API |
| H5.8 | Empty preset name | Save preset with empty name | Should default to "Preset" or reject with validation | Browser |
| H5.9 | Hotspot password length | Try password > 63 chars | Maxlength on input field prevents it | Browser |
Code verification:
grep -n "confirm\|showModal\|are you sure" src/web/static/*.js
grep -n "\.disabled" src/web/static/models.js src/web/static/irs.js
H6 — Recognition Rather Than Recall
| # | Test | Action | Expected | Method |
|---|---|---|---|---|
| H6.1 | Current preset name visible | Load any page | Preset name clearly shown in Dashboard or in header | Browser |
| H6.2 | Currently loaded model/IR | View Models/IRs page | "CURRENT" badge visible on active model/IR | Browser |
| H6.3 | Active preset card highlighted | Browse presets | The active preset card has a distinct border/background | Browser |
| H6.4 | Bank/program location | View preset card | "Bank N · Slot N" visible without clicking | Browser |
| H6.5 | Navigation labels visible | All pages | All 5 nav links visible, no hamburger hiding | Browser |
| H6.6 | FX chain status on dashboard | Connected, preset loaded | Blocks visible with ON/OFF badges | Browser |
| H6.7 | Modal title shows preset name | Click to edit preset | "Edit: [Preset Name]" — user knows what they're editing | Browser |
| H6.8 | Routing mode visible from dashboard | Any page | Badge shows "Mono" or "4CM" | Browser |
| H6.9 | Tone3000 installed state | Revisit after install | Previously installed models show ✓ Installed badge (localStorage) | Browser |
H7 — Flexibility and Efficiency
| # | Test | Action | Expected | Method |
|---|---|---|---|---|
| H7.1 | Keyboard submit on search | Type in Tone3000 search, press Enter | Triggers search | Browser |
| H7.2 | FAQ: Keyboard shortcuts | Test Tab order through form fields | Logical focus order, all interactive elements reachable | Browser |
| H7.3 | Bulk actions | Models/IRs pages | No bulk select/load/delete — note as missing efficiency | Browser |
| H7.4 | Auto-refresh on preset save | Save preset edit | Modal closes, preset list auto-refreshes | Browser |
| H7.5 | Auto-refresh after model/IR upload | Upload model/IR | List auto-refreshes after upload completes | Browser |
| H7.6 | Trending option on Tone3000 | Click "Trending" | Fetches trending models/IRs without typing a query | Browser |
| H7.7 | Tab navigation in Settings | URL hash (#network, #bluetooth) |
Deep-linkable settings tabs | Browser |
| H7.8 | WS-driven live updates | Change volume on another tab | Dashboard and Settings sliders sync in real time | Browser |
H8 — Aesthetic and Minimalist Design
| # | Test | Action | Expected | Method |
|---|---|---|---|---|
| H8.1 | Content-to-chrome ratio | View Dashboard | Essential info above the fold: preset, bypass, volume, FX chain | Browser |
| H8.2 | Visual hierarchy | View any page | Most important element draws eye first (preset name, status) | Browser |
| H8.3 | Information density | Dashboard page | Not overcrowded — cards with clear sections | Browser |
| H8.4 | Typography consistency | Compare h1/h2 across pages | Same font sizes, weights, colors for each heading level | Browser |
| H8.5 | Line length readability | Any card body | Text doesn't span full viewport — contained by max-width | Browser |
| H8.6 | Dark theme cohesion | All pages | Consistent dark palette, no jarring color changes | Browser |
| H8.7 | Redundant elements | Check for duplicate info | No data shown in multiple places unnecessarily | Browser |
| H8.8 | Empty states visual | Unload model, clear presets | Helpful empty states, not just blank areas | Browser |
| H8.9 | Modal sizing | Open preset edit modal | Appropriate width, doesn't overwhelm on mobile | Browser |
H9 — Help Users Recognize, Diagnose, and Recover from Errors
| # | Test | Action | Expected | Method |
|---|---|---|---|---|
| H9.1 | API error → user message | Trigger a 500 on preset load | User-facing error, not raw JSON or console-only | Browser |
| H9.2 | Tone3000 offline state | Disconnect internet, search | "⚠ Offline — search unavailable" warning shown | Browser |
| H9.3 | Upload error handling | Upload corrupt .nam file | Alert with error message: "Upload error: ..." | Browser |
| H9.4 | Model load failure | Try to load corrupt model | Alert: "Failed to load model: ..." | Browser |
| H9.5 | Preset load failure | Access empty slot via direct URL | 404 — "Preset not found" | Browser |
| H9.6 | WiFi connect error | Wrong password on WiFi modal | Error message shown in modal, modal stays open | Browser |
| H9.7 | JACK restart failure | Kill JACK, switch profile | API returns 500 with "Failed to start JACK — rolled back" | API |
| H9.8 | API error on Dashboard | Kill backend, load dashboard | Silent catch with console.warn — check for user-facing message | Browser |
| H9.9 | Empty preset slot styling | Presets page, empty slot | Shows "— Empty —" with reduced opacity | Browser |
Code verification:
# Error handling patterns — check for user-facing messages vs silent console
grep -n "\.catch\|catch(" src/web/static/*.js | grep -v "console.warn\|console.error"
grep -n "alert(" src/web/static/*.js
grep -n "text-muted\|network-error\|Error:" src/web/static/*.js
H10 — Help and Documentation
| # | Test | Action | Expected | Method |
|---|---|---|---|---|
| H10.1 | Tooltips on controls | Hover over any button | No tooltips currently — add recommendation | Browser |
| H10.2 | Upload hints | Check upload sections | "Upload .nam model files to the pedal's model directory." — clear | Browser |
| H10.3 | Tone3000 hints | Check Tone3000 section | "Search and download NAM models directly from the Tone3000 community." | Browser |
| H10.4 | Empty state guidance | No models/presets/IRs | Actionable: "No .nam models found" + upload option visible | Browser |
| H10.5 | About page | Navigate to About tab | Version, platform, repo link available | Browser |
| H10.6 | Help within the app | Check for question marks, help links | None found — add recommendation for critical flows | Browser |
| H10.7 | IR details context | View IR list | Shows "1024 taps · 21.3ms @ 48000Hz" — helpful technical detail | Browser |
3. Flow Friction Map
Each flow from Section 1 tested step-by-step. Score 1-5:
| Flow | Step | Friction | Issue Ref | Notes |
|---|---|---|---|---|
| F1 — Load dashboard | Navigate to pedal.local:8080 |
1 | — | React SPA loads (or legacy fallback) |
| F1 | Check connection status | 1 | — | Color-coded badge in header |
| F1 | View current state | 1 | — | WS pushes state on connect |
| F2 — Browse presets | Click Presets nav | 1 | — | |
| F2 | Wait for bank list | 2 | H1-like | Loading indicator present |
| F2 | Click preset card | 1 | — | |
| F2 | Preset loads, dashboard updates | 1 | — | WS pushes update |
| F3 — Edit preset | Click preset card to open modal | 1 | — | |
| F3 | Change name | 1 | — | Text input clear |
| F3 | Adjust volume | 1 | — | Slider works |
| F3 | View FX chain in modal | 2 | H2, H6 | Labels use replace(/_/g,' ') — see notes |
| F3 | Click Save | 1 | — | Modal closes, list refreshes |
| F3 | Click Delete | 1 | — | Confirm dialog appears |
| F4 — Bypass & volume | Click bypass button | 1 | — | Immediate toggle |
| F4 | Verify bypassed audio | 1 | — | Clean DI signal |
| F4 | Drag volume slider | 1 | — | Real-time update |
| F5 — Tone3000 browse | Go to Models page | 1 | — | |
| F5 | Type search query | 1 | — | Enter triggers search |
| F5 | Wait for results | 3 | H1 | "Searching..." spinner, but no timeout info |
| F5 | Click Install on result | 2 | H1 | Button shows "Downloading..." |
| F5 | Verify model appears in list | 1 | — | Auto-refreshes |
| F6 — Upload IR | Go to IRs page | 1 | — | |
| F6 | Click file input | 1 | — | |
| F6 | Select .wav file | 1 | — | File type restricted |
| F6 | Click Upload | 2 | H1 | No upload progress bar — just button state |
| F6 | Verify in list | 1 | — | Refreshes |
| F7 — Audio profile switch | Go to Settings > Audio | 1 | — | |
| F7 | Profiles are visible | 2 | — | No explicit "switch profile" button in UI — needs API |
| F7 | Switch profile | 2 | H10 | No in-UI profile switcher visible in Audio tab |
| F8 — Hotspot config | Go to Network tab | 1 | — | |
| F8 | Edit SSID/password | 1 | — | Input fields ready |
| F8 | Click Enable Hotspot | 2 | H1 | No "enabling..." state |
| F8 | Verify clients listed | 2 | H1 | Auto-polls or manual refresh? |
| F9 — WiFi scan | Go to Network tab | 1 | — | |
| F9 | Click Scan | 2 | H1 | "Scanning..." button state, results appear |
| F9 | Click Connect on network | 1 | — | Modal opens |
| F9 | Enter password | 1 | — | |
| F9 | Click Connect | 2 | H1/H9 | Modal error if fails |
| F10 — BT scan | Go to Bluetooth tab | 1 | — | |
| F10 | Scan for devices | 2 | H1 | "Scanning (12s)..." — shows expected duration |
| F10 | Pair with device | 2 | H1 | No pairing feedback beyond spinner |
| F11 — 4CM routing | Go to Settings > 4CM Routing | 1 | — | |
| F11 | Toggle 4CM ON | 1 | — | Breakpoint row enables |
| F11 | Drag breakpoint | 1 | — | Description updates live |
| F12 — Tuner | Toggle tuner ON | 1 | — | |
| F12 | Check note detection | 1 | — | Fast poll endpoint |
| F13 — Snapshots | Go to snapshot section | 3 | — | No snapshot UI on dashboard — check React SPA |
| F13 | Save snapshot to slot | 2 | — | Via API or in-app? |
| F14 — Empty states | Unload all models | 1 | H6 | "None loaded" shown clearly |
| F14 | Delete all presets | 1 | H9 | "No presets found. Create one from the Dashboard." |
4. Visual & Interaction Checklist
| Check | Pass? | Issues | Notes |
|---|---|---|---|
| Consistent spacing / grid | ✅ | — | Cards share --radius, --border, padding: 10-14px |
| Typography hierarchy | ✅ | — | h1=1.1rem, h2=0.9-0.95rem, body=0.85rem — clear hierarchy |
| Color consistency | ✅ | — | Single accent #4fc3f7, consistent danger/success |
| Interactive states | ⚠️ | See below | Hover, active states defined; missing focus-visible styles |
| Responsive layout | ✅ | — | 82% max-width mobile, 600px/720px breakpoints |
| Loading states | ⚠️ | H1-series | Most pages have loading indicators; Tone3000 spinner lacks progress |
| Empty states | ✅ | — | Clear messages: "No models found", "None loaded" |
| Error states | ⚠️ | H9-series | API errors shown via alert(); silent catches on Dashboard WS |
| Edge cases (long text, rapid click) | ⚠️ | H5, H8 | Long preset names handled with ellipsis; Button disabled states present |
| Touch targets ≥ 48px | ⚠️ | — | .btn padding 8px 16px — may be borderline on mobile |
| Dark theme readability | ✅ | — | High contrast: #e0e0e0 on #0d0d0d background |
| Smooth transitions | ✅ | — | transition: background 0.2s, border-color 0.2s on interactive elements |
5. Responsive & Mobile UX Checks
| # | Test | Viewport | Expected | Method |
|---|---|---|---|---|
| R1 | Dashboard on mobile | 375px wide | Status row stacks (grid → 1 column), nav links compact | Browser |
| R2 | Presets grid on mobile | 375px wide | 2-column grid intact, cards shrink appropriately | Browser |
| R3 | Settings tabs on mobile | 375px wide | Horizontal scrollable tabs with hidden scrollbar | Browser |
| R4 | Modal on mobile | 375px wide | Modal fills width with padding, scrollable body | Browser |
| R5 | Touch targets on mobile | 375px, touch | Buttons have touch-action: manipulation, no 300ms delay |
Source |
| R6 | Nav overflow | Very long nav labels | overflow-x: auto with hidden scrollbar |
Browser |
| R7 | Header sticky on scroll | Scroll down on any page | Header stays at top (position: sticky; z-index: 100) |
Browser |
| R8 | Input fields on mobile | Focus any input | No viewport zoom (user-scalable=no set) — intentional? |
Browser |
| R9 | Content max-width on large screen | 1920px wide | --max-width: 720px — content centered, not stretched |
Browser |
6. Real-Time & WebSocket UX
| # | Test | Action | Expected | Method |
|---|---|---|---|---|
| WS1 | Multiple tabs sync | Open 2 browser tabs, change volume on tab 1 | Tab 2 slider and value update within 1s | Browser |
| WS2 | Bypass sync across tabs | Toggle bypass on tab 1 | Tab 2 button text and color update | Browser |
| WS3 | Preset change broadcast | Activate preset via /presets page | Dashboard preset card updates on all connected clients | Browser |
| WS4 | Reconnection UX | Unplug network cable, wait 10s, reconnect | "Disconnected" appears, then auto-reconnects showing "Connected" | Browser |
| WS5 | WS reconnection backoff | Keep pedal disconnected for 1 min | Reconnect delay increases from 1s to max 15s | Browser |
| WS6 | Concurrency: 3 tabs + API | Open 3 browser tabs + curl API calls | All clients receive broadcasts, no dropped messages | Multi-browser |
| WS7 | Initial state on WS connect | Open fresh browser tab | Receives {"type": "connected", "state": {...}} with full current state |
Browser |
7. Accessibility Quick Checks
| # | Test | Expected | Method |
|---|---|---|---|
| A1 | Tab navigation through nav links | All 5 nav links focused in order | Browser |
| A2 | Tab navigation through preset grid | Each preset card focusable | Browser |
| A3 | Tab navigation through modal | Input, slider, Save, Delete, Cancel in logical order | Browser |
| A4 | Focus-visible styles on interactive | Visible focus ring on buttons, links, inputs | Browser |
| A5 | Color contrast: text on bg | #e0e0e0 on #1a1a1a — passes WCAG AA |
Source |
| A6 | Color contrast: accent on bg | #4fc3f7 on #222 — passes WCAG AA |
Source |
| A7 | Alt text on Tone3000 thumbnails | alt="" (decorative) — acceptable |
Source |
| A8 | ARIA labels on toggle buttons | No ARIA — buttons have text content (ON/OFF) so passable | Source |
| A9 | Form labels associated with inputs | File inputs have no explicit <label> — just adjacent text |
Source |
8. React SPA-Specific Tests (if mounted at root)
The React SPA at src/web/ui-dist/ replaces the legacy dashboard at /.
| # | Test | Action | Expected | Method |
|---|---|---|---|---|
| SPA1 | SPA loads at root | GET / |
Returns React SPA index.html (not legacy dashboard) |
Browser |
| SPA2 | Fallback if no ui-dist | Delete ui-dist dir, restart | Falls back to legacy dashboard at / |
Browser |
| SPA3 | SPA navigation | Click through the SPA | Client-side routing, no full page reloads | Browser |
| SPA4 | SPA ↔ legacy pages | Navigate from SPA root to /presets |
Full page navigation to legacy page — smooth transition? | Browser |
| SPA5 | Favicon loads | Check browser tab icon | SVG favicon at /ui/favicon.svg |
Browser |
| SPA6 | JS bundle errors | Open browser console on SPA | No console errors, no uncaught exceptions | Browser |
9. Key UX Observations from Source Code (Pre-Findings)
These are issues visible from code review alone. Confirm in browser during execution.
| # | Observation | Heuristic | Source |
|---|---|---|---|
| O1 | FX type labels use block.fx_type.replace(/_/g, ' ') — simple replace, no proper label map. Some types may render with underscores if unmatched. |
H2 | presets.js:92 |
| O2 | WS preset_changed handler updates name/meta but doesn't re-render FX chain on dashboard. Block bypass states may visually lag. |
H1 | app.js:62-69 |
| O3 | toggle4cm() reads button state from DOM classList, not from server — race risk if another client or WS event flips state between read and POST. |
H5 | app.js:142-143 |
| O4 | No keyboard shortcut support (Ctrl+S for save, / for search). | H7 | Whole codebase |
| O5 | No undo for any action — delete is permanent after confirm. | H3 | presets.js:132 |
| O6 | Signal strength icons for WiFi use the same emoji for all levels (📶 — same Unicode codepoint, different on each platform). |
H8 | network.js:83-88 |
| O7 | SN: signal icon 📶 vs 📶 — same char repeated, 4 levels collapse to same visual. |
H8 | network.js:23-26 |
| O8 | BT scan timeout (12s) displayed to user — good. No cancel option on scan. | H3 + H1 | bluetooth.js:72 |
| O9 | No feedback when JACK restarts during profile switch — audio dropout with no visual indicator. | H1 | server.py:1402-1443 |
| O10 | Volume slider on Dashboard and Settings page both update via REST per oninput — may cause excessive API calls during drag. |
H7 | app.js:227-230 |
| O11 | Connection status _handlers check (pedalWS._handlers ? '1' : '0') looks for handler registration, not actual WS count. |
H1 | app.js:261 |
10. Pre-Completion Checklist
Before marking a section complete, verify:
- Browser tested: each test executed and result recorded
- JS console checked for errors after each interaction
- WS messages confirmed where applicable (via browser console:
pedalWS._handlers) - Responsive view tested for mobile flows (R1-R9)
- Code findings (O1-O11) confirmed in live browser session
- Screenshots captured for visual issues (use
browser_vision) - Cross-device sync tested for at least one flow (WS1)
11. Test Annotation Legend
| Symbol | Meaning |
|---|---|
| ✅ | Passes — expected behavior confirmed |
| ❌ | Fails — bug discovered (create Gitea issue) |
| ⚠️ | Non-critical / minor friction (note in recommendations) |
| ⏭️ | Skipped — explain why (e.g., "no pedal hardware connected") |
| 🔄 | Needs retest after fix |
Generated by Hermes Agent UX Review Skill — based on Nielsen's 10 Usability Heuristics and ux-review methodology.