- Fix device rename input collapsing on mobile (fixed width vs w-full
inside an auto-layout table column).
- Add cascade-delete confirmation for sessions with a saved recording.
- Fix header connection LED: derive state from scanning/device-count/
recording instead of the Buttplug client's raw connected flag; drop
the label text and hide the indicator entirely when idle.
- Add a per-device disconnect button (stop + remove from store, the
closest equivalent Buttplug's protocol allows per device).
- Fix replay ending early: duration now comes from the recording's
actual durationMs, not the last event's timestamp.
- Replay robustness: show which devices are being replayed to, reset
actuators to zero on start/play/pause, fully disconnect devices and
the whole client on stop/unmount, surface command failures via toast.
- Stop flagging the header LED red during replay - recording is only
for live sessions.
- Add page-number pagination to recordings/sessions/devices lists.
- Wordmark SEXY -> Sexy; add proper per-page <title>s including
dynamic titles for recording/session detail and replay pages.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
getSessionTimeline() grouped/ordered by a bare `bucket` identifier,
assuming SQLite would resolve it against the SELECT list's alias -
it doesn't in this generated query, so every /sessions/:id page and
/api/stats/sessions/:id/timeline request failed with "no such column:
bucket". Fixed by reusing the actual bucket expression object in
groupBy/orderBy instead of referencing it by name. Verified against a
seeded session - previously every request, now correct bucketed data.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W8WkFF5ppURBAB918593Eb
Next.js app with a browser-side buttplug/buttplug-wasm control layer
(server never touches real-time device commands), SQLite storage via
Drizzle, single-secret auth, recordings/replay with device remapping,
a usage stats dashboard, Docker deployment, and Gitea CI.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W8WkFF5ppURBAB918593Eb