Add real-time chat to your Node.js app in minutes — not hours.
Built on top of Socket.io with rooms, messaging, typing indicators, and read receipts ready out of the box.
npm install quick-socketTypeScript definitions are included out of the box.
const http = require('http')
const express = require('express')
const quickSocket = require('quick-socket')
const app = express()
const server = http.createServer(app)
// Initialize — one line
const io = quickSocket.init(server)
server.listen(3000, () => {
console.log('Server running on port 3000')
})That's it. Your Socket.io server is ready.
- Create and manage chat rooms
- Send, edit and delete messages
- Typing indicators
- Read receipts (sent, delivered, read)
- Broadcast to all users
- Notify specific users or rooms
- Auth middleware support
- Presence tracking (online / away / offline)
- Per-socket rate limiting
- Reconnect recovery with missed messages
quickSocket.createRoom('room-001', {
travellerId: 'user-1',
supplierId: 'user-2'
})io.on('connection', (socket) => {
quickSocket.joinRoom(socket, 'room-001', {
userId: 'user-1',
role: 'traveller'
})
})quickSocket.sendMessage('room-001', {
senderId: 'user-1',
content: 'Hello!',
type: quickSocket.MESSAGE_TYPES.TEXT
})// user started typing
quickSocket.sendTyping('room-001', 'user-1', true)
// user stopped typing
quickSocket.sendTyping('room-001', 'user-1', false)// mark one message as read
quickSocket.markRead('room-001', 'message-id', 'user-2')
// mark all messages as read
quickSocket.markAllRead('room-001', 'user-2')
// mark as delivered
quickSocket.markDelivered('room-001', 'message-id', 'user-2')quickSocket.editMessage('room-001', 'message-id', 'Updated text')
quickSocket.deleteMessage('room-001', 'message-id')const result = quickSocket.getRoomMessages('room-001', 1, 20)
console.log(result)
// {
// roomId: 'room-001',
// page: 1,
// limit: 20,
// total: 42,
// totalPages: 3,
// messages: [...]
// }Page 1 returns the most recent messages.
Message history is stored in memory per process, so pagination works for single-process deployments only.
// notify everyone
quickSocket.broadcast('announcement', { message: 'Server update soon' })
// notify a specific room
quickSocket.notifyRoom('room-001', 'alert', { message: 'New booking!' })
// notify a specific user
quickSocket.notifyUser('user-1', 'ping', { message: 'You have a message' })quickSocket.leaveRoom(socket, 'room-001')
quickSocket.closeRoom('room-001')Listen to these events on the client side:
| Event | When it fires |
|---|---|
message:new |
New message sent |
message:edited |
Message was edited |
message:deleted |
Message was deleted |
message:typing |
User is typing |
message:read |
Message was read |
message:delivered |
Message was delivered |
messages:all_read |
All messages marked read |
user:joined |
User joined the room |
user:left |
User left the room |
room:closed |
Room was closed |
presence:change |
User came online, went offline, or changed status |
rateLimit:exceeded |
Socket sent too many messages in the time window |
reconnect:recovery |
Missed messages delivered after reconnect |
// frontend (browser)
const socket = io('http://localhost:3000')
socket.on('message:new', (msg) => {
console.log('New message:', msg.content)
})
socket.on('message:typing', (data) => {
console.log(data.userId, 'is typing:', data.isTyping)
})
socket.on('message:read', (data) => {
console.log('Read by:', data.userId)
})quickSocket.MESSAGE_TYPES.TEXT // 'text'
quickSocket.MESSAGE_TYPES.IMAGE // 'image'
quickSocket.MESSAGE_TYPES.FILE // 'file'
quickSocket.MESSAGE_TYPES.SYSTEM // 'system'quickSocket.STATUS.SENT // 'sent'
quickSocket.STATUS.DELIVERED // 'delivered'
quickSocket.STATUS.READ // 'read'const io = quickSocket.init(server)
io.use(quickSocket.authMiddleware((token) => {
// verify your token here (JWT, etc.)
return verifyToken(token) // return user object
}))Client sends token like this:
const socket = io('http://localhost:3000', {
auth: { token: 'your-token-here' }
})const participants = quickSocket.getRoomParticipants('room-001')
console.log(participants)
// [{ userId, role, socketId, joinedAt }, ...]Track who is online, away, or offline in real time.
io.on('connection', (socket) => {
quickSocket.trackPresence(socket, socket.user.id)
// automatically emits presence:change on connect and disconnect
})
// manually set a user as away
quickSocket.setPresence('user-1', quickSocket.PRESENCE_STATUS.AWAY)
// query presence
quickSocket.getPresence('user-1')
// { status: 'away', lastSeen: null, meta: {} }
// get presence for everyone in a room
quickSocket.getRoomPresence('room-001')
// { 'user-1': { status: 'online', ... }, 'user-2': { status: 'offline', lastSeen: Date } }Client listens:
socket.on('presence:change', ({ userId, status, lastSeen }) => {
console.log(userId, 'is now', status)
})Protect rooms from message spam with a sliding window rate limiter.
const io = quickSocket.init(server)
// max 10 messages per second per socket
io.use(quickSocket.createRateLimiter({ limit: 10, windowMs: 1000 }))
// limit only specific events
io.use(quickSocket.createRateLimiter({
limit: 5,
windowMs: 1000,
events: ['message:send']
}))Client receives when limit is hit:
socket.on('rateLimit:exceeded', ({ event, limit, retryAfter }) => {
console.log(`Slow down. Retry in ${retryAfter}s`)
})When a user reconnects, re-join their rooms and deliver messages they missed.
io.on('connection', (socket) => {
const userId = socket.user.id
const lastSeen = socket.handshake.auth?.lastSeen
const { rooms, missedMessages } = quickSocket.rejoinRooms(socket, userId, {
since: lastSeen
})
// send missed messages back to the client
socket.emit('reconnect:recovery', { rooms, missedMessages })
})Control Socket.io's ping/pong to keep connections alive on flaky networks.
quickSocket.init(server, {
pingInterval: 10000, // default 25000ms
pingTimeout: 5000 // default 20000ms
})Contributions are welcome! Check the open issues to see what needs doing.
Good places to start:
Please read CONTRIBUTING.md to get started.
MIT