Publishing events
Hotpipe doesn't store anything — it's purely real-time delivery. You save data however you normally do (server actions, API calls, etc.) and publish the event alongside it.
The usePipe hook gives you a publish function. When a user hits send, the event goes out to everyone listening on that pipe.
function MessageInput() {
const [text, setText] = useState('');
const { publish } = usePipe('team-chat');
async function send() {
// save to your database first
const message = await createMessage({ text, userId: currentUser.id });
// then broadcast it to everyone in real time
publish('message.created', {
id: message.id,
text: message.text,
userId: message.userId,
createdAt: message.createdAt,
});
setText('');
}
return (
<form
onSubmit={(e) => {
e.preventDefault();
send();
}}
>
<input value={text} onChange={(e) => setText(e.target.value)} />
<button type="submit">Send</button>
</form>
);
}Data is validated against your Zod schema before sending. If the data fails validation, publish throws. If the connection is temporarily down, events are buffered and flushed automatically when the connection comes back (up to 100 events, within 30 seconds).
Same idea on the server. Maybe you're already saving data in a server action or handling a webhook — just publish the event after. Everyone listening on that pipe gets it instantly.
import { realtime } from '@/lib/realtime-server';
// save to your database
const message = await db.messages.create({ text, userId });
// broadcast to connected users
const teamChat = realtime.pipe('team-chat');
await teamChat.publish('message.created', {
id: message.id,
text: message.text,
userId: message.userId,
createdAt: message.createdAt,
});Unlike the client-side publish, the server-side version is async — it makes an HTTP request to the Hotpipe API and will throw if the request fails.
For server-side publishes, sender is null by default — indicating the event came from your server, not a specific user.
// sender will be null — anonymous server event
await realtime
.pipe('team-chat')
.publish('system.announcement', { text: 'Maintenance in 5 minutes' });You can optionally provide a sender if the event is on behalf of a user:
// sender will be "bot-assistant" — explicitly provided, trusted
await realtime
.pipe('team-chat')
.publish('message.created', data, { sender: 'bot-assistant' });
