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.txtIMPORTANT NOTE: Remember to update
requirements.txtevery 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 installThe 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.pyThe 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_playgroundHTML files - seeREADME.mdin there. - Postman - for HTTP communication with Flask endpoints
- This awesome tool - just enter
ws://localhost:5000/chatand connect. You can communicate with server without writing any client-side code! The/chatURI means that you are connecting to achatSocket.IO namespace instead of default/namespace.
To start web client locally:
cd client
yarn startNow 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.exampleto.env.development.localand paste your imgBB API key there.
There is possibility to deploy the app into local docker environment.
- Go into
clientdirectory and rename file.env.production.local.exampleto.env.production.localand paste your imgBB API key there. - Start compose project
docker-compose up -d --buildBoth 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:
cdintoclient/serveryarn start(doyarn installbefore 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 buildfrom theclientdirectory.
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
Deployworkflow on the left. - Click
Run Workflowon the right (selectmainbranch), then click the green button. - Approve the workflow, or ask the owner for approval.
- Wait for workflow to complete. The app is now live!
