Broadcast Groups

Named groups with explicit membership, roles, metadata, and lifecycle hooks. Like topics but with access control - you decide who can join, what role they have, and what happens when the group fills up or closes.

Setup

// src/lib/server/lobby.js
import { createGroup } from 'svelte-adapter-uws/plugins/groups';

export const lobby = createGroup('lobby', {
  maxMembers: 50,
  meta: { game: 'chess' },
  onJoin: (ws, role) => console.log('joined as', role),
  onFull: (ws, role) => {
    // optionally notify the rejected client
  }
});

Options

OptionDefaultDescription
maxMembersInfinityMaximum members
meta{}Initial metadata (shallow-copied)
onJoin-(ws, role) → void
onLeave-(ws, role) → void
onFull-(ws, role) → void
onClose-() → void

Roles: 'member' (default), 'admin', 'viewer'.

Server usage

Use the hooks helper for zero-config access control. The subscribe hook intercepts the internal __group:lobby topic, calls join(), and blocks the subscription if the group is full or closed. The close hook calls leave().

// src/hooks.ws.js
import { lobby } from '$lib/server/lobby';

export const { subscribe, unsubscribe, close } = lobby.hooks;

If you need custom logic (role selection, auth gating), wrap the hook:

// src/hooks.ws.js
import { lobby } from '$lib/server/lobby';

export function subscribe(ws, topic, ctx) {
  if (topic === '__group:lobby') {
    const role = ws.getUserData().isAdmin ? 'admin' : 'member';
    return lobby.join(ws, ctx.platform, role) ? undefined : false;
  }
  lobby.hooks.subscribe(ws, topic, ctx);
}

export const { unsubscribe, close } = lobby.hooks;

Publish to group members:

// Broadcast to everyone
lobby.publish(platform, 'chat', { text: 'hello' });

// Broadcast only to admins
lobby.publish(platform, 'admin-alert', { msg: 'new report' }, 'admin');

Server API

MethodDescription
group.join(ws, platform, role?)Add member. Returns true or false if full/closed
group.leave(ws, platform)Remove member
group.publish(platform, event, data, role?)Broadcast (optionally filtered by role)
group.send(platform, ws, event, data)Send to one member (throws if not a member)
group.members()Array of { ws, role }
group.count()Member count
group.has(ws)Check membership
group.close(platform)Dissolve group, notify everyone
group.nameGroup name (read-only)
group.metaMetadata (get/set)
group.hooksReady-made { subscribe, unsubscribe, close } hooks with access control

Client usage

<script>
  import { group } from 'svelte-adapter-uws/plugins/groups/client';

  const lobby = group('lobby');
  const members = lobby.members;
</script>

<p>{$members.length} members</p>

The client store exposes two reactive values: the main store for events ($lobby - latest message) and .members for the live member list. The member list updates automatically on join, leave, and close events - no polling needed.

Limitations

  • In-memory. Group state lives in the process. In cluster mode, each worker manages its own groups independently.
  • No persistence. Groups are lost on restart. If you need durable rooms, store membership in a database and rebuild on start.
  • Role-filtered publish uses send(). When filtering by role, the plugin iterates members and sends individually instead of using the topic broadcast. Fine for typical group sizes, but O(n) with member count.

Was this page helpful?