Subscribing to events
The usePipe hook is how you listen for real-time events. Subscribe to a pipe, handle typed events, and the hook manages the subscription lifecycle automatically.
The first argument to usePipe is the pipe name — a string that identifies the channel. The second argument is an object of event handlers. When an event comes in, the matching handler runs with fully typed data based on the Zod schema you defined during setup.
import { usePipe } from '@/lib/realtime-client';
function Messages() {
const [messages, setMessages] = useState([]);
usePipe('team-chat', {
'message.created': (data) => {
setMessages((prev) => [...prev, data]);
},
});
return (
<ul>
{messages.map((msg) => (
<li key={msg.id}>{msg.text}</li>
))}
</ul>
);
}The hook automatically subscribes when the component mounts and unsubscribes when it unmounts. If multiple components subscribe to the same pipe, Hotpipe ref-counts them — the subscription stays active until the last component unmounts.
A pipe name is just a string, and you can name it anything you want. A few examples to get your wheels turning:
"team-chat"— shared space where everyone on the team sees every message"game-lobby-abc"— real-time multiplayer game state"player-xyz"— events targeting a specific player"org-acme"— updates scoped to a whole organization"doc-789"— collaborative editing on a shared document"auction-42"— live bid updates on a specific item
Every event delivered to subscribers includes a metadata object with a verified sender field. For events published from the browser, the sender is automatically set from the authenticated user's identity — the one returned as userId in your authorize function. Clients cannot spoof it.
usePipe('team-chat', {
'message.created': (data, metadata) => {
console.log(metadata.sender); // "user-123" — verified, set by the API
console.log(metadata.ts); // server timestamp (ms)
},
});The metadata parameter is always there, but you only need to use it when sender identity matters to your application. For events where you don't care who sent them (typing indicators, cursor positions), just ignore it.
You can check whether the user is connected to the Hotpipe API at any time. The status field is reactive — it triggers a re-render when it changes.
const { status } = usePipe('team-chat');
// 'connecting' | 'connected' | 'disconnected' | 'reconnecting'Hotpipe automatically reconnects if the connection drops — the user's phone switches from Wi-Fi to cellular, their laptop wakes from sleep, or a spotty coffee shop connection blips for a few seconds. Most disconnections are brief, and the user may not even notice.

