@xorgate/react
v0.4.2
Published
Headless React SDK for the xorgate platform: data hooks, live telemetry over MQTT, live video over WebRTC, and the recorded-media replay player.
Maintainers
Readme
@xorgate/react
The headless React SDK for the xorgate platform: data
hooks over @xorgate/sdk, live
telemetry over MQTT-over-WebSocket, live video over WebRTC, and the
recorded-media replay player with video and telemetry on one synced timeline.
Headless means headless: hooks return state and refs; you render. Two
components ship (LiveVideo, ReplayVideo) and each is a hook plus a bare
<video> element.
Full reference: docs.xorgate.io/docs/frontend-sdk
Install
npm install @xorgate/react @xorgate/sdk reactreact (^18.2 || ^19) is the only peer. @xorgate/sdk is a hard dependency
on purpose: one resolved copy is what makes import type { Device } from
either package the identical type, and instanceof XorgateError true across
the boundary. ESM only, browser only, types bundled.
Use
import { XorgateProvider, useDevices, useLiveTelemetry } from "@xorgate/react"
function App() {
return (
<XorgateProvider
auth={{ getSessionToken: () => myBackend.getXorgateSessionToken() }}
organizationId={orgId}
>
<Fleet />
</XorgateProvider>
)
}
function Fleet() {
const { data: devices, isLoading } = useDevices({ status: "online" })
if (isLoading) return <p>Loading…</p>
return devices?.map((d) => <DeviceRow key={d.id} device={d} />)
}Auth modes
{ getSessionToken }— the third-party default. Your server exchanges its API key for a short-livedxgs_token; the SDK authenticates REST with it and exchanges it for live-plane credentials itself. Config collapses to nothing (baseUrldefaults to production).{ getLiveCredentials }— the fully proxied profile. Your backend holds the key, serves all REST to your own frontend, and vends live credentials viaPOST /auth/live-credentials; hand the response to this callback verbatim and the browser touches no xorgate REST endpoint at all. Live hooks and the replay player are the whole surface in this mode.{ getIdToken }— first-party Cognito, for xorgate's own dashboard.{ apiKey }— REST only, for React rendered on a server you control. A key in a browser bundle is a published key.
What you get
- One metric contract. Live MQTT,
useTelemetryLatestand replayed telemetry all produceRecord<"group.field", LatestReading>, so one readout component renders all three without knowing which it has. - One socket per device. Live telemetry consumers share a ref-counted MQTT connection; mounting the hook in five components costs one socket.
- Reconnect machinery that survived real LTE devices. Generation counters, per-step and whole-attempt deadlines, an ICE disconnect grace window, backoff, a proactive credential cycle and mobile visibility nudges, on both live planes.
- A replay player with one wall clock. Video elements pace the clock; telemetry resolves at the playhead; drift between them is structurally impossible rather than merely small. fMP4 over MSE, gap-aware, with presigned-URL refresh that never resets the clock.
- Recorded telemetry straight from S3. When the replay manifest carries
its
telemetryblock (API 0.9.0),useReplayTelemetryreads one presigned overview object per telemetry session for the route line and the scrub preview, and the device's own 60 s segments for the readouts around the playhead: no REST call, no Lambda, no database on the replay's hot path. Segments are immutable and cached by S3 key, so a seek back into ground already visited fetches nothing, and a still-recording session grows as the manifest re-polls every 60 s. Without the block (an older server,telemetry: false) the REST history routes serve it as before. - A small bundle for pages that need none of that. Every live dependency (mqtt, the KVS and Cognito clients) sits behind a dynamic import; a page that only lists devices ships a few kB of this package and zero AWS code.
- A live plane that notices when the device moves. A vended credential
encodes org + workspace and is cached for up to ~50 minutes, so a device
transferred to another workspace leaves a viewer connected to a topic nothing
will publish to again — silence, no error.
useDeviceScope(deviceId)turns that into a typedDEVICE_OUT_OF_SCOPE, re-vending once first since the usual cause is just a stale credential, anduseLiveScope().invalidate()makes every open live consumer re-resolve after you transfer a device yourself.
Platforms
Everything that touches the host runtime goes through one optional
platform prop on XorgateProvider, and every slot defaults to the browser,
so a web app never passes it:
<XorgateProvider auth={auth} organizationId={orgId} platform={nativePlatform()}>XorgatePlatform has four slots: createWebRtcPlatform (the KVS viewer's
WebRTC), subscribeWake (foreground / network-back events that nudge the
live planes and refetchOnFocus), mqttConnect (the MQTT transport) and
randomId (client-id entropy). React Native consumers install
@xorgate/react-native,
which supplies all four plus useLiveVideo over RTCView and the replay
player over expo-video. Adapter authors build on useLiveVideoSession,
useReplayPlayerCore + attachLane, ReplayEngine and
createWebRtcPlatform(overrides); the browser hooks are thin wrappers over
the same cores.
License
MIT © Epye Labs
