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.
-
chanx, Python
class ChatMessage(BaseMessage): action: Literal["chat"] = "chat" payload: ChatPayload -
chanx-js, TypeScript
const Chat = defineMessage('chat', z.object({ text: z.string() }), ); -
chanx-go, Go
type ChatMessage struct { chanx.BaseMessage `action:"chat"` Payload ChatPayload `json:"payload"` } -
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.
-
chanx for Python
Typed consumers for Django Channels, FastAPI and any ASGI app, with test helpers and DRF permissions. Home of the protocol spec.
Use
chanx[channels]for Django. -
chanx-js for TypeScript
A server for Node, Bun and Deno, and generated clients for the browser, React, Vue, Svelte and Solid.
Clients come from
@chanx-js/codegen. -
chanx-go for Go
Servers on net/http, chi, gin, echo and Fiber, in-memory tests with no ports, and a Go client generator.
Go 1.25 or later.
-
chanx-kit ready-made components
Notifications, chat with history, presence and agent streaming for chanx. Copied into your project, so the code is yours to change.
Works on Django and FastAPI.
The server and the client don't have to share a language
-
Django or FastAPI server, React client. chanx-js generates the client from the AsyncAPI document your Python server serves.
-
Go server, TypeScript client. Same document, same generator, and a typo in a message fails to compile.
-
Node and Python servers on one Redis. Their channel layers share a format, so a broadcast from either reaches clients of both.
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.