Chanx#

Chanx 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#

Routing by type

Incoming JSON is dispatched on its action to the handler whose argument type matches. No if/elif chains.

Consumers & Decorators
Validation

Pydantic checks every payload before your code runs; bad ones get a structured error reply.

Consumers & Decorators
Groups and events

Broadcast to groups and topics, and push messages from views, tasks or workers through the channel layer.

Topics
AsyncAPI 3.0 docs

A spec and an interactive docs page generated from your handlers, so the contract is the code that runs.

AsyncAPI Documentation
Typed clients

Generate Python clients, or TypeScript clients with React, Vue, Svelte and Solid bindings via chanx-js.

Client Generator
Testing and auth

Test communicators for both frameworks, and authenticators that reuse DRF permission classes on Django.

Testing WebSocket Consumers

Pick your path#

Django quick start

Add Chanx to an existing Django Channels project.

quick-start.html?framework=django
FastAPI quick start

Consumers, channel layers and AsyncAPI on FastAPI or Starlette.

quick-start.html?framework=fastapi
Tutorials

Build a full app step by step: chat, AI streaming, background jobs and tests.

Prerequisites
TypeScript clients

chanx-js generates a typed client from your server's AsyncAPI spec.

https://js.chanx.dev/