chanx

Typed WebSockets that speak the same protocol in Python, TypeScript and Go.

Declare each message once. chanx routes it to a typed handler, validates it, broadcasts it to groups and documents it as AsyncAPI, then generates typed clients from that document. Every implementation puts the same frames on the wire, so a Django server, a Go service and a React app can all talk to each other.

  1. chanx, Python
    class ChatMessage(BaseMessage):
        action: Literal["chat"] = "chat"
        payload: ChatPayload
  2. chanx-js, TypeScript
    const Chat = defineMessage('chat',
      z.object({ text: z.string() }),
    );
  3. chanx-go, Go
    type ChatMessage struct {
    	chanx.BaseMessage `action:"chat"`
    	Payload ChatPayload `json:"payload"`
    }
  4. On the wire, from any of them
    {"action": "chat", "payload": {"text": "hi"}}

Four projects, one protocol

Use one, or mix them across your stack. Each has its own docs.

The server and the client don't have to share a language

From handler to typed client

Write a handler, open the AsyncAPI docs generated from it, generate a client, and watch the compiler catch a typo.

Writing another implementation?

The protocol is small: JSON text frames with an action and a payload, plus request ids, topics and a single error shape. The spec lists every frame, so a new implementation can be checked against the three above.

Read the protocol spec