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 FormandZod, and the verification/reset of the account using emails sent viaGmail. The UI is built usingTailwindCSS,Framer Motion,Radix UIandMaterial-UI. - The server, built in
Node.jsandExpress.js, acts as a REST API and it is responsible for theSocket.IOreal-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 ciThe 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_DBin the./server/.envfile accordingly (true,false), since it is used as a parameter of theconnect()function inside the./server/index.tsfile to connect to the desired database. (e.g.MONGO_URIorMONGO_URI_LOCAL).
Also, you HAVE TO change the datasource
urlin the./client/prisma/schema.prismafile accordingly (DATABASE_URLorDATABASE_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.txtcontaining the username for the MongoDB server admin userpassword.txtcontaining the password for the MongoDB server admin userdatafolder (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 -dIn 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
.envfile, used byPrismashould 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.localfile, used byNext.jsshould 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" fieldInside 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=majorityTo generate the Prisma client, the following command is used inside the ./client directory:
npx prisma generate
npx prisma db pushThese 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 populateDBIt 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 resetDBIt 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 pushTo 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" -- startIn 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" -- startTo start the servers in development mode, the following commands are used:
cd client
npm run devIn a different terminal:
cd server
npm run devAlways remember to change the settings as explained in the
MongoDB Serversection 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.