2nd year IT Bachelor β group project A real-time chat application built with C++ (server) and Qt (client), inspired by MSN Messenger (Wizz feature).
- Features
- Tech Stack
- Architecture
- Project Structure
- Dependencies
- Getting Started
- API & Endpoints
- Development
- User registration and login with JWT authentication
- Direct messages between users
- Group channels
- Channel invitations β accept, reject or cancel
- Real-time messaging via WebSocket
- Message history per channel
- Unread message count tracking per channel
- Delete account
- Wizz
| Layer | Technology |
|---|---|
| Server build & runtime | Docker & Docker Compose |
| Server | C++17 with Crow v1.3.0 (HTTP + WebSocket) |
| Client | Qt 6.4.2 minimum, 6.10.2 recommended (Widgets + WebSocket) |
| Database | MySQL 9.6.0 |
The Qt client runs on the host machine. The server and the database each run in their own Docker container, on the same Docker network β so the server reaches the DB using the container name as hostname, no IP needed.
The client communicates with the server over two channels:
- HTTP β for spontaneous one-off actions and client request to change DB state.
- WebSocket β for everything real-time (push notification for other concerned devices)
Every action goes through token authentication first, then an access check before anything is processed.
wizzMania/
βββ server/ β C++ server, DDD architecture (7 domains)
βββ client/ β Qt6 client
βββ common/ β Shared message types and structures (client β server)
βββ tests/ β Server unit tests + debug web client
βββ docs/ β API documentation
βββ docker-compose.yml
βββ Dockerfile.server
βββ init.sql β Database schema + seed data
βββ .env.template β Environment variable template
The server follows a Domain-Driven Design (DDD) approach, organized into 7 domains:
auth Β· channel Β· invitation Β· message Β· user Β· initialization Β· websocket
Each domain has its own controller and service. Some controllers call across services when needed.
common/ holds the message types and structures exchanged between the client and the server (over HTTP and WebSocket). This keeps both sides in sync and lets the client and server teams work independently without breaking the protocol.
It also contains pure C++ helpers that can be needed on both sides.
All server-side dependencies are handled automatically inside the Docker container (using ubuntu:22.04 image) β nothing to install on your machine for the server.
All client-side dependencies need to be installed on your host machine (see Getting Started below).
| Library | Version | Where | Purpose |
|---|---|---|---|
| Crow | v1.3.0 | Server (Docker) | HTTP and WebSocket framework |
| jwt-cpp | v0.7.0 | Server (Docker) | JWT token creation and validation |
| nlohmann/json | v3 | Server (Docker) | JSON serialization/deserialization |
| libbcrypt | no releases β commit d6523c3 (Jun 22, 2021) |
Server (Docker) | bcrypt password hashing |
| Boost | system | Server (Docker) | Async I/O (required by Crow) |
| libmysqlclient-dev | system | Server (Docker) | Low-level C library to connect and send queries to MySQL |
| mysql-client | system | Server (Docker) | MySQL CLI tools β useful for debugging inside the container |
| libmysqlcppconn-dev | system | Server (Docker) | Official C++ wrapper over libmysqlclient β this is what the server code uses directly |
| Google Test / Mock | system | Server (Docker) | Unit testing framework |
| CMake | β | Client (host) | Build system for the Qt client |
Note on libbcrypt: this library has no official releases or tags. The server was built and tested against commit
d6523c370de6e724ce4ec703e2449b5b028ea3b1(June 22, 2021). If the build breaks in the future, check that commit or update theDockerfile.serveraccordingly.
Note on MySQL libraries:
libmysqlclient-devis the C foundation,libmysqlcppconn-devis the C++ layer your server code actually talks to, andmysql-clientis just a convenience tool for manual DB access inside the container.
A .env.template file is provided. Copy it and fill in your values before doing anything else:
cp .env.template .envKey variables to know:
| Variable | Default | Required | Description |
|---|---|---|---|
MYSQL_ROOT_PASSWORD |
β | β | Root password for the MySQL container. Only used internally by MySQL, not by the server. |
MYSQL_DATABASE |
wizzmania |
β | Name of the database that will be created and used by the server. |
MYSQL_USER |
wizzuser |
β | MySQL user the server connects as. |
MYSQL_PASSWORD |
β | β | Password for MYSQL_USER. All four MYSQL_* variables must be set or the DB container will fail to start. |
DB_PORT |
3306 |
β | MySQL port exposed on your host. Change it if you already have a local MySQL running on 3306. |
SERVER_PORT |
8888 |
β | Port the C++ server listens on (also exposed by Docker). |
SERVER_IP |
127.0.0.1 |
β | IP the client uses to reach the server. Keep as localhost for local development. |
SECRET_KEY |
β | Secret used to sign JWT tokens. If left empty, the server falls back to default_secret (defined in auth_service.hpp) β always set this in production. |
β οΈ All fourMYSQL_*variables must be set or the database container will fail to start β and since the server depends on it, it will fail too.
- Install and start Docker Desktop
- Make sure Docker is installed
- Make sure your
.envis ready and run:
docker compose upThat's it. Docker Compose will:
- Start the MySQL container and initialize the database from
init.sql - Build the server container, run the tests, and if they pass β build and start the server
β οΈ If any test fails, the server will not start. Check the logs withdocker compose logs -f server.
First, check if you already have the required tools:
qmake6 --version && cmake --versionIf anything is missing, you have two options:
Option A β via WSL (Windows Subsystem for Linux):
sudo apt install qt6-base-dev qt6-base-dev-tools
sudo apt install cmake
sudo apt install qt6-websockets-devOption B β via the Qt official installer:
Download Qt from https://www.qt.io/download-open-source (free community version, account required).
Install Qt with gcc, g++ and cmake to avoid path issues.
Qt 6.4.2 minimum, 6.10.2 was used for development.
Then add these to your PATH:
C:\Qt\Tools\QtCreator\bin
C:\Qt\6.x.x\mingw_64\bin
Build the client:
From PowerShell:
./client/build-client.batFrom Git Bash:
powershell.exe -NoProfile -Command "& '$(cygpath -w ./client/build-client.bat)'"Run the client:
./client/build/wizzmania-client.exeWSL: if you get EGL/MESA errors, add
export LIBGL_ALWAYS_SOFTWARE=1to your~/.bashrc
Check your tools first:
qmake6 --version && cmake --versionInstall if needed:
sudo apt install qt6-base-dev qt6-base-dev-tools
sudo apt install cmake
sudo apt install qt6-websockets-devMake the scripts executable (only needed once):
chmod +x ./client/build-client.sh
chmod +x ./client/run-client.shBuild then run:
./client/build-client.sh
./client/run-client.shWSL only: if you get EGL/MESA rendering errors, add this to your ~/.bashrc and restart your terminal:
export LIBGL_ALWAYS_SOFTWARE=1WSL has no GPU access, so Qt's hardware OpenGL rendering fails. This flag forces software rendering instead.
All available HTTP routes and WebSocket message types are documented in /docs/API.md.
Refer to it to test the project manually or understand the client β server protocol.
Useful when actively working on the client β not needed just to run the project.
# Suppress Qt internals, keep your app logs
QT_LOGGING_RULES="qt.*=false" ./wizzmania-client
# Full debug output
QT_LOGGING_RULES="*.debug=true;*.info=true;qt.network.*=true" ./wizzmania-client
# Silent (no logs at all)
QT_LOGGING_RULES="*=false" ./wizzmania-clientA lightweight web client is available in tests/web_client/ for quickly testing HTTP endpoints and WebSocket behaviour β useful if you don't want to set up Qt just to check the API.
- Create a
secret.jsfile intests/web_client/with the same values as your.env:
export const SERVER_IP = "localhost";
export const SERVER_PORT = 8888;- Start a local HTTP server from that folder:
cd tests/web_client
python3 -m http.server 8880- Open
http://localhost:8880in your browser
Make sure the server is already running before opening the client.
SERVER_IPandSERVER_PORTmust match the values in your.env.
This project was made by:


