A distributed system example - chat rooms project using Socket.io. Written as an experiment to try out Flask and Socket.io.
The app is not production ready, it has some design flaws and bad practices. However, it may serve as an example. Please contact me if you have any questions.
-
Simple chat application, with the following rules:
- Type in a nickname and enter chat
- Join any chat room by selecting it from the list on the left
- Users cannot see messages from before they joined
- When switching rooms, previous chat history is no longer visible to users after rejoining
- When last user leaves a room, it is automatically deleted (except persistent rooms like the default one)
-
Possibility to send image attachments
-
Displays list of active users
-
Automatically generated avatars for users and rooms
-
Technical stack:
- React/Typescript frontend + chat-ui-kit-react lib
- Python/Flask backend
- Socket.IO for websocket communication, using Flask-SocketIO library
- Node.js/Express server acting as API Gateway/Proxy for Python server. Also used for hosting React client static files.
- Docker-compose based architecture
- Github Actions CI pipeline with deploy to VPS Docker with nginx-proxy
- Attachment Image hosting at imgbb.com
Requirements:
- Python 3.8+
- Node 14 LTS
- Yarn 1.22 (The classic stable version)
- [optional] Docker Desktop & Docker Compose
Installing API server python dependencies:
cd server
pip3 install -r requirements.txt
IMPORTANT NOTE: Remember to update
requirements.txt
every time you add a new dependency! It's a good idea to run this each time you pull from git.
Installing Web Client dependencies
cd client
yarn install
The above step should be ran each time you pull from git (during active development), because of possible dependency changes in
package.json
.
API Server is based on Python flask-socketio
. To start development server:
cd server
python3 app.py
The API server starts at http://localhost:5000.
To test server without worrying about running heavyweight React client, you can use:
- prepared for this purpose
server/browser_playground
HTML files - seeREADME.md
in there. - Postman - for HTTP communication with Flask endpoints
- This awesome tool - just enter
ws://localhost:5000/chat
and connect. You can communicate with server without writing any client-side code! The/chat
URI means that you are connecting to achat
Socket.IO namespace instead of default/
namespace.
To start web client locally:
cd client
yarn start
Now you can run app at http://localhost:3000. It requires the API server to be running.
In order to be able to send attachments, you need to rename
.env.development.local.example
to.env.development.local
and paste your imgBB API key there.
There is possibility to deploy the app into local docker environment.
- Go into
client
directory and rename file.env.production.local.example
to.env.production.local
and paste your imgBB API key there. - Start compose project
docker-compose up -d --build
Both client and API server containers will be rebuilt (--build
flags) and finally the client app will be listening on http://localhost:4121. The API server will be available at http://localhost:4121/api/
Client is hosted in a separate container using express
server. It also acts as a proxy to the Flask API server at /api
endpoint. The server code is located at client/server/server.js
.
To start the proxy server:
cd
intoclient/server
yarn start
(doyarn install
before if running for the first time)- The proxy server will start at http://localhost:4121. If Python API server is listening at port
5000
, it will be available at http://localhost:4121/api. - To make client app available at port
4121
, you need to build it first by runninyyarn build
from theclient
directory.
Currently, the deployment workflow is down, because the app is unused. In order to enable it, please follow this instruction.
To deploy app to publicly exposed production server (contact me to get address), do the following:
- Create a Pull Request with your changes.
- Wait for all checks to complete and for approval code review.
- Merge into
main
. - Go into Actions tab on GitHub (top menu).
- Wait again for both Client and Server workflows to go green.
- Enter
Deploy
workflow on the left. - Click
Run Workflow
on the right (selectmain
branch), then click the green button. - Approve the workflow, or ask the owner for approval.
- Wait for workflow to complete. The app is now live!