> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bbrands.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Integración de clientes

> El hook compartido usePusherChannel, el contrato de entorno del cliente y el fallback de polling.

## El hook compartido

Cada frontend de BBrandsLab se suscribe a través de un único hook agnóstico al framework,
`usePusherChannel`, exportado desde `@bbrandslab/ui`.

<CardGroup cols={2}>
  <Card title="Un socket por (key, cluster)" icon="plug">
    Los clientes se memoizan a nivel de módulo para que varias suscripciones en la misma
    página reutilicen un único WebSocket.
  </Card>

  <Card title="pusher-js perezoso" icon="feather">
    Cargado con un import dinámico. `pusher-js` es una **peer dependency** del paquete
    UI; cada app consumidora lo declara como dependencia directa.
  </Card>

  <Card title="Buffer acotado" icon="layer-group">
    Los eventos se agrupan por frame de animación y se limitan a `maxEvents` (por defecto
    250\), de modo que los canales de alto throughput nunca congelen la UI.
  </Card>

  <Card title="Desactivación elegante" icon="power-off">
    Un `pusherKey` vacío/indefinido produce `status: "disabled"` sin abrir un
    socket.
  </Card>
</CardGroup>

```tsx theme={null}
const { events, latest, status } = usePusherChannel({
  channel: machineId ? `totem-${machineId}` : null,
  cluster: env.NEXT_PUBLIC_PUSHER_CLUSTER,
  events: ["alert:created", "command:result"],
  pusherKey: env.NEXT_PUBLIC_PUSHER_KEY,
});

if (status === "disabled") return <ConfigureRealtimeBanner />;
```

Cuando se omite `events`, el hook enlaza cada evento del canal y filtra
los eventos del sistema de Pusher.

## Variables de entorno del cliente

| Variable                     | Propósito                                         |
| ---------------------------- | ------------------------------------------------- |
| `NEXT_PUBLIC_PUSHER_KEY`     | App key pública. Vacía → tiempo real desactivado. |
| `NEXT_PUBLIC_PUSHER_CLUSTER` | Cluster, por defecto `us2`.                       |

<Note>
  La key es pública por diseño; solo el servidor tiene
  `INTEGRATION_PUSHER_SECRET`. Los canales privados se autorizan a través de
  [`POST /api/v3/realtime/pusher/auth`](/es/realtime/channels-and-events).
</Note>

## Apps consumidoras

<CardGroup cols={2}>
  <Card title="portal-customer" icon="file-signature">
    Se suscribe al canal del contrato digital e invalida la query del contrato
    cuando llega un evento de etapa de firma.
  </Card>

  <Card title="horizon-enterprise" icon="tower-broadcast">
    Se suscribe a los canales de NOC y de tótems de Maihue Street; combina la
    invalidación de Pusher con un poll de notificaciones de 60 s.
  </Card>
</CardGroup>

## Fallback de polling

El tiempo real es opcional, así que cada consumidor mantiene un fallback basado en query. Cuando no
hay una key de Pusher configurada, la UI depende solo del refetching de React Query. Diseña
cada pantalla para que sea totalmente utilizable sin tiempo real.
