# TimePlot TimePlot is now a clean restart: a small PixiJS time-series sandbox built around a simple state core, a pluggable data source layer, and toggleable UI panels. ## What it does - Real-time scrolling plot with PixiJS - Pause/resume plot time - Adjustable playback speed - Current real-time and plot-time labels - Hover tooltip for data points - Modular synthetic data input system - CSV replay sources - WebSocket live sources - Persisted workspace settings - Toggleable side panels for status, source config, app config, and help ## Getting started ```bash bun install bun run dev ``` Production build: ```bash bun run build bun run preview ``` Demo WebSocket source: ```bash bun run ws:demo ``` ## Controls - `Space` — pause/resume - `[` — slow down playback - `]` — speed up playback - `G` — toggle grid - Hover plot — inspect nearest sample ## Demo data Sample CSV replay files are included in [public/demo-data](public/demo-data): - [public/demo-data/telemetry-sweep.csv](public/demo-data/telemetry-sweep.csv) - [public/demo-data/chirp-ramp.csv](public/demo-data/chirp-ramp.csv) - [public/demo-data/step-bursts.csv](public/demo-data/step-bursts.csv) Use the `CSV replay` source type in the sidebar and upload one of those files. ## WebSocket source TimePlot includes a local demo WebSocket server in [scripts/demo-websocket-server.mjs](scripts/demo-websocket-server.mjs). Start it with: ```bash bun run ws:demo ``` Then set a signal source to `WebSocket` and use `ws://localhost:8080`. Optional environment variables: ```bash PORT=8090 TIMEPLOT_PROFILE=chirp TIMEPLOT_INTERVAL_MS=50 bun run ws:demo ``` Supported demo profiles: - `telemetry` - `chirp` - `steps` - `burst` Protocol details and accepted message formats are documented in [WEBSOCKET_FORMAT.md](WEBSOCKET_FORMAT.md). ## Persistence TimePlot persists core workspace settings in `localStorage`, including: - plot display settings - playback speed - panel visibility - graph routing and transforms - source configuration such as presets and WebSocket URLs CSV replay files themselves are not persisted in storage. After a reload, TimePlot remembers which CSV file was selected but asks you to reload the file data. ## Project structure ```text src/ ├── app/ │ └── create-app.js # application composition root ├── core/ │ ├── event-bus.js # lightweight pub/sub │ ├── store.js # centralized app state │ └── time-controller.js # real time + plot time transport ├── data/ │ ├── base-source.js # source interface │ ├── csv-replay-source.js │ ├── parse-replay-csv.js │ ├── source-registry.js # source lifecycle + routing │ ├── synthetic-wave-source.js │ └── websocket-source.js ├── plot/ │ ├── plot-buffer.js # bounded in-memory sample history │ └── timeplot-view.js # Pixi rendering + hover picking ├── ui/ │ └── panel-manager.js # DOM shell, controls, panels, tooltip ├── bootstrap.js # startup entry ├── main.js # compatibility shim to bootstrap ├── styles.css # global UI styling └── utils-format.js # display formatting helpers public/ └── demo-data/ # sample CSV replay fixtures scripts/ └── demo-websocket-server.mjs ``` ## Design direction This restart intentionally optimizes for a strong foundation instead of feature sprawl: - transport and time are first-class systems - data generation is isolated from rendering - the plot owns visualization only - DOM panels handle controls and diagnostics - app composition happens in one predictable bootstrap path - synthetic, file replay, and WebSocket sources share one source abstraction - core workspace configuration survives reloads ## Next good additions - richer external data sources (REST replay, binary streams, custom adapters) - richer panel layout system with docking/persistence - plot annotations and multiple stacked plots - configurable schemas for incoming data types - persistent user settings