This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
npm run dev- Start development server (localhost:5173)npm run build- Type-check and build for productionnpm run typecheck- Run TypeScript checking without buildnpm run lint- Run ESLint code quality checksnpm test- Run Vitest test suitenpm run preview- Preview production build locally
This is a real-time serial data plotting application built on a ring buffer + windowing architecture for high-performance data visualization. The core pattern separates data ingestion, storage, windowing, and rendering into distinct layers.
- Serial Input (
useSerial) → Line parsing → RingStore.append() - RingStore maintains fixed-capacity ring buffers per data series
- Windowing System provides efficient data slices via
getWindow({ startFromNewest, length }) - Canvas Renderer draws from windowed snapshots with 60 FPS performance
- Core Concept: Fixed-memory ring buffer that never grows, preventing memory bloat during long data sessions
- Windowing:
getWindow()returns contiguous views without copying data - critical for performance - Freeze Behavior: Uses
totalcounter to anchor frozen views while live data continues appending - Anchors: Precomputed time indices for efficient X-axis labeling
- Performance: Device pixel ratio aware, ResizeObserver-based sizing, requestAnimationFrame drawing
- Interaction Model: Sophisticated pointer/touch handling with momentum scrolling and pinch zoom
- Theme Integration: Redraws on CSS class changes for seamless dark/light mode
The app manages multiple coordinate spaces that can be confusing:
- UI Coordinates: User scroll/window inputs (scrollOffsetInput, windowSizeInput)
- Data Coordinates: Ring buffer indices (
startFromNewestin getWindow calls) - Freeze Coordinates: Delta calculation between current total and freeze base
- Canvas Coordinates: Pixel positions for rendering
Use utilities in src/utils/coordinates.ts for transformations between these spaces.
- External Store Pattern: Uses
useSyncExternalStorewith RingStore for efficient React integration - No Redux/Zustand: Simple context provider with ref-based singleton store
- Performance: Store updates trigger minimal re-renders via precise subscriptions
- Momentum Scrolling: Physics-based deceleration after pan gestures (
useMomentumScrolling) - Zoom Controls: Center-point preserving zoom with coordinate transformation (
useZoomControls) - Freeze System: Allows historical data exploration while live data continues
The app uses the Web Serial API for direct browser-to-device communication:
- Parser: Newline-delimited text with CSV/space/tab separation
- Headers: Lines starting with
#define series names - Error Handling: Graceful degradation for unsupported browsers
- Stream Management: Proper TextDecoderStream usage with cleanup
- Ring buffers prevent unbounded growth during long sessions
- TypedArrays (Float32Array/Float64Array) for numerical data storage
- Windowing system avoids copying large datasets
- Canvas rendering with proper DPR scaling
- Clipped drawing to prevent overdraw artifacts
- Theme-aware redraw triggers via MutationObserver
- O(1) append operations regardless of buffer size
- Non-blocking data parsing with proper error handling
- Configurable history capacity (default 12K samples)
Recent refactoring extracted complex logic into focused hooks:
useZoomControls- All zoom math with center-point preservationuseMomentumScrolling- Physics simulation for smooth pan interactionsuseSerial- Web Serial API lifecycle management
- Compound Components: StatsPanel with individual exportable cards
- Overlay System: Legend and tools as absolute positioned overlays
- Theme Integration: CSS custom properties with Tailwind dark: variants
PlotCanvas uses forwardRef with imperative handle for PNG export functionality. The component separates concerns:
- Drawing Logic: Pure functions in
src/utils/plotRendering.ts - Interaction Logic: Event handling utilities in
src/utils/canvasInteractions.ts - Coordinate Math: Transformation utilities in
src/utils/coordinates.ts
- Unit Tests: Focus on core data structures (RingStore) using Vitest
- No E2E: Serial API requires hardware; use built-in signal generator for testing UI
- Test Location:
src/store/__tests__/follows co-location pattern
- Web Serial API: Chrome/Edge only (89+), no Firefox/Safari support
- Graceful Degradation: Clear messaging for unsupported browsers
- Built-in Testing: Signal generator provides hardware-free development
- 60 FPS: Smooth rendering during high-frequency data streams
- Memory Bound: Fixed memory usage regardless of session length
- Responsive: Sub-100ms interaction response times
Uses manual Tailwind dark mode with custom variant:
- Toggle via
darkclass ondocument.documentElement - Canvas redraws automatically on theme changes
- CSS custom properties for plot-specific colors (
--plot-bg,--plot-grid)