Skip to content

rajayush6200/VitalLink

Repository files navigation


VitalLink Logo

VitalLink Typing SVG

Every Second Counts. Every Drop Matters.

A production-grade, full-stack Blood Bank Management System powered by a custom-trained TensorFlow AI model that performs real-time blood sample infection screening — bridging the gap between donors, recipients, and healthcare providers.


Live App Backend API AI Service

Node.js Express.js MongoDB Python TensorFlow Flask

HTML5 CSS3 JavaScript Render MIT License

Architecture AI Model Database Auth Render


🌐 Live Demo  ·  Architecture  ·  Setup Guide  ·  API Docs  ·  AI Engine



Table of Contents

Click to expand / collapse


Project Overview

"In India alone, the demand for blood exceeds supply by 3 million units annually. VitalLink was built to solve this with technology."

VitalLink is a healthcare-grade, production-deployed blood bank management system that tackles one of the most critical challenges in modern healthcare: the safe, efficient, and intelligent connection between blood donors, recipients, and healthcare administrators.

🩺 The Problem It Solves

Challenge VitalLink Solution
Manual blood sample screening is error-prone & slow Custom-trained TensorFlow AI analyzes blood samples in real-time
No centralized blood request management Full-stack request workflow with admin approval system
Donors with blood infections slip through AI infection detection blocks ineligible donors at registration
Hospitals lack transparency into blood requests Admin dashboard with live stats, inventory charts & activity feed
No paper trail for blood approvals PDF generation for approved blood requests via jsPDF
Announcements are fragmented Priority-based announcement system (Normal / Urgent)

💡 Core Innovation

What makes VitalLink unique is its three-service microservices architecture where:

  1. A Vanilla JS frontend (deployed as a static site) handles the user experience
  2. A Node.js/Express REST API (backend service) manages all business logic and database operations
  3. A Python Flask AI microservice runs a custom MobileNetV2-based TensorFlow Lite model for real-time blood infection analysis

These three services communicate seamlessly across the cloud, all deployed independently on Render.



Key Features

🔐 Authentication & Security

  • Role-based access controluser and admin roles enforced server-side
  • bcryptjs password hashing with salt rounds for secure credential storage
  • JWT-ready architecture with session management via localStorage
  • Protected frontend routes — unauthorized users redirected to login immediately
  • Admin-only access — dashboard checks user.role === 'admin' before rendering
  • Database availability guard — all auth routes check MongoDB state before processing

🩸 Donor Registration & AI Screening

  • Multi-field registration form — Name, Email, Age (18–60), Blood Group
  • Blood sample image upload with Multer file handling on the backend
  • Real-time AI blood screening — image sent to Flask AI service for infection detection
  • Animated progress bar — smooth fake-progress UX while AI processes the image
  • Binary diagnosis resultNORMAL (eligible) or INFECTION DETECTED (blocked)
  • Confidence score display — numerical confidence from model output shown to user
  • Downloadable Donor ID Card — generated via html2canvas as a PNG certificate
  • Admin AI stats tracking — normal vs. infected donor counts stored and visualized

🆘 Blood Request System

  • Emergency blood request form — Name, Phone, Blood Group, Reason for request
  • Duplicate request prevention — users cannot submit if an active request (Pending/Approved) exists
  • Admin approval workflow — Approve / Reject with optional rejection reason
  • Request status tracking — Pending → Approved / Rejected lifecycle
  • PDF slip generation — approved requests downloadable as official Blood Request PDFs via jsPDF
  • Status badge visualization — color-coded Pending 🟡 / Approved 🟢 / Rejected 🔴

🖥️ Admin Dashboard

  • Live statistics cards — Total Requests, Pending, Approved, Rejected counts
  • Blood Stock Inventory Chart — Chart.js bar chart for blood group availability visualization
  • Live Activity Feed — real-time scrollable feed of latest platform actions
  • Donor management table — all AI-verified normal donors listed with blood group & age
  • User management — full user list with delete capability
  • Message center — view and reply to user messages inline
  • Announcement system — post urgent/normal announcements with blood group tags
  • AI Insights panel — doughnut chart showing normal vs. infected scan statistics
  • Dark glassmorphism UI — premium dark-mode admin panel with floating animations

💬 Messaging & Communication

  • User → Admin messaging — users submit messages via the Contact page
  • Admin replies inline — admins reply from dashboard, users see replies in their portal
  • User message portal — "My Messages" modal shows thread with admin responses

🔔 Announcements System

  • Admin-broadcast announcements — post platform-wide announcements from dashboard
  • Priority levelsNormal (green) and Urgent (red, pulsing) visual differentiation
  • Blood group targeting — announcements can specify affected blood group
  • Date scheduling — announcements include optional event/deadline date
  • Public visibility — announcements visible on login page for immediate awareness

🎨 UI/UX Design System

  • Glassmorphism design languagebackdrop-filter: blur(), translucent cards throughout
  • Responsive layouts — mobile-first CSS with breakpoints at 480px, 768px, 900px
  • Micro-animations — pulse logo, slideInLeft/Right sidebar, fadeInUp cards, zoomIn modals
  • CSS custom properties — design token system (--primary-red, --glass-bg, --shadow)
  • Dark/Light mode support — toggle theme functionality built in
  • Chart.js integration — beautiful, animated charts for data visualization
  • jsPDF + html2canvas — client-side PDF and image generation for official documents


Tech Stack

Frontend

Technology Purpose Version
HTML5 Semantic structure, multi-page app Latest
CSS3 Glassmorphism, animations, responsive design Latest
Vanilla JavaScript DOM manipulation, fetch API, SPA logic ES2020+
Chart.js Blood inventory & AI stats visualization CDN
jsPDF PDF generation for approved requests 2.5.1
html2canvas Donor ID card image export 1.4.1

Backend

Technology Purpose Version
Node.js Runtime environment v18+
Express.js REST API framework, routing, middleware 4.19.2
Mongoose MongoDB ODM, schema validation 8.4.0
Multer Multipart file upload handling 1.4.5-lts
bcryptjs Password hashing & verification 3.0.3
node-fetch HTTP client for AI service communication 3.3.2
dotenv Environment variable management 17.2.3
cors Cross-Origin Resource Sharing middleware 2.8.5
nodemon Development auto-restart 3.0.3

AI Service

Technology Purpose Version
Python AI service runtime 3.11+
Flask Lightweight REST API for AI inference Latest
TensorFlow Deep learning model inference 2.20.0
TensorFlow Lite Optimized model format for deployment 2.20.0
MobileNetV2 Base CNN architecture (transfer learning) ImageNet weights
NumPy Numerical array operations Latest
Pillow Image preprocessing & loading Latest
Gunicorn Production WSGI server Latest

Infrastructure & Deployment

Service Role
MongoDB Atlas Cloud database (M0 free tier, production-ready)
Render (Static) Frontend hosting — vitallink-app-2jb5.onrender.com
Render (Node) Backend API — vitallink-backend.onrender.com
Render (Python) AI microservice — vitallink-ai-service.onrender.com
render.yaml Infrastructure-as-Code, Blueprint deployment


System Architecture

High-Level Architecture

graph TB
    subgraph CLIENT["Client Layer (Static Frontend - Render)"]
        U["User Browser"]
        A["Admin Browser"]
    end

    subgraph BACKEND["Backend API - Node.js / Express (Render)"]
        API["REST API Server - Port: 3000"]
        AUTH["/api/auth - register | login"]
        DONORS["/api/donors - POST | GET | ai-stats"]
        REQUESTS["/api/requests - CRUD + status"]
        MESSAGES["/api/messages - submit | reply"]
        ANNOUNCE["/api/announcements - CRUD"]
        USERS["/api/users - list | delete"]
        ANALYZE["/api/analyze - standalone scan"]
        AI_CLIENT["aiClient.js - HTTP Bridge"]
    end

    subgraph AI["AI Microservice - Python / Flask (Render)"]
        FLASK["Flask App - Gunicorn WSGI"]
        MODEL["TFLite Interpreter - MobileNetV2"]
        INFER["Binary Classification - normal | infected"]
    end

    subgraph DB["Database - MongoDB Atlas"]
        USERS_COL[("users")]
        DONORS_COL[("donors")]
        REQUESTS_COL[("bloodrequests")]
        MESSAGES_COL[("messages")]
        ANNOUNCE_COL[("announcements")]
    end

    U -->|"HTTPS Fetch"| API
    A -->|"HTTPS Fetch"| API
    API --> AUTH & DONORS & REQUESTS & MESSAGES & ANNOUNCE & USERS & ANALYZE
    DONORS --> AI_CLIENT
    ANALYZE --> AI_CLIENT
    AI_CLIENT -->|"POST imageBase64 JSON"| FLASK
    FLASK --> MODEL --> INFER
    INFER -->|"result + confidence"| AI_CLIENT
    AUTH --> USERS_COL
    DONORS --> DONORS_COL
    REQUESTS --> REQUESTS_COL
    MESSAGES --> MESSAGES_COL
    ANNOUNCE --> ANNOUNCE_COL
Loading

Authentication Flow

sequenceDiagram
    participant U as User
    participant F as Frontend
    participant B as Backend API
    participant DB as MongoDB

    U->>F: Enter email + password
    F->>B: POST /api/auth/login
    B->>DB: findOne(email)
    DB-->>B: User document
    B->>B: bcrypt.compare(password, hash)
    alt Password Valid
        B-->>F: 200 { id, name, email, role }
        F->>F: localStorage.setItem(user, data)
        F-->>U: Redirect to index.html or admin-dashboard.html
    else Password Invalid
        B-->>F: 400 { error: Invalid credentials }
        F-->>U: Show error message
    end
Loading

AI Blood Screening Flow

sequenceDiagram
    participant U as Donor
    participant F as Frontend
    participant B as Node.js Backend
    participant AI as Flask AI Service
    participant DB as MongoDB

    U->>F: Upload blood sample image
    F->>F: Start animated progress bar
    F->>B: POST /api/donors (multipart/form-data)
    B->>B: Multer saves image to /uploads
    B->>B: fs.readFileSync to base64 encode
    B->>AI: POST /analyze { imageBase64 }
    AI->>AI: Load TFLite interpreter
    AI->>AI: Preprocess to 224x224 to normalize
    AI->>AI: interpreter.invoke()
    AI-->>B: { result: normal or infected, confidence: 0.87 }
    alt Normal Blood Sample
        B->>DB: Save Donor { ai_result: normal }
        B-->>F: 201 { result: normal, confidence }
        F-->>U: Show Donor ID Card + Download option
    else Infection Detected
        B->>DB: Save Donor { ai_result: infected }
        B-->>F: 200 { result: infected, confidence }
        F-->>U: Registration blocked, infection detected
    end
Loading

Blood Request Lifecycle

stateDiagram-v2
    [*] --> Submitted: User fills Need Blood form
    Submitted --> Pending: POST /api/requests
    Pending --> AdminReview: Admin opens dashboard
    AdminReview --> Approved: Admin clicks Approve
    AdminReview --> Rejected: Admin clicks Reject + reason
    Approved --> PDFGenerated: User downloads PDF slip
    Rejected --> [*]: User notified with reason
    PDFGenerated --> [*]: Process complete
Loading

Database Entity Relationships

erDiagram
    USERS {
        ObjectId _id PK
        string name
        string email
        string password_hash
        string role
        date createdAt
        date updatedAt
    }

    DONORS {
        ObjectId _id PK
        string name
        string email
        number age
        string blood_group
        string image_path
        string ai_result
        number confidence
        date createdAt
    }

    BLOOD_REQUESTS {
        ObjectId _id PK
        ObjectId userId FK
        string name
        string phone
        string bloodGroup
        string reason
        string status
        string rejectionReason
        date createdAt
        date updatedAt
    }

    MESSAGES {
        ObjectId _id PK
        ObjectId userId FK
        string userName
        string userEmail
        string message
        string reply
        date createdAt
    }

    ANNOUNCEMENTS {
        ObjectId _id PK
        string title
        string message
        string bloodGroup
        date date
        string priority
        date createdAt
    }

    USERS ||--o{ BLOOD_REQUESTS : submits
    USERS ||--o{ MESSAGES : sends
Loading


Folder Structure

VitalLink/
│
├── 📄 render.yaml                    # Render Blueprint — Infrastructure as Code
├── 📄 package.json                   # Root package (workspace config)
├── 📄 .gitignore                     # Git ignore rules
│
├── 🌐 frontend/                      # Static HTML/CSS/JS Application
│   ├── 📄 index.html                 # Home page (protected, login required)
│   ├── 📄 login.html                 # Login & registration page
│   ├── 📄 signup.html                # User registration page
│   ├── 📄 donate.html                # Donor registration + AI screening form
│   ├── 📄 need-blood.html            # Blood request submission form
│   ├── 📄 admin-dashboard.html       # Full admin panel (role-protected)
│   ├── 📄 blood-availability.html    # Live blood stock availability
│   ├── 📄 blood-graph.html           # Blood analytics & charts
│   ├── 📄 about.html                 # About VitalLink page
│   ├── 📄 why-donate.html            # Blood donation awareness page
│   ├── 📄 contact.html               # Contact & message submission
│   ├── 📄 privacy-policy.html        # Privacy policy
│   ├── 📄 terms-of-service.html      # Terms of service
│   ├── 📄 _redirects                 # Render static routing rules
│   │
│   ├── 📁 css/
│   │   └── 📄 style.css              # Global design system & tokens
│   │
│   ├── 📁 js/
│   │   ├── 📄 config.js              # API base URLs (backend + AI service)
│   │   └── 📄 footer.js              # Shared footer component
│   │
│   └── 📁 assets/
│       ├── 🖼️ blood-drop.png         # Logo mark
│       ├── 🖼️ hero1.jpg              # Hero section image
│       └── 🖼️ log.jpg               # Background texture
│
├── ⚡ backend/                        # Node.js / Express REST API
│   ├── 📄 server.js                  # App entry, middleware, route mounting
│   ├── 📄 package.json               # Backend dependencies
│   ├── 📄 .env                       # Environment secrets (gitignored)
│   ├── 📄 RENDER_ENV.md              # Render env setup guide
│   ├── 📄 changeAdminPassword.js     # Admin account seeder script
│   │
│   ├── 📁 models/                    # Mongoose ODM Schemas
│   │   ├── 📄 User.js                # User schema (name, email, password, role)
│   │   ├── 📄 Donor.js               # Donor schema (blood group, AI result, confidence)
│   │   ├── 📄 BloodRequest.js        # Request schema (status, rejectionReason)
│   │   └── 📄 Message.js             # Message schema (userId, message, reply)
│   │
│   ├── 📁 routes/                    # Express Route Handlers
│   │   ├── 📄 auth.js                # POST /register, POST /login
│   │   ├── 📄 donors.js              # POST /, GET /normal, GET /ai-stats
│   │   ├── 📄 bloodRequest.js        # POST /, GET /, GET /user/:id, PUT /:id
│   │   ├── 📄 messages.js            # GET, POST, PUT (reply)
│   │   ├── 📄 users.js               # GET /, DELETE /:id
│   │   ├── 📄 announcements.js       # GET, POST, DELETE /:id
│   │   └── 📄 analyze.js             # POST / (standalone AI scan endpoint)
│   │
│   ├── 📁 utils/                     # Shared Utilities
│   │   ├── 📄 aiClient.js            # AI service HTTP bridge (base64 → Flask)
│   │   └── 📄 db.js                  # MongoDB connection state helpers
│   │
│   └── 📁 uploads/                   # Blood sample images (gitignored, runtime)
│
├── 🤖 ai-service/                    # Python Flask AI Microservice (Production)
│   ├── 📄 app.py                     # Flask app — /analyze endpoint (Gunicorn)
│   ├── 📄 requirements.txt           # Python dependencies
│   ├── 📄 render-start.sh            # Render startup script
│   ├── 📄 train_model.py             # MobileNetV2 training script
│   ├── 📄 evaluate.py                # Model evaluation metrics
│   ├── 📄 predict.py                 # CLI prediction utility
│   ├── 📄 convert_model.py           # H5 → Keras converter
│   ├── 📄 convert_tflite.py          # Keras → TFLite converter
│   ├── 📄 auto_fix_leakage.py        # Dataset data-leakage fixer
│   ├── 🧠 blood_infection_model.tflite  # Production TFLite model (9.5 MB)
│   ├── 🧠 blood_infection_model.keras   # Keras saved model (10.3 MB)
│   ├── 🧠 blood_infection_model.h5      # Legacy H5 format (11.5 MB)
│   └── 📁 dataset/                   # Training data (train/ val/ splits)
│
└── 🧠 ai-model/                      # AI Model Development (Local Training)
    ├── 📄 train_model.py             # MobileNetV2 training pipeline
    ├── 📄 evaluate.py                # Accuracy/loss evaluation
    ├── 📄 predict.py                 # Sample prediction script
    ├── 🧠 blood_infection_model.h5   # Trained model artifact
    └── 📁 dataset/                   # Local dataset mirror


Screenshots Gallery


🏠 Landing & Authentication

Login Page Sign Up Page
Login Page Sign Up Page
Glassmorphism login with announcements display Clean registration with live validation

🏡 Home & Navigation

Home / Dashboard Why Donate Blood
Home Page Why Donate
Hero section with user profile & request portal Educational content with glassmorphism cards

🩺 Donor Registration & AI Screening

Donor Form AI Analysis — Normal AI Analysis — Infected
Donor Form AI Normal AI Infected
Multi-step donor registration Green diagnosis — eligible donor Red diagnosis — registration blocked
Donor ID Card
Donor ID Card
Downloadable donor certificate generated via html2canvas

🆘 Blood Request System

Need Blood Form My Blood Requests Modal
Need Blood My Requests
Emergency request submission with validation Request status tracker with PDF download

🖥️ Admin Dashboard

Dashboard Overview Blood Requests Management
Admin Overview Admin Requests
Live stats, inventory chart & activity feed Approve/Reject workflow with status badges
AI Insights Panel Announcements System
AI Insights Announcements
Normal vs Infected donor analytics chart Priority-based announcement broadcaster
User Management Message Center
Users Messages
Full user registry with delete controls Admin reply system for user messages


AI System & Blood Analysis Engine

Model Architecture

The VitalLink AI system uses Transfer Learning with MobileNetV2 — a lightweight, efficient CNN pre-trained on ImageNet, fine-tuned for binary blood infection classification.

Input Image (any size)
        ↓
Resize to 224×224 pixels
        ↓
Normalize pixel values (÷ 255.0) → [0.0 – 1.0]
        ↓
┌─────────────────────────────────────┐
│  MobileNetV2 Base (frozen weights)  │
│  Pre-trained on ImageNet (1.4M imgs)│
│  Feature extraction backbone        │
└─────────────────────────────────────┘
        ↓
GlobalAveragePooling2D
        ↓
Dense(128, activation='relu')
        ↓
Dense(1, activation='sigmoid')  ← Binary output
        ↓
prediction < 0.5  →  "infected"
prediction ≥ 0.5  →  "normal"

Model Specifications

Property Value
Architecture MobileNetV2 + Custom Head
Input Shape (224, 224, 3)
Output Binary sigmoid (0.0 – 1.0)
Loss Function Binary Cross-Entropy
Optimizer Adam
Production Format TensorFlow Lite (.tflite)
Model Size (TFLite) ~9.5 MB
Training Epochs 5
Batch Size 16
Base Weights ImageNet (Transfer Learning)

Production Inference Pipeline

# app.py — Simplified Flask AI endpoint
interpreter = tf.lite.Interpreter(model_path="blood_infection_model.tflite")
interpreter.allocate_tensors()

@app.route("/analyze", methods=["POST"])
def analyze():
    img_data   = base64.b64decode(request.json["imageBase64"])
    img        = image.load_img(BytesIO(img_data), target_size=(224, 224))
    img_array  = np.expand_dims(image.img_to_array(img), axis=0) / 255.0
    
    interpreter.set_tensor(input_details[0]['index'], img_array.astype(np.float32))
    interpreter.invoke()
    prediction = interpreter.get_tensor(output_details[0]['index'])[0][0]
    
    return jsonify({
        "result":     "infected" if prediction < 0.5 else "normal",
        "confidence": float(prediction)
    })

Why TFLite for Production?

Format Size Inference Speed Production Use
.h5 (Keras) 11.5 MB Baseline Training only
.keras 10.3 MB Baseline Training only
.tflite 9.5 MB ~40% faster Production


API Reference

Base URL: https://vitallink-backend.onrender.com

🔐 Authentication Routes — /api/auth

Method Endpoint Body Response Description
POST /api/auth/register { name, email, password } { message } Register new user
POST /api/auth/login { email, password } { user: { id, name, email, role } } Login & get session

🩸 Donor Routes — /api/donors

Method Endpoint Body / Params Response Description
POST /api/donors multipart/form-data (name, email, age, blood_group, image) { result, confidence, imagePath } Register donor + AI screening
GET /api/donors/normal [{ donor }] Fetch AI-verified normal donors
GET /api/donors/ai-stats { normal, infected, total } AI screening statistics

🆘 Blood Request Routes — /api/requests

Method Endpoint Body / Params Response Description
POST /api/requests { userId, name, phone, bloodGroup, reason } { message } Submit blood request
GET /api/requests [{ request }] Get all requests (admin)
GET /api/requests/user/:userId [{ request }] Get user's requests
PUT /api/requests/:id { status, rejectionReason? } { updated request } Update request status (admin)

💬 Message Routes — /api/messages

Method Endpoint Body / Params Response Description
GET /api/messages [{ message }] All messages (admin)
GET /api/messages/user/:userId [{ message }] User's messages
POST /api/messages { userId, userName, userEmail, message } { message } Submit message
PUT /api/messages/:id { reply } { updated } Admin reply

🔔 Announcement Routes — /api/announcements

Method Endpoint Body / Params Response Description
GET /api/announcements [{ announcement }] All announcements
POST /api/announcements { title, message, bloodGroup?, date?, priority } { message, id } Create announcement
DELETE /api/announcements/:id { message } Delete announcement

👥 User Routes — /api/users

Method Endpoint Body / Params Response Description
GET /api/users [{ user }] All users (admin)
DELETE /api/users/:id { message } Delete user (admin)

🤖 AI Analyze Route — /api/analyze

Method Endpoint Body Response Description
POST /api/analyze multipart/form-data (image) { result, confidence, imagePath } Standalone AI scan (no DB save)

❤️ Health Check

Method Endpoint Response Description
GET /api/health { api, database, mongoConfigured, aiServiceConfigured } System health status


Database Design

Database: MongoDB Atlas
ODM: Mongoose 8.x


📋 users Collection

{
  _id:       ObjectId,           // Auto-generated primary key
  name:      String (required),  // Full name
  email:     String (unique, lowercase, trimmed),
  password:  String,             // bcrypt hash (10 salt rounds)
  role:      "user" | "admin",   // Role-based access control
  createdAt: Date,               // Mongoose timestamps
  updatedAt: Date
}

🩸 donors Collection

{
  _id:        ObjectId,
  name:       String (required),
  email:      String (required),
  age:        Number (required),
  blood_group: String (required),  // A+, A-, B+, B-, O+, O-, AB+, AB-
  image:      String,              // Server file path (/uploads/...)
  ai_result:  "normal" | "infected",  // AI diagnosis result
  confidence: Number,              // 0.0 – 1.0 model confidence
  createdAt:  Date
}

🆘 bloodrequests Collection

{
  _id:             ObjectId,
  userId:          ObjectId (ref: "User"),
  name:            String (required),
  phone:           String (required),
  bloodGroup:      String (required),
  reason:          String (required),
  status:          "Pending" | "Approved" | "Rejected",  // default: "Pending"
  rejectionReason: String,          // Set only when status = "Rejected"
  createdAt:       Date,
  updatedAt:       Date
}

💬 messages Collection

{
  _id:       ObjectId,
  userId:    ObjectId (ref: "User", nullable for guests),
  userName:  String,
  userEmail: String,
  message:   String (required),
  reply:     String,   // Admin's reply — default: ""
  createdAt: Date,
  updatedAt: Date
}

🔔 announcements Collection

{
  _id:        ObjectId,
  title:      String (required),
  message:    String (required),
  bloodGroup: String | null,        // Optional blood group targeting
  date:       Date | null,          // Optional event/deadline date
  priority:   "normal" | "urgent",  // default: "normal"
  createdAt:  Date
}


Installation & Local Setup

Prerequisites

Tool Version Purpose
Node.js 18+ Backend runtime
npm 8+ Package management
Python 3.11+ AI service runtime
pip Latest Python packages
MongoDB Atlas Free tier Cloud database
Git Latest Version control

Step 1 — Clone the Repository

git clone https://github.com/rajayush6200/VitalLink.git
cd VitalLink

Step 2 — Backend Setup

cd backend
npm install

Create .env in the backend/ directory:

# MongoDB Atlas
MONGO_URI=mongodb+srv://<username>:<password>@cluster0.xxxxx.mongodb.net/vitallink?retryWrites=true&w=majority

# Authentication
JWT_SECRET=your_minimum_64_character_super_secure_random_secret_key_here_do_not_share

# Server
PORT=3000

# AI Microservice (local)
AI_SERVICE_URL=http://localhost:5001/analyze

# Admin Credentials
ADMIN_EMAIL=admin@vitallink.com
ADMIN_PASSWORD=YourSecureAdminPassword123!

Step 3 — Seed Admin Account

# From the backend/ directory
node changeAdminPassword.js

This creates the admin user in MongoDB with the credentials from your .env file.


Step 4 — AI Service Setup

cd ../ai-service
pip install -r requirements.txt

Start the AI service:

python app.py
# Flask starts on http://localhost:5001
# AI service endpoint: http://localhost:5001/analyze

Step 5 — Start the Backend Server

# In a new terminal, from backend/
npm run dev
# Express API starts on http://localhost:3000

Step 6 — Serve the Frontend

# Option A: Open directly in browser
open frontend/index.html

# Option B: Serve with a static server
npx serve frontend
# Serves on http://localhost:3000 (or nearest available port)

Step 7 — Verify Everything Works

# Check backend health
curl http://localhost:3000/api/health

# Expected response:
# {
#   "api": "ok",
#   "database": "connected",
#   "mongoConfigured": true,
#   "aiServiceConfigured": true,
#   "aiServiceUrl": "http://localhost:5001/analyze"
# }

Visit http://localhost:3000 (or your served frontend port) and log in with your admin credentials.



Environment Variables

Backend — backend/.env

Variable Required Description Example
MONGO_URI ✅ Yes MongoDB Atlas connection string mongodb+srv://user:pass@cluster.mongodb.net/vitallink
JWT_SECRET ✅ Yes Minimum 64-char secret for JWT signing a8f2c3d9... (64+ chars)
PORT ⚪ Optional Backend server port 3000
AI_SERVICE_URL ✅ Yes Flask AI service analyze endpoint https://vitallink-ai-service.onrender.com/analyze
ADMIN_EMAIL ✅ Yes Admin account email address admin@vitallink.com
ADMIN_PASSWORD ✅ Yes Admin account plaintext password (hashed on seed) SecurePass123!

Frontend — frontend/js/config.js

Variable Description Production Value
API_BASE_URL Backend REST API base URL https://vitallink-backend.onrender.com
AI_SERVICE_URL Flask AI service URL https://vitallink-ai-service.onrender.com

⚠️ Security Note: Never commit .env files to version control. Always use Render's Environment Variables dashboard for production secrets.



Deployment on Render

VitalLink is fully deployed using Render's Blueprint infrastructure-as-code (render.yaml). Three independent services are deployed from a single repository.

Deployment Architecture

GitHub Repository
       │
       ├── render.yaml (Blueprint)
       │
       ├─── 🌐 vitallink-app-2jb5      (Static Site)
       │    └─ rootDir: .
       │    └─ publishDir: ./frontend
       │    └─ URL: vitallink-app-2jb5.onrender.com
       │
       ├─── ⚡ vitallink-backend        (Node.js Service)
       │    └─ rootDir: backend
       │    └─ buildCmd: npm install
       │    └─ startCmd: npm start
       │    └─ URL: vitallink-backend.onrender.com
       │
       └─── 🤖 vitallink-ai-service    (Python Service)
            └─ rootDir: ai-service
            └─ buildCmd: pip install -r requirements.txt
            └─ startCmd: gunicorn app:app --bind 0.0.0.0:$PORT --timeout 120 --workers 1
            └─ URL: vitallink-ai-service.onrender.com

Render Environment Variables (Backend Service)

Set these in Render Dashboard → Service → Environment:

Key Source
MONGO_URI MongoDB Atlas → Connect → Drivers
JWT_SECRET Generate with openssl rand -hex 64
AI_SERVICE_URL https://vitallink-ai-service.onrender.com/analyze
ADMIN_EMAIL Your admin email
ADMIN_PASSWORD Your secure admin password

Deploy with Blueprint

# 1. Push your code to GitHub
git push origin main

# 2. In Render Dashboard:
#    New → Blueprint → Connect your GitHub repo → Deploy

💡 Tip: Render free-tier services spin down after inactivity. First request after idle will take 30–60 seconds (cold start). The AI service has a --timeout 120 flag to handle this gracefully.



Security Architecture

Layer Implementation Details
Password Security bcryptjs (salt rounds: 10) Passwords never stored in plaintext
Frontend Auth Guard JavaScript localStorage check Immediate redirect if no session
Admin Route Guard user.role === 'admin' check Client-side role enforcement
Database Availability isDatabaseReady() utility All DB routes check connection state
CORS Policy cors() middleware Configurable cross-origin requests
Env Secrets dotenv + Render Env Vars No secrets in source code
Upload Handling Multer with file path isolation Uploads stored in /uploads, served statically
Duplicate Prevention MongoDB query on active requests Prevents request spam per user
Error Handling Try-catch on all async routes No stack traces leaked to clients

Note on JWT: The architecture is JWT-ready with a JWT_SECRET environment variable. Session data is currently stored client-side via localStorage. Full stateless JWT implementation is a planned enhancement.



Performance & Scalability

Current Architecture Strengths

Aspect Design Decision Benefit
Microservices 3 independent services Scale AI, backend, frontend independently
TFLite Inference Compiled TFLite model ~40% faster than full TF, minimal RAM
Static Frontend No SSR, pure HTML/JS Zero compute cost, instant CDN delivery
MongoDB Atlas Cloud-native DB Auto-scaling, backups, global clusters
Render Blueprint IaC deployment Reproducible, one-command redeploy
Mongoose Schemas Strict validation Data integrity enforced at ORM level
Gunicorn WSGI Multi-process server Production-grade Python serving

Scalability Vision

Current (MVP)                 →    Enterprise Scale
─────────────────────────────────────────────────────
Single Render Free Tier       →    Multi-region deployment
localStorage auth             →    Redis session store + JWT
Gunicorn 1 worker             →    Kubernetes AI pod autoscaling
MongoDB Atlas M0              →    Atlas M10+ with read replicas
Static HTML frontend          →    Next.js SSR + CDN edge caching
Manual blood stock            →    Real-time IoT blood bank sensors


Roadmap & Future Improvements

VITALLINK ROADMAP
══════════════════

🔜 Version 2.0 — Core Enhancements

  • Full JWT Authentication — stateless tokens, refresh token rotation
  • Real-time Notifications — WebSocket / Socket.io for live alerts
  • Email Notifications — Nodemailer for request status updates
  • Hospital/Blood Bank Onboarding — multi-organization support
  • SMS Alerts — Twilio integration for emergency donor matching

🔮 Version 3.0 — Intelligence Layer

  • Geolocation Donor Matching — find nearest compatible donors via Google Maps API
  • ML Demand Prediction — predict blood shortage by region using historical data
  • AI Model v2 — retrain on larger dataset with multi-class infection classification
  • Chatbot Assistant — conversational AI for donor/recipient guidance
  • Smart Scheduling — AI-powered donation appointment optimization

🌐 Version 4.0 — Platform & Scale

  • React Native Mobile App — iOS & Android donor app with push notifications
  • Analytics Dashboard — advanced BI charts for healthcare administrators
  • API Versioning/api/v2 with backward compatibility
  • Multi-language Support — i18n for regional healthcare accessibility
  • HIPAA Compliance — enterprise-grade data privacy for US markets
  • Blockchain Donor Records — immutable, verifiable donation history


Contributing

Contributions are welcome and appreciated! VitalLink is built to grow.

How to Contribute

# 1. Fork the repository
# 2. Create your feature branch
git checkout -b feature/amazing-feature

# 3. Make your changes and commit
git commit -m "feat: add amazing feature"

# 4. Push to your branch
git push origin feature/amazing-feature

# 5. Open a Pull Request

Contribution Guidelines

  • Follow the existing code style (ES2020+, async/await patterns)
  • Write descriptive commit messages using Conventional Commits
  • Test your changes locally against all three services
  • Update documentation where relevant
  • AI model changes require evaluation metrics in the PR

Good First Issues

  • Add input validation on frontend forms
  • Implement proper JWT refresh token flow
  • Add unit tests for Express routes
  • Improve mobile responsiveness on admin dashboard
  • Add loading skeletons to dashboard data tables


Developer


Ayush Raj

Full-Stack Developer · AI/ML Enthusiast · Healthcare Tech Builder

GitHub   Email


🌐 Live Deployment Links

Service URL Status
🌐 Frontend App vitallink-app-2jb5.onrender.com Live
⚡ Backend API vitallink-backend.onrender.com Live
🤖 AI Service vitallink-ai-service.onrender.com Live


⭐ If VitalLink impressed you, please give it a star — it helps more developers discover it!


Built with love Save Lives



© 2026 Ayush Raj — MIT License


About

An enterprise-grade, AI-driven healthcare platform designed to streamline blood bank operations, automate sample analysis, and orchestrate real-time emergency donor coordination.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors