The session detail page (a server component) was importing STATUS_VARIANT
from SessionsTable.tsx, a "use client" file. Next.js compiles client
modules separately for the server and client bundles, and pulling a plain
value (not a component) across that boundary let the two compiler caches
drift out of sync in dev, so the same session status could render a
different Badge color depending on which page rendered it. Moved the
constant into its own plain module that both files import.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WzyfRyA7h5rs5SCAahLAWd
Reuses SessionsTable's STATUS_VARIANT mapping (now exported) so the
detail page's status matches the table's badge instead of plain text.
Also drops the now-stale px-1.5 alignment padding on the meta lines
now that the title input carries no horizontal padding of its own.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WzyfRyA7h5rs5SCAahLAWd
Recordings were just a thin named pointer over an already-captured
session's events, so the whole separate feature (recordings table, API
routes, pages, UI) is gone: any completed session can now be named and
replayed directly. Replaying no longer creates a session or duplicates
events of its own - it just bumps the source session's playCount/lastPlayedAt.
Also renames play_sessions/playSession(s) to sessions/session(s) throughout
the schema, queries, API routes, and UI for consistency, and updates the
README to match the new flow.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- 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>
Adds a pink/purple/blue SVG brand mark (favicon + header) and reworks
the visual language around the app's actual interaction - fader-driven
device control - via LED-style indicators, mono instrument readouts,
hairline-framed cards, console-tab nav, and an oscilloscope-style
session timeline. Leaves components/ui/* untouched, restyling only via
design tokens and the app's own composed components. Also fixes a
proxy.ts matcher gap that was gating /icon.svg behind auth.
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