Skip to content

Choose and swap a transport

Pick the wire your client and server talk over, then change it in one line. The contract, handlers, roles, rooms, and topics above the transport are identical on every wire — only the transport differs.

Pick a wire

If you need…UsePackage
The default — lowest latency, full-duplex, broadest supportWebSocket@super-line/transport-websocket
To survive restrictive networks / proxies that block or buffer WebSocketHTTP (SSE or long-poll)@super-line/transport-http
Peer-to-peer / WebRTC / WebTransport, browser↔server with no signaling codelibp2p@super-line/transport-libp2p
Fast, deterministic tests with a real server + client in one processLoopback@super-line/transport-loopback

Start with WebSocket. Reach for HTTP as a fallback wire, libp2p when you want WebRTC/p2p, and loopback in your test suite.

Swap the client transport

The transport is the only line that changes between wires:

ts
// the ONLY thing that changes between wires:
webSocketClientTransport({ url: 'ws://localhost:3000' })   // WebSocket
httpClientTransport({ url: 'http://localhost:3000' })       // HTTP — SSE / long-poll
libp2pClientTransport({ node, multiaddr })                  // libp2p / WebRTC
loopbackTransport.client()                                  // in-memory (tests)
ts
const client = createSuperLineClient(contract, {
  transport: webSocketClientTransport({ url: 'ws://localhost:3000' }), // ← swap this one line
  role: 'user',
})
await client.send({ room: 'lobby', text: 'hi' }) // identical on every wire

Accept several wires at once

A server can accept multiple transports on one http.Server:

ts
createSuperLineServer(contract, {
  transports: [webSocketServerTransport({ server }), httpServerTransport({ server })],
  authenticate,
})

WebSocket uses the HTTP upgrade channel and HTTP uses the request channel, so they coexist without collision — a browser that can't open a WebSocket falls back to HTTP against the very same server.

Write auth once

authenticate always receives a normalized Handshake — the same shape regardless of transport — so your auth code doesn't change when you swap wires:

ts
authenticate: (h) => {
  // h: { transport, headers, query, peer?, raw }
  const token = h.query.token        // WS/HTTP carry it on the URL; libp2p carries it in the first frame
  return { role: 'user', ctx: verify(token) }
}

Transports vs adapters

A transport is the client↔server wire (this page). An adapter is the server↔server fan-out substrate for multi-node clusters (Redis, libp2p, …). They're independent — you pick each separately. See transports & adapters and choose an adapter.

Configure each wire: WebSocket · HTTP · libp2p & WebRTC · Loopback. For the model — what every transport shares, why the seam is one line — see transports & adapters.

Released under the MIT License.