@socketly/client
v0.1.1
Published
Browser client for Socketly — realtime channels, presence, and reconnect handling with no setup.
Maintainers
Readme
@socketly/client
Realtime channels in the browser. Connect with a public key, subscribe, and receive events — no server to run, no adapter to configure.
npm install @socketly/clientConnect
import { Socketly } from '@socketly/client';
const socketly = new Socketly({
key: process.env.NEXT_PUBLIC_SOCKETLY_KEY!, // pk_app_…
});
const channel = socketly.subscribe('public-status');
channel.bind('deployed', ({ data }) => {
console.log(data.version, 'is live');
});The public key is safe in a browser — that is what it is for. It can subscribe to public channels and nothing else. Anything private needs a signature from your backend, which is the next section.
Private and presence channels
A channel name's prefix decides its rules:
| Prefix | Who can subscribe |
|---|---|
| public- | anyone with the public key |
| private- | only with a signature from your server |
| presence- | same, plus a signed identity that appears in the roster |
For the last two, point the client at an endpoint on your own backend:
const socketly = new Socketly({
key: process.env.NEXT_PUBLIC_SOCKETLY_KEY!,
authEndpoint: '/api/socketly/auth',
});The client posts { socket_id, channel_name } there whenever it needs authorization. Your endpoint decides whether that user may subscribe — you already know who they are — and signs the answer with @socketly/server. Your secret key never leaves your server, and we never need to know your user model.
The signature is bound to the socket id, so it cannot be replayed on a different connection.
Reconnects
Every subscription is replayed on reconnect, and each private channel is re-authorized against the new socket id. You do not resubscribe by hand, and a signature from the old connection is never reused.
socketly.onStateChange((state) => {
// 'initialized' | 'connecting' | 'connected' | 'reconnecting' | 'disconnected' | 'failed'
});Presence
const channel = socketly.subscribe('presence-room-42');
channel.bind('socketly:subscription_succeeded', () => {
console.log(channel.members.toArray()); // [{ userId, userInfo }]
});
channel.bind('socketly:member_added', (member) => { /* … */ });
channel.bind('socketly:member_removed', (member) => { /* … */ });The identity in the roster comes from inside the signed payload, so a client cannot claim to be someone else.
Client events
Browser-to-browser events, for things like typing indicators that are not worth a round trip through your backend. They must be enabled on the app, are only allowed on private-/presence- channels, and their names must start with client-.
socketly.trigger('presence-room-42', 'client-typing', { userId });Options
| Option | Default | |
|---|---|---|
| key | — | required, pk_app_… |
| url | https://api.socketly.co | point at a local gateway in development |
| authEndpoint | — | required for private-/presence- |
| authHeaders | — | object, or a function called per request |
| autoConnect | true | set false to call connect() yourself |
| reconnection | true | |
| debug | false | logs protocol activity to the console |
React
@socketly/react wraps this in useChannel and usePresence.
Full documentation: docs.socketly.co
MIT
