Realtime presence

Wie is er online. Zonder je API te bevragen.

Abonneer je op een presence-kanaal en het huidige overzicht komt mee met het abonnement, zodat de ruimte gevuld wordt weergegeven in plaats van leeg. Daarna hoort elke client dezelfde joins en leaves. Je backend wijst elk lid een identiteit toe bij het ondertekenen van het abonnement, en dat is wat de lijst betrouwbaar maakt.

room.ts
18 members
import type { Member } from "@messagebird/realtime";

const room = bird.subscribe("presence-room-42");

room.bind("bird:subscription_succeeded", () => {
  // The roster is already here. Paint it before anyone moves.
  render({ me: room.myId, members: [...room.members.values()] });
});

room.bind<Member>("bird:member_added", (member) => join(member.member_id));
room.bind<Member>("bird:member_removed", (member) => leave(member.member_id));

input.addEventListener("input", () => {
  room.trigger("client-typing", { at: Date.now() });
});

Een lid is een persoon, geen socket.

Drie tabbladen zijn één lid.

Presence maakt deel uit van de Bird Realtime API en telt identiteiten in plaats van sessies. Een lid verschijnt op de lijst wanneer de eerste verbinding zich abonneert en verdwijnt wanneer de laatste verbinding wegvalt; de tussenliggende tabbladen produceren niets, dus een overzicht flikkert niet telkens als iemand een dubbel venster opent. Als je in plaats daarvan het aantal sockets nodig hebt, is dat een aparte app-instelling en een apart event.

Wat presence je biedt

Het overzicht, de wijzigingen en de identiteit om beide aan te koppelen. Allemaal ondertekend door je eigen backend.

  1. 01

    Het overzicht, bij aankomst.

    bird:subscription_succeeded bevat de huidige ledenlijst, zodat de eerste weergave de echte ruimte is. Je past joins en leaves toe bovenop het overzicht in plaats van de lijst vanuit een lege staat op te bouwen.

  2. 02

    Een identiteit die jij beheert.

    Je autorisatie-endpoint retourneert een member id en optionele member info, en ondertekent precies die string. Een client kan een abonnement aanvragen maar kan niet kiezen wie het is. Beperk member info tot kleine openbare profielgegevens zoals een weergavenaam of avatar: elk lid van het kanaal ontvangt het, en het is begrensd op 1 KB.

  3. 03

    Uitlezen vanaf je server.

    Lijst de leden van een kanaal op, of vraag member_count op zonder ze op te sommen, rechtstreeks via de API. Geen van beide vereist een abonnement, dus een backend kan beantwoorden wie er in een ruimte zit zonder er zelf aan deel te nemen. Member count is alleen voor presence; het opvragen op een publiek of privékanaal is een validatiefout, omdat die kanalen geen leden hebben.

  4. 04

    Client events tussen peers.

    Een presence-kanaal is een van de twee plekken waar een client rechtstreeks een event naar de anderen kan sturen, zodat typingindicatoren en cursorposities nooit je API raken. Tien per seconde per verbinding, en de afzender ontvangt zijn eigen event niet.

  5. 05

    Verbindingsaantallen, wanneer je ze wilt.

    Members beantwoorden wie er is. Schakel verbindingstelling en verbindingsaantal-events in, en bird:connection_count geeft aan hoeveel sockets er open zijn op het kanaal — dat is het getal waar de persoon met drie tabbladen drie aan bijdraagt.

Lid-geadresseerde events

Soms is de bestemming een persoon, geen ruimte.

Een ingelogd lid kan rechtstreeks worden aangesproken, zonder een kanaal te benoemen en zonder een abonnement te autoriseren. Eén aanroep bereikt elke verbinding die die identiteit heeft, over alle tabbladen en apparaten heen, en niemand anders — zelfs als een ander lid dezelfde eventnaam bindt. Als er geen actieve verbinding is, slaagt de aanroep alsnog: bezorging wordt niet in een wachtrij geplaatst, dus sla de notificatie op en laad deze wanneer ze terugkomen. Dezelfde identiteit is wat disconnect target wanneer een sessie onmiddellijk moet eindigen.

members.ts
server
// Address the person, not a channel. Every tab, every device.
await bird.realtime.members.send(APP_ID, "u_42", {
  event: "order.shipped",
  data: { order_id: "ord_123" },
});

// The roster, read from your server. No subscription needed.
const roster = await bird.realtime.channels.members(APP_ID, "presence-room-42");

// Password changed. Close every connection they hold.
await bird.realtime.members.disconnect(APP_ID, "u_42");

Een vriendenlijst is geen ruimte.

Presence beantwoordt wie er in deze ruimte bij mij is. Watchlist-events beantwoorden of de mensen die mij interesseren ergens online zijn. De ondertekende identiteit van een lid kan tot 100 member-id's bevatten, en met watchlist-events ingeschakeld wordt de verbinding geïnformeerd wanneer een van hen online of offline gaat, met de huidige status van de hele lijst direct na het inloggen. Omdat de lijst in de ondertekende identiteit zit, bepaalt jouw endpoint wie wie mag volgen. Geen kanaal per relatie, en de mensen die gevolgd worden hoeven niets anders te doen dan inloggen.

Duik dieper in de documentatie.

Presence-kanalen behandelt het overzicht, member info en de server-side reads. Kanalen autoriseren is het contract dat je backend implementeert, events naar een lid sturen vergelijkt member events met privékanalen, en watchlist-events is de volglijst-variant.

Breng het in de praktijk.

Ga verder met de documentatie, gidsen en voorbeelden voor dit onderwerp. De bronnen zijn in het Engels.

Probeer de oefening en ontvang een implementatieoverzicht

Toon de ruimte, niet een laadstatus.

Presence, client events en member-addressed delivery zijn inbegrepen bij elke Realtime-app. Het gratis abonnement dekt 100 gelijktijdige verbindingen.

Begin met één kanaal.
Voeg de rest toe wanneer je er klaar voor bent.

Een test-API-key is direct beschikbaar. Productietoegang wordt ontgrendeld zodra je een betaalmethode toevoegt en een afzender verifieert.

Gebruik je Claude Code, Cursor of Codex? Kopieer een setup-prompt en je agent installeert de Bird CLI en skills voor je. Kies de jouwe:

Cursor