A production-ready React library for consuming real-time telemetry data through WebSocket connections. Built for SCADA systems, IoT dashboards, and industrial monitoring applications.
The library is published to npm and can be installed in any React project:
npm install scadableRequirements:
- React 18.0.0 or higher
- React DOM 18.0.0 or higher
The fastest way to visualize real-time data:
import { LiveTelemetryLineChart } from 'scadable';
function App() {
return (
<LiveTelemetryLineChart
apiKey="your-api-key"
deviceId="your-device-id"
title="Temperature Monitor"
xAxisLabel="Time"
yAxisLabel="Temperature (°C)"
xDataPath=".timestamp"
yDataPath=".data.temperature"
yMin={0}
yMax={50}
lineColor="#8884d8"
/>
);
}For custom implementations with full control:
import { Facility, Device, useLiveTelemetry } from 'scadable';
const facility = new Facility("your-api-key");
const device = new Device(facility, "your-device-id");
function App() {
const { telemetry, isConnected, error } = useLiveTelemetry(device);
return (
<div>
<h1>Status: {isConnected ? 'Connected' : 'Disconnected'}</h1>
{error && <p>Error: {error}</p>}
{telemetry && <pre>{JSON.stringify(telemetry, null, 2)}</pre>}
</div>
);
}- 📊 Real-Time Visualization: Live line charts with smooth scrolling data
- 🔌 WebSocket Integration: Automatic connection management and reconnection
- ⚛️ React Hooks: Simple
useLiveTelemetryhook for custom implementations - 🛡️ TypeScript Support: Full type safety with comprehensive definitions
- 🎨 Customizable Charts: Configurable colors, scales, and dimensions
- 🧪 Production Ready: Comprehensive tests and error handling
- 📱 Framework Agnostic: Works with Next.js, Create React App, Vite, and more
Manages API authentication for WebSocket connections.
import { Facility } from 'scadable';
const facility = new Facility("your-api-key");Methods:
connect(deviceId: string): WebSocket- Creates a WebSocket connectionisValid(): boolean- Validates the API key
Manages device connections and message handling.
import { Facility, Device } from 'scadable';
const facility = new Facility("your-api-key");
const device = new Device(facility, "device-id");
// Connect to WebSocket
device.connect();
// Subscribe to messages
device.onMessage((data) => console.log(data));
// Handle errors
device.onError((error) => console.error(error));
// Monitor connection status
device.onStatusChange((status) => console.log(status));
// Disconnect when done
device.disconnect();Methods:
connect()- Establishes WebSocket connectiondisconnect()- Closes WebSocket connectiononMessage(handler)- Subscribe to telemetry messagesonError(handler)- Subscribe to connection errorsonStatusChange(handler)- Subscribe to connection status changesgetConnectionStatus()- Get current connection statusisConnected()- Check if currently connected
React hook for consuming real-time telemetry data with automatic lifecycle management.
import { useLiveTelemetry } from 'scadable';
const { telemetry, isConnected, error } = useLiveTelemetry(device);Returns:
telemetry- Latest telemetry data receivedisConnected- Connection status (boolean)error- Error message if connection fails
Ready-to-use real-time line chart component.
import { LiveTelemetryLineChart } from 'scadable';
<LiveTelemetryLineChart
apiKey="your-api-key" // API key for authentication
deviceId="your-device-id" // Device ID to connect to
title="Temperature Monitor" // Chart title
xAxisLabel="Time" // X-axis label
yAxisLabel="Temperature (°C)" // Y-axis label
xDataPath=".timestamp" // JSON path to X value
yDataPath=".data.temperature" // JSON path to Y value
yMin={0} // Minimum Y-axis value
yMax={50} // Maximum Y-axis value
lineColor="#8884d8" // Optional: line color
maxDataPoints={20} // Optional: max data points
width={600} // Optional: chart width
height={400} // Optional: chart height
/>- LiveTelemetryLineChart Documentation - Complete guide to the chart component
- useLiveTelemetry Hook Documentation - Advanced hook usage and patterns
- NPM Package: https://www.npmjs.com/package/scadable
- GitHub Repository: https://github.com/scadable/library-react
- Live Examples: Run
npm run storybooklocally to see interactive examples
'use client';
import { LiveTelemetryLineChart } from 'scadable';
export default function DashboardPage() {
return (
<LiveTelemetryLineChart
apiKey={process.env.NEXT_PUBLIC_SCADABLE_API_KEY}
deviceId="sensor-001"
title="Temperature Monitor"
xAxisLabel="Time"
yAxisLabel="Temperature (°C)"
xDataPath=".timestamp"
yDataPath=".data.temperature"
yMin={0}
yMax={50}
/>
);
}import { LiveTelemetryLineChart } from 'scadable';
function App() {
return (
<div className="App">
<LiveTelemetryLineChart
apiKey={process.env.REACT_APP_SCADABLE_API_KEY}
deviceId="sensor-001"
title="Temperature Monitor"
xAxisLabel="Time"
yAxisLabel="Temperature (°C)"
xDataPath=".timestamp"
yDataPath=".data.temperature"
yMin={0}
yMax={50}
/>
</div>
);
}import { LiveTelemetryLineChart } from 'scadable';
function App() {
return (
<LiveTelemetryLineChart
apiKey={import.meta.env.VITE_SCADABLE_API_KEY}
deviceId="sensor-001"
title="Temperature Monitor"
xAxisLabel="Time"
yAxisLabel="Temperature (°C)"
xDataPath=".timestamp"
yDataPath=".data.temperature"
yMin={0}
yMax={50}
/>
);
}function Dashboard() {
return (
<div>
<LiveTelemetryLineChart
apiKey="your-api-key"
deviceId="temp-sensor-1"
title="Temperature Sensor 1"
xAxisLabel="Time"
yAxisLabel="°C"
xDataPath=".timestamp"
yDataPath=".data.temperature"
yMin={0}
yMax={50}
lineColor="#ef4444"
/>
<LiveTelemetryLineChart
apiKey="your-api-key"
deviceId="pressure-sensor-1"
title="Pressure Sensor 1"
xAxisLabel="Time"
yAxisLabel="PSI"
xDataPath=".timestamp"
yDataPath=".data.pressure"
yMin={0}
yMax={150}
lineColor="#22c55e"
/>
</div>
);
}function CustomTelemetryDisplay() {
const facility = new Facility("your-api-key");
const device = new Device(facility, "your-device-id");
const { telemetry, isConnected, error } = useLiveTelemetry(device);
return (
<div className="custom-display">
<div className="status-bar">
<span className={isConnected ? 'connected' : 'disconnected'}>
{isConnected ? '🟢 Live' : '🔴 Offline'}
</span>
</div>
{error && <div className="error">{error}</div>}
{telemetry && (
<div className="telemetry-data">
<h2>Temperature: {telemetry.data?.temperature}°C</h2>
<p>Last Updated: {telemetry.timestamp}</p>
</div>
)}
</div>
);
}If you're experiencing connection problems:
- Verify API Key: Ensure your API key is valid
- Check Device ID: Confirm the device ID exists in your system
- Network: Verify WebSocket connections aren't blocked by firewall
- Browser Console: Check for error messages in the developer console
- Verify JSON Paths: Ensure
xDataPathandyDataPathmatch your data structure - Check Y-axis Range: Make sure
yMinandyMaxencompass your data values - Inspect WebSocket Messages: Use browser DevTools to inspect WebSocket traffic
Ensure you have the latest type definitions:
npm install --save-dev @types/react @types/react-dom- Node.js: v20 or higher
- npm: v8 or higher
- Git: Latest version
-
Clone the repository:
git clone https://github.com/scadable/library-react.git cd library-react -
Install dependencies:
npm install
-
Run Storybook (interactive development environment):
npm run storybook
This opens at
http://localhost:6006with live component examples. -
Run tests:
npm run test # Watch mode npm run test:stories:ci # CI mode
-
Build the library:
npm run build
┌─────────────────────────────────────────────────────────┐
│ User's React Application │
│ (Next.js / Create React App / Vite) │
└────────────────────┬────────────────────────────────────┘
│ npm install scadable
▼
┌─────────────────────────────────────────────────────────┐
│ Scadable React Library │
│ │
│ ┌──────────────┐ ┌────────────┐ ┌────────────────┐ │
│ │ Components │ │ Hooks │ │ Core Classes │ │
│ │ │ │ │ │ │ │
│ │ • LiveChart │ │ • useLive │ │ • Facility │ │
│ │ │ │ Telemetry│ │ • Device │ │
│ └──────┬───────┘ └─────┬──────┘ └────────┬───────┘ │
│ │ │ │ │
│ └────────────────┴───────────────────┘ │
│ │ │
│ ┌────────▼─────────┐ │
│ │ WebSocket │ │
│ │ Connection │ │
│ └────────┬─────────┘ │
└──────────────────────────┼──────────────────────────────┘
│ wss://
▼
┌──────────────────────┐
│ Scadable Backend │
│ WebSocket Server │
└──────────────────────┘
library-react/
├── src/
│ ├── core/ # Core business logic
│ │ ├── Facility.ts # API key & authentication
│ │ ├── Device.ts # WebSocket connection management
│ │ └── types.ts # TypeScript definitions
│ │
│ ├── hooks/ # React hooks
│ │ └── useLiveTelemetry.ts # Main telemetry hook
│ │
│ ├── components/ # React components
│ │ ├── LiveTelemetryLineChart.tsx
│ │ ├── LiveTelemetryLineChart.stories.tsx
│ │ └── TelemetryDisplay.tsx
│ │
│ ├── utils/ # Utilities
│ │ ├── jsonPath.ts # JSON path extraction
│ │ └── parseMessage.ts # Message parsing
│ │
│ └── index.ts # Public API exports
│
├── __tests__/ # Test files
├── docs/ # Component documentation
├── .storybook/ # Storybook config
├── .github/workflows/ # CI/CD pipelines
├── dist/ # Build output (generated)
├── package.json
├── vite.config.ts # Build configuration
└── tsconfig.json # TypeScript config
LiveTelemetryLineChart
↓
useLiveTelemetry Hook
↓
Device Class (WebSocket management)
↓
Facility Class (Authentication)
↓
WebSocket Connection
↓
Backend Server
1. User creates component with apiKey + deviceId
↓
2. Facility validates API key
↓
3. Device establishes WebSocket connection
↓
4. useLiveTelemetry hook:
• Connects on mount
• Subscribes to messages
• Updates React state
• Cleans up on unmount
↓
5. Backend sends WebSocket message
↓
6. parseMessage() validates JSON
↓
7. Hook updates state → Component re-renders
↓
8. jsonPath extracts X/Y values → Chart renders
| Technology | Version | Purpose |
|---|---|---|
| React | ^19.1.1 | UI framework (peer dependency) |
| TypeScript | Latest | Type safety |
| Vite | ^6.3.6 | Build tool and bundler |
| Vitest | ^3.2.4 | Testing framework |
| Recharts | ^3.3.0 | Chart visualization |
| Tool | Purpose |
|---|---|
| Storybook | Interactive component development |
| ESLint | Code linting |
| Testing Library | React testing utilities |
| vite-plugin-dts | TypeScript declarations |
The library builds to three formats:
- CommonJS:
dist/index.js(older bundlers) - ES Modules:
dist/index.mjs(modern bundlers) - TypeScript:
dist/index.d.ts(type definitions)
# Unit tests (watch mode)
npm run test
# Storybook interaction tests
npm run test:stories
# CI mode (all tests)
npm run test:stories:ciTests cover:
- Component rendering
- WebSocket lifecycle (connect, disconnect, reconnect)
- Error handling
- Data parsing and extraction
- Hook behavior
npm run buildOutput in dist/ directory:
index.js(CommonJS)index.mjs(ES Modules)index.d.ts(TypeScript types)
npm version patch # Bug fixes (1.0.0 → 1.0.1)
npm version minor # New features (1.0.0 → 1.1.0)
npm version major # Breaking changes (1.0.0 → 2.0.0)Automated via GitHub Actions:
-
Create a GitHub Release:
- Tag:
v1.0.11(match package.json version) - Title: Same as tag
- Description: Release notes
- Tag:
-
GitHub Actions automatically:
- Runs tests
- Builds package
- Publishes to npm
-
Verify:
npm view scadable version
Runs on every push and pull request:
Steps:
1. Checkout code
2. Setup Node.js 20
3. Install dependencies (npm ci)
4. Lint code
5. Run tests
6. Build packageRuns when GitHub release is created:
Steps:
1. Checkout code
2. Setup Node.js with npm registry
3. Install dependencies
4. Build package
5. Publish to npm (with provenance)NPM_TOKEN: npm authentication token with publish permissions
Create GitHub Release
↓
Trigger GitHub Actions
↓
Run CI checks (lint, test, build)
↓
Build succeeds?
↙ ↘
Yes No
↓ ↓
Publish Fail
↓
npm updated
- NPM: https://www.npmjs.com/package/scadable
- Install:
npm install scadable
- GitHub: https://github.com/scadable/library-react
- Issues: GitHub Issues
- Storybook: Run
npm run storybooklocally
- Package Registry: npm (public)
- CI/CD: GitHub Actions
- Version Control: GitHub
- Fork the repository
- Clone your fork locally
- Create a feature branch:
git checkout -b feature/my-feature
- Make changes with clear commits:
git commit -m "feat: add new feature" - Test your changes:
npm run test npm run build - Push and create a pull request
Follow conventional commits:
feat:New featurefix:Bug fixdocs:Documentationtest:Testschore:Maintenancerefactor:Code refactoring
- Automated CI checks must pass
- At least one maintainer review
- Address feedback
- Merge when approved
rm -rf node_modules package-lock.json
npm install
npm run storybooknpx tsc --noEmit # Check TypeScript errors
rm -rf dist
npm run buildnpm run test -- --reporter=verboseISC License - See LICENSE file for details
- Issues: GitHub Issues
- Questions: Open a discussion on GitHub