DEV Community

Amverum Cloud
Amverum Cloud

Posted on

Websockets on FastAPI: Implementing a simple chat with rooms in 20 minutes

In the near future, I plan to publish a large article on Habr, where I will analyze in detail the development of an anonymous chat in the Telegram MiniApp format. We will create a service for face-to-face communication, which will work inside Telegram and provide instant messaging.

Project technology stack:

  • FastAPI + WebSocket – for real time and messaging

  • Redis – for quick search and connection of interlocutors

  • PostgreSQL – for storing messages and user information

  • Vue 3 + Pinia – for a convenient and responsive interface

  • Telegram Mini Apps API – to embed the chat directly into Telegram

In addition to the technical analysis, in the article I will also touch on the issue of monetization. One of the most effective ways to monetize Telegram MiniApp is advertising. This allows the service to remain free for users, and the developer to earn money on the popularity of the project.

As an advertising platform, I will consider RichAds - they offer excellent tools for integrating advertising into Telegram MiniApps, which makes them a logical choice for such a project.

But before we dive into MiniApp development, let's get the basics down. In this article, we will get acquainted with web sockets, learn how they work, and learn how to implement them on FastAPI.

This is only the first part of a large project, which I will refer to in future material to make it more structured and easier to read.

So, what is WebSocket and how can it help us in developing a chat? Let's figure it out.

WebSocket: principles of operation

Imagine a phone call: you dial a number (establish a connection) once, and after that you can freely talk without having to dial the number again for each phrase. WebSocket works in a similar way - it is a technology that creates a permanent "communication channel" between the user's browser and the server, allowing them to exchange messages in real time.

Let's get some terminology straight:

  • The client is what the person uses: a web page in a browser, an application on a phone or computer

  • The server is a remote computer that stores and processes our application data

Key advantages of WebSocket:

  1. Persistent connection: like a phone call – establish a connection once and communicate

  2. Fast operation: no time is wasted on reconnection

  3. Two-way communication: both the client and the server can start communicating first

  4. Resource saving: service information is transmitted only at the beginning of the connection

Comparison of approaches to implementing a chat

Classic method (HTTP):

Imagine that you send letters:

  1. Write a message and send it to the server

  2. The server saves the letter

  3. Other chat participants must constantly check the "mailbox" (make requests to the server)

  4. Only after checking will they see the new message

Even if the check is done automatically (for example, via AJAX), you still have to constantly "look into the mailbox", which creates an extra load.

Disadvantages:

  • The server gets tired of constant checks

  • Messages arrive with a delay

  • A lot of Internet traffic is spent

WebSocket Method:

Now imagine a group call:

  1. All participants are connected to the general conversation

  2. When someone speaks, everyone hears it at once

  3. No need to constantly check for new messages

  4. Communication happens instantly

Advantages:

  • Messages arrive instantly

  • The server is less loaded

  • Internet traffic is saved

  • True real-time communication

This approach works great not only in chats, but also in online games, collaborative document editors and anywhere where an instant response to user actions is needed.

Next, we will create a simple chat on FastAPI to see how it works in practice. For simplicity of the example, we will make both the server and client parts in one application, although in a real "Tet-a-Tet" chat the interface will be a separate application on VueJS3.

What project are we going to develop?

Today we will create a full-fledged FullStack application – a group chat, in which users will be able to:

  • Create rooms for communication

  • Join existing rooms

  • Exchange messages in real time

All participants in the same room will instantly receive new messages without having to refresh the page.

Tech stack

To implement the project, we will use modern and convenient tools:

  • Python + FastAPI + WebSockets – for the server part and organizing real time

  • JavaScript – for establishing connections via web sockets and page dynamics

  • TailwindCSS – for fast and convenient interface styling

  • HTML + Jinja2 – for rendering pages with data

  • Amverum Cloud – for fast and easy deployment

Development stages

1. Server part (Backend)

  • Developing a class for managing web sockets

  • Creating an endpoint for handling connections via WebSocket

  • Implementing routes (endpoints) for rendering HTML pages

2. Client part (Frontend)

  • Developing two HTML pages

  • Adding JavaScript logic for connecting to WebSocket

  • Implementing dynamic interface updates

3. Project deployment

A group chat is pointless without external access, so in conclusion we will deploy the project on the Internet.

For deployment, we will use Amverum Cloud – a service that allows you to deploy a FastAPI application in just a couple of minutes. The advantages of this solution:

  • Automatic HTTPS certificates

  • Free domain name

  • Webhooks support (for example, for integration with Telegram bots)

Thus, as a result of the work, we will have a ready, expanded and working group chat that can be used, tested and expanded.

Project preparation

Let's start with project preparation. Let me remind you that we will be writing in the Python FastAPI framework, which is great for implementing WebSocket due to its asynchronous nature and simple API.

  • Open IDE and create a new project

  • Create a requirements.txt file and fill it in as follows:

fastapi==0.115.8 # The web framework itself
websockets==15.0 # Library for working with WebSocket
uvicorn==0.34.0. # ASGI server for running the application
jinja2==3.1.5    # Template engine for rendering HTML
Enter fullscreen mode Exit fullscreen mode
  • Install libraries:
pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode
  • Prepare the project structure:
my_chat_project/
├── requirements.txt      # Project dependencies file
├── app/                  # Main application directory
 ├── templates/          # Directory with HTML templates
  ├── home.html         # Home page template
  └── index.html        # Main application template
 ├── static/             # Directory with static files (JS, CSS)
  └── index.js          # JavaScript for index.html
 ├── api/                # Directory with API routes
  ├── router_page.py    # Routes for pages (HTML)
  └── router_socket.py  # Routes for WebSocket connections
 └── main.py             # Main application file (launch)
Enter fullscreen mode Exit fullscreen mode

Writing the server part

We will describe the main logic of the server part of our application in the router_socket.py file. This file will be responsible for managing WebSocket connections and sending messages between users.

Importing the necessary modules

from fastapi import APIRouter, WebSocket, WebSocketDisconnect
from typing import Dict
Enter fullscreen mode Exit fullscreen mode
  • FastAPI — used to create a web application.

  • WebSocket, WebSocketDisconnect — classes for working with WebSocket connections. The first allows you to establish connections, the second — to handle their termination.

  • Dict — a data type for convenient annotation of the structure for storing user connections.

Initializing the router

FastAPI uses routers (APIRouter) to organize endpoints into logical blocks. In this case, let's create a router with the prefix /ws/chat:

router = APIRouter(prefix="/ws/chat")
Enter fullscreen mode Exit fullscreen mode

This route will handle all WebSocket requests related to the chat.

Creating a connection manager

For convenient connection management, let's create a ConnectionManager class. It will be responsible for connecting and disconnecting users, as well as for sending messages.

Full class code:

class ConnectionManager:
    def __init__(self):
        # Store active connections as {room_id: {user_id: WebSocket}}
self.active_connections: Dict[int, Dict[int, WebSocket]] = {}

    async def connect(self, websocket: WebSocket, room_id: int, user_id: int):
        """
        Establishes a connection with the user.
        websocket.accept() — confirms the connection.
        """
        await websocket.accept()
        if room_id not in self.active_connections:
            self.active_connections[room_id] = {}
        self.active_connections[room_id][user_id] = websocket

    def disconnect(self, room_id: int, user_id: int):
        """
        Closes the connection and removes it from the list of active ones connections.
        If there are no more users in the room, deletes the room.
        """
        if room_id in self.active_connections and user_id in self.active_connections[room_id]:
            del self.active_connections[room_id][user_id]
            if not self.active_connections[room_id]:
                del self.active_connections[room_id]

    async def broadcast(self, message: str, room_id: int, sender_id: int):
        """
        Broadcasts a message to all users in the room.
        """
        if room_id in self.active_connections:
            for user_id, connection in self.active_connections[room_id].items():
                 message_with_class = {
                    "text": message,
                    "is_self": user_id == sender_id
                }
                await connection.send_json(message_with_class)

Enter fullscreen mode Exit fullscreen mode

Code breakdown

  1. Class constructor
  • self.active_connections is a dictionary that stores active connections grouped by rooms (room_id).

  • Each room (room_id) stores connected users as {user_id: WebSocket}.

  1. connect
  • Accepts a WebSocket connection, a room id (room_id), and a user (user_id).

  • Acknowledges the connection (websocket.accept()).

  • Adds the WebSocket to self.active_connections.

  1. disconnect
  • Removes the user's WebSocket from self.active_connections.

  • If there are no users left in the room, deletes the room.

  1. broadcast
  • Sends a message to all users in the room.

  • Additionally adds the is_self flag so that the client can visually highlight its messages.

Initializing the connection manager

Let's create an instance of the ConnectionManager class, which we will use later:

manager = ConnectionManager()
Enter fullscreen mode Exit fullscreen mode

Creating a WebSocket endpoint

Now let's create a WebSocket endpoint that will manage user connections and message transmission in the chat.

@router.websocket("/{room_id}/{user_id}")
async def websocket_endpoint(websocket: WebSocket, room_id: int, user_id: int, username: str): 
    await manager.connect(websocket, room_id, user_id) 
    await manager.broadcast(f"{username} (ID: {user_id}) has joined the chat.", room_id, user_id) 

    try: 
        while True: 
            data = await websocket.receive_text() 
            await manager.broadcast(f"{username} (ID: {user_id}): {data}", room_id, user_id) 
    except WebSocketDisconnect: 
        manager.disconnect(room_id, user_id) 
        await manager.broadcast(f"{username} (ID: {user_id}) has left the chat.", room_id, user_id)

Enter fullscreen mode Exit fullscreen mode

Code breakdown

  1. Route
  • Endpoint accepts three parameters from URL: room_id, user_id, username.

  • Each user connects via URL /ws/chat/{room_id}/{user_id}.

  1. Connection
  • await manager.connect(...) — adds user to active connections list.

  • await manager.broadcast(...) — notifies all users of the room about new member.

  1. Receiving and sending messages
  • Infinite loop (while True) listens for incoming messages via websocket.receive_text().

  • After receiving message, it is broadcast to all users of the room via manager.broadcast(...).

  1. Disconnection
  • If connection is interrupted (WebSocketDisconnect), manager.disconnect(...) is called.

  • Sends a message to the chat about the user leaving.

In this section, we created the server part of the chat on WebSocket using FastAPI. We:

  • Figured out imports and routers.

  • Created ConnectionManager to manage connections.

  • Wrote a WebSocket endpoint to receive and send messages.

In the next section, we will look at how to connect the client part and test WebSocket connections.

Writing the client part

The client part will conditionally consist of two main stages:

  1. Description of endpoints for rendering HTML pages

  2. Writing the frontend part itself: HTML + CSS + JS

In this section, we will describe the endpoints that will serve HTML pages. We will implement them in the app/router_page.py file.

Imports

First, import the necessary modules:

from fastapi import APIRouter, Request, Form
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
import random
Enter fullscreen mode Exit fullscreen mode

Let's figure out why we need each import:

  • APIRouter – allows you to organize routing in the application.

  • Request – a request object that is passed to the template during rendering.

  • Form – used to process data transmitted via an HTML form.

  • Jinja2Templates – needed to work with HTML templates.

  • HTMLResponse – specifies that the endpoint returns an HTML page.

  • Random - to generate a random user ID

Initializing the route and renderer

Before describing the endpoints, let's create a templates object that will indicate where the HTML templates are stored, and initialize the router:

templates = Jinja2Templates(directory='app/templates')
router = APIRouter()

Enter fullscreen mode Exit fullscreen mode

Endpoints description

Now let's create two endpoints. The first one will be responsible for rendering the main page, and the second one - for the room page (our group chat).

Endpoint for the main page

@router.get("/", response_class=HTMLResponse)
async def home_page(request: Request):
    return templates.TemplateResponse("home.html", {"request": request})

Enter fullscreen mode Exit fullscreen mode

This endpoint returns the main page home.html. It will contain a form for entering the chat, which we will analyze later.

Endpoint for joining chat

@router.post("/join_chat", response_class=HTMLResponse)
async def join_chat(request: Request, username: str = Form(...), room_id: int = Form(...)):
    # Simple user_id generation
    user_id = random.randint(100, 100000)
    return templates.TemplateResponse("index.html",
                                      {"request": request,
                                       "room_id": room_id,
                                       "username": username,
                                       "user_id": user_id}
                                      )

Enter fullscreen mode Exit fullscreen mode

This endpoint does several things:

  1. Gets username and room_id from the form (using Form(...)).

  2. Generates a random user ID in the range from 100 to 100000

  3. Returns the HTML page index.html with the parameters passed to the template:

  • room_id – ID of the room the user enters.

  • username – username.

  • user_id – generated user ID.

Why is Form(...) used?

FastAPI has several ways to pass data to an endpoint. In this case, Form(...) specifies that the username and room_id parameters are passed through an HTML form using the POST method. This is convenient for processing data entered by the user on a web page.

If we were passing data in the URL (as query parameters), we would have to use Query(...), and if we were passing JSON – Body(...).

At this point, we have endpoints ready for working with HTML pages. In the next section, we will implement the frontend: create HTML templates, styles, and connect WebSocket.

Frontend implementation: HTML, CSS, and JavaScript

Now that we have the server part and endpoints for rendering pages, let's move on to creating the user interface. Our client part will include:

  • HTML - for the page structure,

  • CSS (TailwindCSS) - for styling,

  • JavaScript - for event handling and working with WebSocket.

1. HTML structure

We will create two main HTML files:

  • home.html – the main page with the chat login form.

  • index.html – the chat page where real-time communication will take place.

Home page (home.html)

<!DOCTYPE html>
<html lang="en">
<head> 
    <meta charset="UTF-8"> 
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
    <title>Login to chat</title> 
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 flex flex-col items-center justify-center min-h-screen p-4">
<h1 class="text-3xl font-bold mb-6">Welcome to the chat</h1>

<form action="/join_chat" method="post" class="bg-white p-6 rounded-lg shadow-md w-full max-w-md"> 
    <label class="block" text-gray-700">Enter your name:</label> 
    <input type="text" name="username" required 
            class="w-full p-2 border border-gray-300 rounded-lg mt-2 focus:ring-2 focus:ring-blue-500"> 

    <label class="block text-gray-700 mt-4">Enter room ID:</label> 
    <input type="number" name="room_id" required min="1" 
           class="w-full p-2 border border-gray-300 rounded-lg mt-2 focus:ring-2 focus:ring-blue-500"> 
    <button type="submit" class="w-full bg-blue-500 text-white px-4 ru-2 rounded-lg mt-4 hover:bg-blue-600">Log in 
        chat
    </button>
</form>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

Code breakdown

This template does the following:

  1. Displays a greeting title.

  2. Shows a login form consisting of two fields:

  • Username (username) – a regular text field.

  • Room ID (room_id) – a field for entering a numeric identifier.

  1. After clicking the "Enter chat" button, the data is sent to the server via POST (/join_chat).

Why just enter the room ID?

In production projects, you could select a room from a list, but in our case it is easier to let the user enter the ID themselves. If the room exists, they will connect, if not, they will create a new one.

Chat page (index.html)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSocket Chat - Room {{ room_id }}</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 flex flex-col items-center p-4">
<h1 class="text-2xl font-bold mb-4">WebSocket Chat - Room {{ room_id }}</h1>

<!-- Hidden element for storing room data -->
<div id="room-data" 
    data-room-id="{{ room_id }}" 
    data-username="{{ username }}" 
    data-user-id="{{ user_id }}" 
    class="hidden">
</div>

<!-- Message area -->
<div id="messages" 
    class="w-full max-w-lg h-96 overflow-y-auto border border-gray-300 bg-white p-4 rounded-lg shadow-md">
</div>

<!-- Input field and button -->
<div class="flex mt-4 w-full max-w-lg"> 
    <input id="messageInput" 
           type="text" 
           placeholder="Enter a message" 
           class="flex-1 p-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-blue-500"/> 
    <button onclick="sendMessage()" 
            class="bg-blue-500 text-white px-4 py-2 rounded-r-lg hover:bg-blue-600">Submit 
    </button>
</div>
<script src="/static/index.js"></script>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

Code breakdown

This template creates a chat interface:

  1. Displays a title with the room number ({{ room_id }}).

  2. Hidden block #room-data

  • Stores data sent by the server (room_id, username, user_id).

  • Made hidden with class="hidden".

  • In the future, JavaScript will extract this data.

  1. Message area (#messages) - user messages will appear here.

  2. Input field and "Send" button

  • Field (#messageInput) for entering text.

  • The onclick="sendMessage()" button sends a message.

  1. Connecting index.js
  • The /static/index.js file will describe the logic of interaction with WebSocket.

Why the hidden #room-data block?

Passing server variables directly to JS code is not always convenient. With Jinja2, you can output them to HTML and then read them in JavaScript.

2. Including styles

We use TailwindCSS, which is included via CDN:

<script src="https://cdn.tailwindcss.com"></script>
Enter fullscreen mode Exit fullscreen mode

This allows us to write compact and flexible CSS code directly in HTML, for example:

<body class="bg-gray-100 flex flex-col items-center p-4">
Enter fullscreen mode Exit fullscreen mode

Why TailwindCSS?

  • Eliminates the need to write custom CSS files.

  • Allows you to quickly style elements.

  • Good for prototyping.

3. How pages interact with the server

  1. The user goes to the main page of the site (/).

  2. Enters the name and room ID.

  3. Clicks "Join the chat" - the request is sent to /join_chat.

  4. The server returns index.html with the parameters passed to it.

  5. The page loads, and the JS code starts working with WebSocket.

What's next?

We have prepared the interface, but the chat cannot send messages yet. In the next section, we will implement JavaScript logic that will allow us to connect to WebSocket, send and receive messages.

Implementing WebSocket in JavaScript

Now that we have an interface, it's time to add logic for exchanging messages in real time. We will use WebSocket for communication between the client and the server.

Implementing WebSocket in JavaScript

Now that we have the interface, it's time to add the logic for exchanging real-time messages. We will use WebSocket for communication between the client and the server.

A small but important digression

I want you to have a correct understanding: implementing WebSocket, and especially chats, on the backend side is not such a difficult task.

For us, backend developers, it is enough to write a few dozen lines of code to create a WebSocket connection, handle client connections and forward messages to all participants of a chat, room or, for example, an online game.

But if anyone has to really sweat, it is the frontend developers.

Why?

  • In addition to the visual component of the interface, they need to establish a connection to the server correctly.

  • Handle WebSocket events: connection, disconnection, receiving and sending messages.

  • Organize convenient and dynamic display of messages in real time.

Of course, this work is not super complicated, but the main difficulties when working with WebSocket often arise on the frontend.

Next, I will show a simple example of how to implement a WebSocket connection in JavaScript and how to work with it on the client side.

We describe the further code in the file app/static/index.js.

1. WebSocket initialization

First, we need to get the user and room data. Since we passed it via Jinja2 in a hidden HTML block (#room-data), we will extract it using JavaScript:

// Get data from a hidden element
const roomData = document.getElementById("room-data");
const roomId = roomData.getAttribute("data-room-id");
const username = roomData.getAttribute("data-username");
const userId = roomData.getAttribute("data-user-id");
Enter fullscreen mode Exit fullscreen mode

We will need this data to establish a WebSocket connection.

2. Setting up a WebSocket connection

Let's create a connection to the server:

const ws = new WebSocket(`ws://localhost:8000/ws/chat/${roomId}/${userId}?username=${username}`);

Enter fullscreen mode Exit fullscreen mode

At the deployment stage to the Amverum Cloud service, we will need to replace this link with a live https domain.

What's going on here?

  • We create a WebSocket connection at ws://localhost:8000/ws/chat/.

  • We pass the room ID (roomId), user ID (userId), and username (username) to the URL.

  • The server uses this data to identify the connection.

Additionally, we add event handlers to track the connection state:

ws.onopen = () => {
    console.log("Connection established");
};

ws.onclose = () => {
    console.log("Connection closed");
};

Enter fullscreen mode Exit fullscreen mode

3. Receiving messages

When the server sends a message, the onmessage handler is triggered. We parse the JSON data and add it to the chat area:

ws.onmessage = (event) => {
    const messages = document.getElementById("messages");
    const messageData = JSON.parse(event.data);
    const message = document.createElement("div");

    // Define styles depending on the sender
    if (messageData.is_self) {
        message.className = "p-2 my-1 bg-blue-500 text-white rounded-md self-end max-w-xs ml-auto";
    } else {
        message.className = "p-2 my-1 bg-gray-200 text-black rounded-md self-start max-w-xs";
    }

    message.textContent = messageData.text;
    messages.appendChild(message);
    messages.scrollTop = messages.scrollHeight; // Auto scroll down
};

Enter fullscreen mode Exit fullscreen mode

Code parsing:

  • JSON.parse(event.data) – converts a JSON string to an object.

  • If is_self == true, then the message was sent by the current user, and it is displayed on the right (in blue).

  • Otherwise, the message is from another user, and it is displayed on the left (in gray).

  • Autoscroll (messages.scrollTop = messages.scrollHeight) – so that new messages are always visible.

4. Sending messages

Let's create a function for sending messages:

function sendMessage() {
    const input = document.getElementById("messageInput");
    if (input.value.trim()) {
        ws.send(input.value);
        input.value = '';
    }
}

Enter fullscreen mode Exit fullscreen mode

How ​​does it work?

  1. Take the text from the input field (#messageInput).

  2. If the message is not empty, send it via ws.send().

  3. Clear the input field.

Additionally, to send messages by Enter, add an event handler:

document.getElementById("messageInput").addEventListener("keypress", (e) => {
    if (e.key === "Enter") {
        sendMessage();
    }
});

Enter fullscreen mode Exit fullscreen mode

Now the user can press Enter and the message will be sent automatically.

5. Full chat cycle

  1. Connect to the WebSocket server when the page loads.

  2. Wait for incoming messages and display them in the chat window.

  3. When sending a message, the user enters the text and presses the button or Enter.

  4. The server transmits the message to all participants in the room.

  5. The chat is updated in real time without reloading the page.

Thanks to WebSocket and a small amount of JavaScript code, we have a full-fledged chat that works in real time.

Now we just need to configure the main file (the launch file) and we can start testing our web application.

Final settings and launching the application

At this stage, we only need to make the final settings and launch our application.

We will work with the file app/main.py, where we will implement three key tasks:

  • Initialize the FastAPI application

  • Add processing of static files (for example, JS, CSS)

  • Register all routes

Setting up main.py

Add the necessary imports and describe the basic configuration:

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from app.api.router_page import router as router_page
from app.api.router_socket import router as router_socket

app = FastAPI()

# Connect the folder with static files
app.mount('/static', StaticFiles(directory='app/static'), 'static')

# Register routes
app.include_router(router_socket)
app.include_router(router_page)

Enter fullscreen mode Exit fullscreen mode

Since our web application is responsible for rendering HTML pages itself, we do not need CORS settings.

Launching the application

To start, we use uvicorn, a lightweight ASGI server that we installed earlier.

Basic command:

uvicorn main:app
Enter fullscreen mode Exit fullscreen mode

By default, the server will go up to http://127.0.0.1:8000.

If you need to configure the launch parameters, add flags:

  • --host 0.0.0.0 – makes the server accessible from the external network

  • --port 8005 – specifies a specific port

  • --reload – enables auto-restart when changing the code (useful in development)

Example: Launch on port 8005 with auto-update of the code

uvicorn main:app --port 8005 --reload
Enter fullscreen mode Exit fullscreen mode

After a successful launch, the server is ready to work, and we can connect to the chat! 🎉

Below is a short screencast demonstrating the application in action (3 users in one room):

This is all great, but chatting with yourself is not that exciting. It would be great to make this chat available to everyone. And the Amverum Cloud service will help us with this.

Why Amverum?

I chose this service because it is easy to deploy applications. You can see for yourself. To deploy an application similar to ours, you only need to follow a few simple steps:

  1. Register on the service.

  2. Click on the "Create project" button.

  3. Upload the project files to the service. This can be done either through the interface on the site or using Git commands.

  4. Fill in the necessary configurations on the site (for example, select a programming language for the project or specify a command to launch it).

  5. Attach a free https domain name to the project or register your own.

The deployment process takes only a couple of minutes. In addition, each new user receives a bonus of 1$ to the main balance. The choice of the service is obvious.

Let's perform the deployment.

  1. Register on the Amverum Cloud website, if you haven't registered yet

  2. Click on "Applications"

  3. Then select "Create an application" and follow the step-by-step instructions.

Name the project and choose a tariff plan (a trial plan is suitable for educational purposes)

Name the project and choose a tariff plan (a Tester plan is suitable for educational purposes)

Upload files in a convenient way

Upload files in a convenient way method

Fill in the configurations. The command to run will be: uvicorn app.main:app --host 0.0.0.0 --port 8000

Fill in the configurations. The command to run will be: uvicorn app.main:app --host 0.0.0.0 --port 8000

Next, to activate the free https domain, we need to go to the created project, then go to the "Domains" tab and activate the free domain, as shown below:

Image description

Now we need to make some changes to the static/index.js file. In particular, we must replace the web socket connection string.

Before:

const ws = new WebSocket(`ws://localhost:8000/ws/chat/${roomId}/${userId}?username=${username}`);
Enter fullscreen mode Exit fullscreen mode

After:

const ws = new WebSocket(`wss://easysocketfastap-yakvenalex.amverum.com/ws/chat/${roomId}/${userId}username=${username}`);
Enter fullscreen mode Exit fullscreen mode

Note that we not only replaced the link to the domain name, but also corrected the format from ws to wss. Be careful!

Now all that remains is to rewrite the index.js file in Amverum and rebuild the project.

Image description

You can see the working code here: https://easysocketfastap-yakvenalex.amverum.com. The full source code of the project, as well as other exclusive content that I do not publish on Habr, can be found in my free telegram channel "Easy Path to Python".

By the way, I analyzed the project we talked about today in my half-hour video, available on YouTube and RuTube.

Conclusion

Today's material is a methodological basis that will prepare you for analyzing a more complex and large-scale project: a Telegram bot with MiniApp for anonymous chat "Tete-a-Tet". In the next article, we will analyze this project in detail, and the knowledge gained here will help you master it easier.

I tried to make the material as accessible and understandable as possible, so that even complex topics became simpler. If you found this article useful, don't forget to support it with a like or a comment - it motivates me to prepare even more interesting content.

And if you want even more practice and useful analysis, subscribe to my Telegram channel "Easy Path to Python" - there are already almost 3000 participants, and we regularly discuss interesting topics on development.

That's all for now. See you in the next materials!

Top comments (0)