Web platform for the annotation of LUS data, built in Next.js 14 (App Router), as part of the LLMs4ULTRA thesis project where the goal is to use a dataset for fine-tuning a Vision-Language Model (VLM) to make it capable of producing a diagnosis based on lung ultrasound (LUS) videos.
The platform is available at the following link: https://llms4ultra.disi.unitn.it
The platform is composed of two main parts: the client and the server.
- The client, built in Next.js, is responsible for the user interface and the interaction with the user, as well as the management of the state and the data, using
Redux Toolkit
, the authentication, usingAuth.js (v5)
via JWT, the registration/login forms, usingReact Hook Form
andZod
, and the verification/reset of the account using emails sent viaGmail
. The UI is built usingTailwindCSS
,Framer Motion
,Radix UI
andMaterial-UI
. - The server, built in
Node.js
andExpress.js
, acts as a REST API and it is responsible for theSocket.IO
real-time communications, the assignment of videos to the users, the interaction with the database and the management of the data.
- Node.js 21.17.1 or higher
- npm 10.7.0 or higher
- Docker 25.0.3 or higher (if you want to use a local MongoDB server)
- MongoDB account (if you want to use MongoDB Atlas)
- Resend account (if you want to use Resend as the email provider)
- Gmail account (if you want to use NodeMailer with your Gmail account)
- Nginx 1.25.5 or higher (if you want to use a reverse proxy for deployment)
- Let's Encrypt (if you want to use SSL)
The platform is deployed on a VPS, hosted by the University of Trento, with Ubuntu 22.04
, using Nginx
as a reverse proxy. The database is hosted on MongoDB Atlas
, or alternatively on a Docker
container with a replica set of three nodes. The SSL
certificate is provided by Let's Encrypt
. The platform is managed using pm2
to run the servers in the background and restart them automatically in case of a crash.
To work properly in a firewalled VPS, the following ports need to be open:
- 80 (HTTP)
- 443 (HTTPS)
And for the outbound traffic:
- 27015-27017 (MongoDB)
- 25, 465, 587 (SMTP)
To create the reverse proxy with Nginx
, a new Server Block is needed, and the following configuration is used:
server {
server_name llms4ultra.disi.unitn.it; # Listen to requests for this domain
# Redirect Socket.IO requests to the backend server
location /socketIO {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://localhost:3000; # Local address of the Express.js server
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
# Redirect everything else to the Next.js server. The server API is not exposed to the client
location / {
proxy_pass http://localhost:5174; # Local address of the Next.js server
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/llms4ultra.disi.unitn.it/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/llms4ultra.disi.unitn.it/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}server {
if ($host = llms4ultra.disi.unitn.it) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name llms4ultra.disi.unitn.it www.llms4ultra.disi.unitn.it;
return 404; # managed by Certbot
}
To install the required node modules, the following commands are used:
cd client
npm ci
cd ../server
npm ci
The npm ci
command performs a clean install. It is used to install the exact versions of the packages listed in the package-lock.json
file, without updating nor modifying it.
The platform can use a local MongoDB server, or a MongoDB Atlas cluster.
N.B. You HAVE TO change the environment variable
USE_REMOTE_DB
in the./server/.env
file accordingly (true
,false
), since it is used as a parameter of theconnect()
function inside the./server/index.ts
file to connect to the desired database. (e.g.MONGO_URI
orMONGO_URI_LOCAL
).
Also, you HAVE TO change the datasource
url
in the./client/prisma/schema.prisma
file accordingly (DATABASE_URL
orDATABASE_URL_LOCAL
) and then run in the terminalcd client && npx prisma generate && npx prisma db push
. This command should be run every time the schema or the database connection changes.
A folder named mongo3
is needed inside the ./server
directory, containing the following files:
username.txt
containing the username for the MongoDB server admin userpassword.txt
containing the password for the MongoDB server admin userdata
folder (empty) used to persist the data after the container is stopped
To start a local MongoDB server with a three replica set in a Docker container, the following command is used inside the ./server
directory:
docker compose up -d
In case of an error about the host.docker.internal
not being resolved, the following line needs to be added to the /etc/hosts
file:
127.0.0.1 host.docker.internal
To use MongoDB Atlas, a cluster needs to be created in their website, and the connection string needs to be added to the .env
file inside the ./client
and ./server
directories.
Inside the ./client
directory, two dotenv
files are needed.
- The
.env
file, used byPrisma
should contain the following environment variables:
DATABASE_URL=<your-remote-mongodb-atlas-url> # e.g. mongodb+srv://<username>:<password>@<cluster-url>/<database>?retryWrites=true&w=majority
DATABASE_URL_LOCAL<your-local-mongodb-url> # e.g. mongodb://<username>:<password>@127.0.0.1:27017,127.0.0.1:27018,127.0.0.1:27019/<database>?retryWrites=true&w=majority
- The
.env.local
file, used byNext.js
should contain the following environment variables:
SERVER_URL_BASE=<server-url> # e.g. http://localhost:3000
NEXT_PUBLIC_SERVER_PORT=<server-port> # e.g. 3000
NEXT_PUBLIC_BASE_URL=<your-client-base-url> # e.g. http://localhost:5174 or https://llms4ultra.disi.unitn.it
AUTH_SECRET=<secret-key-for-auth-js> # create a random string (e.g. using openssl rand -hex 32)
# if you want to use Resend as the email provider
RESEND_API_KEY=<your-resend-api-key> # create an account on Resend and get the API key
# If you want to use NodeMailer with your Gmail account
SMTP_EMAIL=<your-gmail-address>
SMTP_PASS=<gmail-application-password> # create an application password on your Gmail account under the "Security->Two-Step Verification" section
REPLY_TO_EMAIL=<your-email> # if you want to use a different email for the "reply-to" field
Inside the ./server
directory, a .env
file is needed, containing the following environment variables:
USE_REMOTE_DB=true # true if you want to use MongoDB Atlas, false if you want to use a local MongoDB server
PORT=<server-port> # e.g. 3000
MONGO_URI=<your-remote-mongodb-atlas-url> # e.g. mongodb+srv://<username>:<password>@<cluster-url>/<database>?retryWrites=true&w=majority
MONGO_URI_LOCAL=<your-local-mongodb-url> # e.g. mongodb://<username>:<password>@127.0.0.1:27017,127.0.0.1:27018,127.0.0.1:27019/<database>?retryWrites=true&w=majority
To generate the Prisma client, the following command is used inside the ./client
directory:
npx prisma generate
npx prisma db push
These commands have to be run every time the schema or the database connection changes.
The video files are stored in the ./client/public/videos
directory, and they are served statically by the Next.js server.
To populate the database with the initial data, the following command is used inside the ./server
directory:
npm run populateDB
It will create the entries for the videos stored in the ./client/public/videos
directory.
To reset the database, the following command is used inside the ./server
directory:
npm run resetDB
It will ask for a confirmation on which collections to delete, and then it will reset the database accordingly. After that, this command should be used to populate the database again to avoid Prisma errors:
npx prisma db push
To start the servers, the following commands are used:
cd client
npm run build
npm run start
... or if you want to start it in production mode using pm2
such that it runs in background and restarts automatically in case of a crash, in place of npm run start
:
pm2 start npm --name "client" -- start
In a different terminal:
cd server
npm run build
npm run start
...or if you want to start the it in production mode using pm2
so that it runs in background and restarts automatically in case of a crash, in place of npm run start
:
pm2 start npm --name "server" -- start
To start the servers in development mode, the following commands are used:
cd client
npm run dev
In a different terminal:
cd server
npm run dev
Always remember to change the settings as explained in the
MongoDB Server
section if you want to change the database connection (remote or local).
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.