Chanx#
Typed WebSocket APIs for Python. Write one handler per message; Chanx routes, validates, broadcasts and documents it, and generates typed clients from the result. Runs on Django Channels, FastAPI, or any ASGI framework.
pip install "chanx[channels]" # Django Channels
pip install "chanx[fast_channels]" # FastAPI, Starlette and other ASGI frameworks
One handler per message#
Messages are Pydantic models with a Literal action. Handlers are typed methods. The
same consumer runs on either framework; only the import changes.
from chanx.channels.websocket import AsyncJsonWebsocketConsumer
from chanx.core.decorators import channel, ws_handler
@channel(name="chat", description="Room chat")
class ChatConsumer(AsyncJsonWebsocketConsumer):
groups = ["lobby"]
@ws_handler(output_type=ChatNotification)
async def handle_chat(self, message: ChatMessage) -> None:
await self.broadcast_message(ChatNotification(payload=message.payload))
from chanx.fast_channels.websocket import AsyncJsonWebsocketConsumer
from chanx.core.decorators import channel, ws_handler
@channel(name="chat", description="Room chat")
class ChatConsumer(AsyncJsonWebsocketConsumer):
channel_layer_alias = "default"
groups = ["lobby"]
@ws_handler(output_type=ChatNotification)
async def handle_chat(self, message: ChatMessage) -> None:
await self.broadcast_message(ChatNotification(payload=message.payload))
from typing import Literal
from pydantic import BaseModel
from chanx.messages.base import BaseMessage
class ChatPayload(BaseModel):
text: str
class ChatMessage(BaseMessage): # client -> server
action: Literal["chat"] = "chat"
payload: ChatPayload
class ChatNotification(BaseMessage): # server -> everyone in the group
action: Literal["chat_notification"] = "chat_notification"
payload: ChatPayload
What you get#
Incoming JSON is dispatched on its action to the handler whose argument type
matches. No if/elif chains.
Pydantic checks every payload before your code runs; bad ones get a structured error reply.
Broadcast to groups and topics, and push messages from views, tasks or workers through the channel layer.
A spec and an interactive docs page generated from your handlers, so the contract is the code that runs.
Generate Python clients, or TypeScript clients with React, Vue, Svelte and Solid bindings via chanx-js.
Test communicators for both frameworks, and authenticators that reuse DRF permission classes on Django.
Pick your path#
Add Chanx to an existing Django Channels project.
Consumers, channel layers and AsyncAPI on FastAPI or Starlette.
Build a full app step by step: chat, AI streaming, background jobs and tests.
chanx-js generates a typed client from your server's AsyncAPI spec.