Concepts

Connection & errors

Hotpipe gives you the building blocks — how you respond to connection issues is up to you and depends on what makes sense for your app.

The status field is reactive, so you can render UI based on it directly. A simple approach — show an inline banner when the user goes offline, and hide it when they're back:

function ChatRoom() {
  const { status } = usePipe('team-chat', {
    'message.created': (data) => {
      setMessages((prev) => [...prev, data]);
    },
  });

  return (
    <div>
      {status === 'reconnecting' && (
        <div className="bg-yellow-100 p-2 text-sm">
          Reconnecting — messages may be delayed
        </div>
      )}
      {status === 'disconnected' && (
        <div className="bg-red-100 p-2 text-sm">
          Disconnected — trying to reconnect
        </div>
      )}
      <MessageList messages={messages} />
    </div>
  );
}

If users shouldn't be able to send messages while offline, disable the form:

function MessageInput() {
  const { status, publish } = usePipe('team-chat');
  const isOnline = status === 'connected';

  return (
    <form onSubmit={send}>
      <input disabled={!isOnline} />
      <button disabled={!isOnline}>Send</button>
    </form>
  );
}

Outgoing events are covered — if the user publishes while the connection is briefly down, Hotpipe buffers those events (up to 100, within 30 seconds) and flushes them automatically when the connection comes back. The user doesn't need to do anything, and neither do you.

Incoming events are a different story. Hotpipe is purely real-time — it doesn't store events on the server. If other users publish while this user is disconnected, those events are gone. For many features (typing indicators, live cursors) that's fine — stale data isn't useful anyway. But for things like chat messages, you probably want to fill in the gap by re-fetching from your database when the connection comes back:

function Messages() {
  const [messages, setMessages] = useState([]);

  const { status } = usePipe('team-chat', {
    'message.created': (data) => {
      setMessages((prev) => [...prev, data]);
    },
  });

  const prevStatus = useRef(status);

  useEffect(() => {
    if (prevStatus.current === 'reconnecting' && status === 'connected') {
      // we just came back online — fetch anything that arrived while we were away
      fetchMessages({ since: messages.at(-1)?.createdAt }).then((recent) => {
        setMessages((prev) => deduplicateAndMerge(prev, recent));
      });
    }
    prevStatus.current = status;
  }, [status]);
}

If the connection is down long enough for the outgoing buffer to fill up (100 events or 30 seconds), publish starts returning false instead of true. From there, you can do whatever makes sense — show a toast, disable the input, or silently wait it out:

function send() {
  const sent = publish('message.created', { id, text, userId, createdAt });

  if (!sent) {
    toast("Sorry, we're having a little trouble right now. Hang tight.");
  }
}
Hotpipe automatically reconnects if the connection drops. Most disconnections are brief and the user may not even notice. The patterns above are for when you want to give your users extra visibility into what's happening.

Was this page helpful?