• Martin Thoma
  • Home
  • Categories
  • Tags
  • Archives
  • Support me

Flask Chat - Part I

Contents

  • Architecture
  • Project Structure
  • How it works
  • User Experience
    • General Theme
    • New Messages
  • Why this is awful
  • Complete Project
  • Free Chat Servers
  • See also

Chat applications are everywhere nowadays. The two best-known ones are probably Slack and WhatsApp. If you keep the amount of users low (e.g. less than 100) and the number of features limited, then it is actually pretty easy to create such a chat app.

I've create a small proof of concept chat app with Flask and jQuery. It runs in the browser.

Architecture

We will keep it simple for this tutorial:

Chat App
Chat App

We store the messages - and only that - in a single table in a SQLite database. We have an API which has one endpoint messages which allows to GET messages (filtered by id) and to POST a new message.

The backend is done with Flask.

The front end is partially done with Jinja2 and partially with jQuery.

Project Structure

The folder structure is typical for Flask applications:

.
├── app
│   ├── api.py
│   ├── docs
│   ├── __init__.py
│   ├── main
│   │   ├── __init__.py
│   │   └── routes.py
│   ├── models.py
│   ├── static
│   └── templates
├── Dockerfile
├── migrations
├── pyproject.toml
├── README.md
├── requirements.txt
├── start.sh
└── wsgi.py

In the root directory, you have a start.sh which uses the wsgi.py to start a gunicorn server. The pyproject.toml gives some basic configuration.

Within the app directory, there is a single blueprint called "main". The models.py defines the sqlalchemy database models, the api.py defines the REST API with flask restx.

The front end is in the templates directory.

How it works

When a new user opens the website, they get a session variable with a unique identifier. They receive all messages which were ever written (yes, in a productive system this is an awful idea) and they store the latest message ID they have seen.

Locally, jQuery asks every 500ms for new messages. For this request, it gives the latest message it has seen. This means most of the time the server returns an empty response.

When the client sends a new message, it is stored in the database.

That's it.

User Experience

General Theme

The key CSS classes you have are:

  • message: It can either be one you received or one you sent.
  • conversation: The block that contains the stream of messages.

See this codepen for a nice the theme by Rumbiiha Swaibu.

New Messages

A key point that took me a bit to implement is to add the most recent messages at the bottom and keep scrolling with the most recent ones - but only if you didn't scroll up before.

Why this is awful

Missing core functionality:

  • Registration and Authentication: It is important who writes something. So people want to know the sender. In the system above, it is super easy to change the ID to somebody elses ID. To have arbitrary many IDs. It is hard to know who writes something. This topic comes with a lot of other topics like single sign on (SSO), 2FA / MFA, password recovery...
  • Formatting: Allow users to format messages (bold, italic, links, math mode, ...)
  • Chatrooms: People want to have private conversations. Conversations splitted by topic.
  • Search: Once you have different rooms, you might want to search across rooms.
  • Images
  • File sharing

Other missing functionality:

  • Voice over IP (calls) and Videotelephony (Video chat)
  • Themes: Let users change the default looks
  • Tennants: Besides chats / chatrooms, you might want to run the chat appliction as a service for organizations. They have their own (seperate) users and chat rooms. Maybe have some possibilities for customization.

Engineering:

  • Scalability: If the database comes to its limits, you have to get a bigger machine. Other databases like AWS DynamoDB might have better behaviour.
  • Backups were not even mentioned
  • Polling: Pining the server twice per second is no big deal if you have few users. But the more users you get, the worse this will become.
  • Pagination: Getting all messages in the beginning is a really bad idea.
  • Front Ends: You might want way more. For example, native apps for smartphones.
  • Protocols: Adding support for XMPP to allow usage of other clients (IRC seems to be outdated; Matrix could be an alternative according to this German post)

Complete Project

If you want to get the complete project and look at the code, here you are:

$ git clone https://github.com/MartinThoma/flask-chat.git
$ git checkout v1.0

Free Chat Servers

In case you want to look at more professional chat server projects:

Name License Core Language XMPP LDAP
Rocketchat MIT JavaScript ✔️ ✔️
Let's Chat MIT JavaScript ✔️ ✔️
Mattermost MIT / GNU AGPL v.3.0 Go not directly ✔️
Riot.im Apache v2 JavaScript No, but matrix not directly

See also

  • Wikipedia: Slack Technologies, 2019-12-17.
  • Rumbiiha swaibu: WhatsApp in Pure CSS and JS

Published

Dez 20, 2019
by Martin Thoma

Category

Code

Tags

  • Flask 6
  • Python 141

Contact

  • Martin Thoma - A blog about Code, the Web and Cyberculture
  • E-mail subscription
  • RSS-Feed
  • Privacy/Datenschutzerklärung
  • Impressum
  • Powered by Pelican. Theme: Elegant by Talha Mansoor