Search the complete documentation

Try idempotency, proposal lifecycle, authentication, or ordering.

Navigate Open
繁體中文
Browse documentation

Relay · Client integration

SDK and widget

Relay provides a TypeScript core SDK, React bindings and UI, Vue composables, a script-tag widget, and a browser streaming renderer. Choose the thinnest layer that fits your product. Authentication, channel membership, and business authorization still belong to the host.

Distribution status

@tonetify/relay@0.1.0-beta.1 is published on npm under the beta tag. The package includes ESM, CommonJS, declarations, streaming styles, and an IIFE widget bundle. It is licensed under MIT and does not ship source maps.

Install the beta explicitly:

npm install @tonetify/relay@0.1.0-beta.1

Pin the exact beta version in production automation. The package is public, but Relay does not yet publish a server-to-SDK compatibility matrix or an upgrade policy.

Relay + Govern

The SDK transports the turn, Govern bounds the reply

Composed path

  1. Host

    Gets a scoped Relay session from Govern.

  2. Relay SDK

    Joins and sends the user message.

  3. Govern

    Handles message.created and chooses an effect.

  4. Relay

    Commits and delivers the resulting reply.

Core SDK

The host must provide a JWT, tenant ID, channel ID, and WebSocket URL. apiUrl is required only by REST convenience helpers such as reaction inspection and notification mute. userId lets those helpers derive viewer-specific state.

import { ChatClient } from "@tonetify/relay";

const client = new ChatClient({
  url: "wss://relay.example.com/socket",
  apiUrl: "https://relay.example.com",
  token,
  userId
});

client.connect();

const channel = client.channel(channelId, tenantId);

channel.on("msg:new", (message) => {
  console.log(message.seq, message.body);
});

await channel.join();
await channel.send("Hello from Relay", {
  nonce: crypto.randomUUID()
});

Call connect() only in the browser. It throws during server-side rendering. Mount it in a React effect, Vue client scope, or equivalent browser lifecycle, and call disconnect() when the integration is disposed.

Stable core and preview surfaces

The contract-beta core covers:

  • join, leave, retry-safe send, and cursor updates;
  • stable presence_state, presence_diff, msg:new, catch_up:truncated, and unread_count events;
  • connection state and lifecycle events;
  • notification mute helpers.

ChatChannel also exposes edit, retract, pin, unpin, thread, reaction, and typing capabilities. These are preview surfaces. Their methods are usable, but the related WebSocket event names, payloads, and recovery behavior can change during contract beta.

channel.send() generates a nonce unless the caller supplies one. If the result is uncertain and the host retries, it must retain the original nonce. Calling send() again without that nonce creates a new logical send.

React integration

Use RelayWidget for a minimal conversation UI:

import { RelayWidget } from "@tonetify/relay/react";

export function SupportChat({ token }: { token: string }) {
  return (
    <RelayWidget
      url="wss://relay.example.com/socket"
      apiUrl="https://relay.example.com"
      token={token}
      userId="current-user-id"
      tenantId="tenant-uuid"
      channelId="channel-uuid"
      channelName="Support"
    />
  );
}

For a product-owned UI, compose ChatProvider, useChannel, useMessages, and usePresence, or use the core SDK directly. The React layer connects on mount, joins the requested channel, applies optimistic sends, and disconnects on unmount.

Script-tag widget

The build produces dist/tonetify-relay-widget.global.js. Host that exact artifact and mount it explicitly:

<div id="chat-root"></div>
<script src="/assets/tonetify-relay-widget.global.js"></script>
<script>
  window.TonetifyRelay.init({
    url: "wss://relay.example.com/socket",
    token: "host-signed-jwt",
    tenantId: "tenant-uuid",
    channelId: "channel-uuid",
    target: "#chat-root",
    mode: "shadow",
    theme: { primaryColor: "#3158d3" }
  });
</script>

mode accepts shadow or iframe. The iframe mode uses a same-document srcdoc; it is a styling boundary, not a cross-origin security boundary. The widget renders a minimal live timeline, presence status, connection errors, and message composer. It is not a complete support desk or moderation UI.

Calling TonetifyRelay.init() again destroys the previous singleton widget before mounting the next one.

Vue and streaming

@tonetify/relay/vue exports useChat, useChannel, useMessages, and usePresence. These composables are implemented and tested, but remain a preview integration surface. They may change before a published compatibility policy exists.

@tonetify/relay/streaming provides a browser-only renderer for progressively displaying text or Markdown, including bounded CJK tokenization. It affects presentation only. Relay still stores one final message body and does not expose a server streaming-message contract.

Recovery boundary

Phoenix reconnects the socket and rejoins channels, but the default React, Vue, and script widget stores are memory-only. A page reload loses the last known seq. The high-level bindings also do not persist or fully drain truncated catch-up windows.

For dependable history recovery, persist the newest confirmed seq, call channel.join(lastSeq), listen for catch_up:truncated, and fetch additional pages through the REST history contract. Do not claim offline storage or exactly-once client rendering from the current SDK.

The SDK does not yet include helpers for attachment upload, search, channel administration, user export, or tenant operations. Use the documented HTTP APIs for those surfaces.

Artifact verification

Before distributing a build, run:

cd sdk
npm run build
npm test
npm run typecheck
npm run pack:check

These commands prove the package can be built, typed, tested, and packed from the repository. The public 0.1.0-beta.1 artifact has also been read back from npm. This does not prove browser compatibility targets, server compatibility across versions, semantic-version support, or a managed upgrade service.

Related: Realtime and reconnect · Authentication · Relay overview