WebSockets

Use WebSockets when your UI needs live two-way messaging between browser and server. In Caspian, socket endpoints are app-owned in main.py, while route templates keep browser socket clients with PulsePoint state and cleanup effects.

Feature gate first

Enable WebSocket support in caspian.config.json by setting "websocket": true before relying on socket-specific project flows.

Live Two-Way Events

Keep server push and client updates in one persistent connection.

Low-Latency UX

Avoid repeated polling for chat, dashboards, and collaborative views.

Explicit Security

Validate origin and session at connection time, not just HTTP routes.

Server Endpoint

Keep app-owned endpoint registration in main.py. This pattern checks origin, accepts the socket, receives JSON payloads, and sends structured responses.

main.py
from fastapi import WebSocket, WebSocketDisconnect

@app.websocket("/ws/live")
async def live_socket(websocket: WebSocket):
    # Validate origin/session before accepting in production flows.
    await websocket.accept()

    try:
        while True:
            payload = await websocket.receive_json()
            await websocket.send_json(
                "type": "echo",
                "message": payload.get("message", "")
            )
    except WebSocketDisconnect:
        pass

Route Client

Keep the browser socket in a route-owned template script. Store the connection in pp.ref(...), update UI with pp.state(...), and close sockets in effect cleanup.

src/app/chat/index.html
<div class="space-y-3">
  <button onclick="sendPing()">Send</button>

  <script>
    const socketRef = pp.ref(null);
    const [messages, setMessages] = pp.state([]);

    pp.effect(() => 
      const socket = new WebSocket("ws://localhost:5090/ws/live");
      socketRef.current = socket;

      socket.onmessage = (event) => 
        const data = JSON.parse(event.data);
        setMessages((prev) => [...prev, data.message]);
      ;

      return () => 
        if (socket.readyState === WebSocket.OPEN) socket.close(1000, "dispose");
      ;
    , []);

    function sendPing() 
      socketRef.current?.send(JSON.stringify(message: "ping"));
    
  </script>
</div>

Security Checklist

  • Validate origin allow-lists explicitly for socket handshakes.
  • Verify auth/session data inside the socket endpoint path.
  • Define a typed message envelope with explicit type keys.
  • Enforce idle timeouts, size limits, and clear close codes.