Supporters
JOIN MY SPONSORS

Recipes

To get you started, here are a few common patterns for building with itty-sockets.

Chat Room

A basic chat room with user names and message display:

chat.js
import { connect } from 'itty-sockets'

const chat = connect('my-chat', {
  as: 'Anonymous User',
  announce: true,
})

chat.on('message', ({ message, alias }) => {
  log(`${alias}: ${message}`)
})

chat.on('join', ({ alias = 'a user', users }) => {
  log(`${alias} joined (${users} online)`)
})

chat.on('leave', ({ alias = 'a user', users }) => {
  log(`${alias} left (${users} online)`)
})

Live Dashboard

Broadcast-only pattern where a server publishes data and many clients listen:

dashboard-server.js
// server-side: publish metrics every second
import { connect } from 'itty-sockets'

const feed = connect('myapp:metrics', {
  sendKey: 'server-only',
})

setInterval(() => {
  feed.send({
    cpu: getCpuUsage(),
    memory: getMemoryUsage(),
    requests: getRequestCount(),
  })
}, 1000)
dashboard-client.js
// client-side: read-only listener
import { connect } from 'itty-sockets'

const metrics = connect('myapp:metrics')

metrics.on('message', ({ message }) => {
  // message = { cpu, memory, requests }
  updateChart(message)
})

Multiplayer Cursors

Share cursor positions in real-time:

cursors.js
import { connect } from 'itty-sockets'

const room = connect('cursors', { as: 'user-1' })

// broadcast cursor position
document.addEventListener('mousemove', (e) => {
  room.send({ x: e.clientX, y: e.clientY })
})

// render other cursors
room.on('message', ({ message, alias }) => {
  moveCursor(alias, message.x, message.y)
})

This is an incomplete example. You'll need to debounce/throttle events like mousemove to prevent getting forcibly disconnected.

Ephemeral Private Room

Create a private room on the fly without a namespace reservation:

private-room.js
import { connect } from 'itty-sockets'

// generate a random room + key
const room = 'room-' + Math.random().toString(36).slice(2)
const key  = crypto.randomUUID()

// first joiner sets the key
const channel = connect(room, { joinKey: key })

// share room + key with friends (URL, QR, etc.)
console.log(`Join: ${room} with key ${key}`)

The room and keys are ephemeral — they only exist while someone is connected. Once everyone leaves, the room is destroyed.

We could have skipped the joinKey entirely, since a random channel name is effectively just as secure.