@yappr/core
v0.1.1
Published
Headless reliability layer for Yappr realtime chat — optimistic send, reconnect, backfill, unread. Framework-agnostic.
Readme
@yappr/core
The headless reliability layer for Yappr realtime chat. Framework-agnostic, zero-dependency, useSyncExternalStore-shaped (subscribe + getSnapshot).
It handles the hard parts of a chat client for you: optimistic send with an outbox + retry/dedupe, reconnect with backoff, ?since backfill + loadOlder() pagination, and server-synced unread counts — over a single WebSocket to your Yappr server.
Using React? Install
@yappr/reactinstead — it's a thin binding over this package with auseChannelhook. Use@yappr/coredirectly for other frameworks (Vue, Svelte, vanilla) or custom integrations.
Install
npm install @yappr/coreQuickstart
import { createClient } from "@yappr/core";
const client = createClient({
// url defaults to wss://api.yappr.sh — override for self-host/local
tenantId: "t_xxx", // your tenant id
key: "pk_live_xxx", // your publishable key (browser-safe)
userId: "alice",
token: yapprToken, // short-lived JWT minted by YOUR backend (see Auth)
});
const channel = client.channel("room1");
// It's a store: subscribe to changes, read the current snapshot.
const unsubscribe = channel.subscribe(() => {
const { messages, status, unreadCount, hasOlder } = channel.getSnapshot();
render(messages, status, unreadCount);
});
channel.send("hello"); // optimistic — appears immediately, retries on failure
await channel.loadOlder(); // paginate backwards
channel.markRead(seq); // advance the read cursor
// later
unsubscribe();
client.close();Auth
The publishable key (pk_live_…) identifies your tenant and is safe to ship in the browser. To prove who the end-user is, your backend mints a short-lived JWT signed with your tenant secret — the secret never reaches the client. Use @yappr/server-node's mintToken on your server, then pass the result as token.
For local prototyping you can use a pk_test_… key (self-asserted identity, no backend, not for production).
API
createClient(config)→YapprClientconfig:{ url?, tenantId, key, userId, displayName?, token?, storage? }(urldefaults towss://api.yappr.sh)
client.channel(channelId)→ChannelHandleclient.close()ChannelHandle:subscribe(listener) => unsubscribegetSnapshot()→{ messages, status, unreadCount, hasOlder }send(content)·loadOlder()·markRead(seq)·close()
