Liveflux
Turn a live connection — WebSocket, SSE, Socket.IO, Phoenix Channels, any push transport — into typed, reconnect-safe UI state. You describe the channel and how its events fold; Liveflux owns the sockets, cache glue, dedup, backpressure, and reconnect logic.
Scaffolds the client and installs the packages for your framework and transport.
A live, keyed list of trades — the whole component, and it running:
import { useStream } from '@liveflux/react';
type Trade = { id: number; symbol: string; price: number };
export function Trades() {
// upsert → Trade[]: a matching id updates in place, a new id is appended.
const trades = useStream<Trade>({
channel: 'trades',
into: { strategy: 'upsert', key: 'id', cap: 50 },
});
return trades.map((t) => <Row key={t.id} symbol={t.symbol} price={t.price} />);
}The wire subscription is multiplexed onto one connection, deduped, and re-sent after a reconnect — none of which you wrote.
The realtime plumbing it owns
A realtime feature looks small until you ship it. Liveflux is the layer that owns the parts you'd otherwise hand-roll every time — behind a small typed surface.
Reconnect-safe
On an unexpected close it backs off with jitter and replays every active subscription on the new connection — streams resume on their own.
One multiplexed connection
Many subscriptions share a single socket. Identical subscriptions fold once, ref-counted, and release only when the last subscriber leaves.
Cache-shaped state
Fold raw events into the shape your UI renders — append (log), upsert (keyed list), replace (latest), or your own reducer.
Backpressure
Adapters watch the send buffer and queue control frames past a high-water mark; oversized inbound frames are dropped before decoding.
Tear-free React
Reads go through useSyncExternalStore, so state is consistent under concurrent rendering. Pass a selector to re-render only on the slice you use.
Typed end-to-end
Generics flow from the channel through the fold strategy to the value your component receives — the return type follows the strategy.
Protocol- and framework-agnostic
One engine, swappable transports, per-framework bindings. Point it at a new backend by changing the adapter; the components don't move.
Core packages
The engine and the React binding — the two you always install. Add one adapter for your transport and you're set.
@liveflux/coreFramework-agnostic engine — connection, subscriptions, store, backpressure.
@liveflux/reactReact binding — the useStream hook + LivefluxProvider.
One core, five transports
Each adapter normalizes a different backend into the same stream. Same components, same useStream — you only swap the adapter.
WebSocket
@liveflux/wsAny plain-WebSocket backend, in any language.
Server-Sent Events
@liveflux/sseAn EventSource stream with reconnect and cursor resume.
Socket.IO
@liveflux/socketioWraps an existing Socket.IO client into a normalized stream.
GraphQL over WebSocket
@liveflux/graphql-wsgraphql-transport-ws subscriptions, zero-dependency.
Phoenix Channels
@liveflux/phoenixPhoenix Channels v2 — joins, rejoin backoff, heartbeat topic.
Wire up your first stream
Install three packages, drop in a provider, and call useStream. It's about a dozen lines.