WebSocket Endpoints for Real-Time Updates in Kaneo

Kaneo exposes two primary WebSocket endpoints at /ws/user for user-specific events and /ws/:projectId for project-scoped updates, both registered in apps/api/src/index.ts and powered by Hono's WebSocket adapter with a pluggable broadcast system.

Kaneo is an open-source project management platform that delivers live collaboration features through persistent WebSocket connections. The real-time layer is implemented in the apps/api directory, where the Hono framework handles connection upgrades and message broadcasting via adapter-based architecture.

Available WebSocket Endpoints

The API defines scoped endpoints to separate user-specific notifications from project-wide activity. These routes are registered before any other /ws/* handlers in apps/api/src/index.ts, ensuring they match incoming upgrade requests first.

User-Scoped Endpoint (/ws/user)

The /ws/user endpoint streams events specific to the authenticated user. This includes personal notifications, direct mentions, and user-only broadcasts that are not visible to other project members. Connections to this route require a valid session and maintain a persistent link for the duration of the user's session.

Project-Scoped Endpoint (/ws/:projectId)

The /ws/:projectId endpoint delivers real-time updates for a specific project identified by the :projectId parameter. This channel broadcasts task changes, activity feed entries, status updates, and other project-level events to all connected clients viewing that project. Multiple clients can subscribe to the same project ID simultaneously.

Broadcasting Architecture

Kaneo uses an adapter pattern to handle message distribution, allowing the platform to scale from single-instance deployments to multi-server clusters. The broadcast system lives in apps/api/src/ws/ and consists of three core components:

  • broadcast-adapter.ts – Defines the BroadcastAdapter interface and the message schema used across all implementations.
  • redis-broadcast-adapter.ts – Implements the adapter using Redis Pub/Sub on channels prefixed with kaneo:ws:*, enabling horizontal scaling across multiple API instances.
  • in-memory-broadcast-adapter.ts – Provides a fallback implementation that manages connections within a single Node.js process when Redis is not configured.

The system uses upgradeWebSocket from Hono's createNodeWebSocket integration to handle the HTTP upgrade handshake in apps/api/src/index.ts, after which messages are routed through the active adapter.

Client Connection Examples

To connect to the user-scoped endpoint from a browser client:

const socket = new WebSocket(
  `${window.location.origin.replace(/^http/, 'ws')}/ws/user`
);

socket.addEventListener('message', (event) => {
  const data = JSON.parse(event.data);
  console.log('User event received:', data);
});

To subscribe to project-specific updates:

const projectId = 'your-project-id';
const socket = new WebSocket(
  `${window.location.origin.replace(/^http/, 'ws')}/ws/${projectId}`
);

socket.addEventListener('message', (event) => {
  const update = JSON.parse(event.data);
  console.log(`Project ${projectId} update:`, update);
});

Server-Side Publishing

The server emits events using the publish or publishToUser functions imported from the broadcast module. When calling publish, the system inspects the message payload to determine the target project and forwards it to all matching connections.

import { publish } from '@kaneo/api';

await publish({
  projectId: '12345',
  message: {
    type: 'task.updated',
    projectId: '12345',
    taskId: '67890',
    timestamp: Date.now()
  },
});

If the Redis adapter is active, the message is serialized and published to the kaneo:ws:project:12345 channel, where all subscribed API instances receive it and push it to their local WebSocket connections.

Summary

  • Two dedicated endpoints: /ws/user for personal events and /ws/:projectId for project collaboration.
  • Central registration: Both routes are defined in apps/api/src/index.ts using Hono's WebSocket integration.
  • Pluggable adapters: The system supports both Redis-backed and in-memory broadcast strategies via files in apps/api/src/ws/.
  • Scoped broadcasting: Messages target specific users or projects, preventing unauthorized data leakage between contexts.
  • Horizontal scaling: The Redis adapter (redis-broadcast-adapter.ts) enables real-time sync across multiple server instances using kaneo:ws:* channels.

Frequently Asked Questions

What WebSocket library does Kaneo use?

Kaneo leverages Hono's native WebSocket support through createNodeWebSocket, which provides the upgradeWebSocket method used in apps/api/src/index.ts. This integration handles the HTTP upgrade process and wraps Node.js WebSocket connections for use within Hono's middleware stack.

How does Kaneo handle WebSocket scaling across multiple servers?

When REDIS_URL is configured, Kaneo uses redis-broadcast-adapter.ts to publish messages to Redis channels prefixed with kaneo:ws:*. All API instances subscribe to these channels and forward messages to their locally connected WebSocket clients, ensuring clients on different servers receive the same real-time updates.

Can a client connect to multiple project WebSockets simultaneously?

Yes. Clients can open separate WebSocket connections to multiple /ws/:projectId endpoints concurrently, with each connection maintaining independent event streams for its respective project. There is no hard limit imposed by the server architecture in apps/api/src/index.ts.

What message format does Kaneo use for WebSocket events?

The broadcast system in apps/api/src/ws/broadcast-adapter.ts defines a JSON-based schema where messages include a type field (e.g., task.updated, activity.created) and contextual data such as projectId or userId. All payloads are serialized to JSON strings before transmission.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →