π« Building a Full-Stack Heart Disease Prediction System: ML, FastAPI, Docker, React, Render, GitHub Pages, and CI/CD
Published:
In this project, I built a complete end-to-end AI application that predicts the risk of heart failure using real clinical data. The goal was not just to train a machine learning model, but to transform it into a full-stack production-grade web application, deploy it using modern DevOps tools, and make it publicly available.
This system includes:
| Layer | Technology |
|---|---|
| ML Training | Python, Scikit-Learn, Matplotlib, Pandas |
| Backend API | FastAPI + Uvicorn |
| Model Serving | Pickle + Docker |
| Deployment (API) | Render (Docker) |
| Frontend | React + Vite + Tailwind |
| Hosting (Frontend) | GitHub Pages |
| CI/CD | GitHub Actions |
| Communication | REST API (JSON) |
π§ System Architecture
ββββββββββββββββββββββββββββββ
β Machine Learning (ML) β
β Model training + Pickle β
β Python, Scikit-learn β
βββββββββββββββ¬βββββββββββββββ
β
Model.pkl exported
β
βββββββββββββββΌβββββββββββββββ
β FastAPI Backend (Render) β
β /predict endpoint (JSON) β
β Dockerized model serving β
βββββββββββββββ¬βββββββββββββββ
β
REST API
β
ββββββββββββββββββΌβββββββββββββββββ
β React Frontend β
β Hosted on GitHub Pages β
β Form β API β Prediction β
ββββββββββββββββββ¬βββββββββββββββββ
β
β
βββββββββββββββΌβββββββββββββββ
β End Users (Browser) β
β Web Interface for Testing β
ββββββββββββββββββββββββββββββ
π File Structure
Heart_Disease/
βββ .python-version
βββ Dockerfile
βββ pyproject.toml / requirements.txt
βββ uv.lock
β
βββ heart_failure_clinical_records_dataset.csv
βββ heart_failure_model.pkl
βββ Mid_Term_Project.py # Training Script
βββ Mid_Term_Project.ipynb # EDA Notebook
βββ export_artifacts.py # JSON/Graph exporting
βββ main.py # FastAPI backend
β
βββ figures/
β βββ correlation_matrix.png
β βββ histograms.png
β βββ death_event.png
β
βββ heart-disease-app/ # FRONTEND (React+Vite)
β βββ public/
β βββ src/
β β βββ components/
β β β βββ DataHead.jsx
β β β βββ EDAGallery.jsx
β β β βββ ModelSummary.jsx
β β βββ App.jsx
β β βββ main.jsx
β β βββ index.css
β βββ package.json
β βββ vite.config.js
β βββ tailwind.config.js
β βββ postcss.config.js
β
βββ .github/
βββ workflows/
βββ deploy.yml # CI/CD GitHub Actions
βοΈ Phase 1: Machine Learning Model Development
π₯ Install Dependencies
pip install pandas numpy scikit-learn matplotlib seaborn
π§ͺ Load Dataset & Explore
import pandas as pd
df = pd.read_csv("heart_failure_clinical_records_dataset.csv")
print(df.head())
df.info()
df.describe()
π EDA Visualizations
import seaborn as sns
import matplotlib.pyplot as plt
sns.heatmap(df.corr(), annot=True)
plt.savefig('figures/correlation_matrix.png')
π€ Model Training
python Mid_Term_Project.py
Inside Mid_Term_Project.py:
- Model training
- Cross-validation
- Hyperparameter tuning
- Save best model:
import pickle
pickle.dump(best_model, open("heart_failure_model.pkl", "wb"))
π Phase 2: FastAPI Backend
π¦ Install FastAPI
pip install fastapi uvicorn pydantic gunicorn
π Create API (main.py)
from fastapi import FastAPI
import pickle
import numpy as np
app = FastAPI()
model = pickle.load(open("heart_failure_model.pkl", "rb"))
@app.post("/predict")
def predict(request: dict):
values = np.array([list(request.values())]).reshape(1,-1)
prediction = model.predict(values)[0]
probability = model.predict_proba(values)[0][1]
return {"prediction": int(prediction),
"probability": float(probability)}
βΆοΈ Run Locally
uvicorn main:app --reload --port 8000
Visit: http://127.0.0.1:8000/docs
π³ Phase 3: Dockerization
π Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY . /app
RUN pip install --no-cache-dir --upgrade pip
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 8000
CMD ["gunicorn", "-k", "uvicorn.workers.UvicornWorker", "main:app", "--bind", "0.0.0.0:8000", "--log-file", "-"]
ποΈ Build Docker Image
docker build -t heart-disease-api .
docker run -p 8000:8000 heart-disease-api
π€ Push to Docker Hub
docker tag heart-disease-api mdislammazharul/heart-disease-api
docker push mdislammazharul/heart-disease-api
π Phase 4: Deploy Backend using Render (Docker)
Steps:
1οΈβ£ Render site β https://dashboard.render.com
2οΈβ£ New β Web Service
3οΈβ£ Select Deploy from Docker
4οΈβ£ Use GitHub repo
5οΈβ£ Use start command auto-detected from Dockerfile.
6οΈβ£ Deploy β after build, get an API URL like:
https://heart-failure-prediction-qe7o.onrender.com/predict
π Phase 5: React Frontend (Vite + Tailwind)
π» Create Project
npm create vite@latest heart-disease-app --template react
cd heart-disease-app
npm install
π¨ Install Tailwind
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
π Call API from Frontend
In src/components/PredictForm.jsx:
const API_BASE = "https://heart-failure-prediction-qe7o.onrender.com/predict";
fetch(API_BASE, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(formData),
})
.then((res) => res.json())
.then((data) => setResult(data));
β οΈ Configure CORS on FastAPI (main.py)
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=[
"http://localhost:5173",
"https://mdislammazharul.github.io"
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
π Deploy Frontend using GitHub Pages
npm install gh-pages --save-dev
In package.json:
"homepage": "https://mdislammazharul.github.io/Heart_Failure_Prediction/",
"scripts": {
"deploy": "gh-pages -d dist"
}
Build and deploy:
npm run build
npm run deploy
Frontend is live at:
π https://mdislammazharul.github.io/Heart_Failure_Prediction/
π CI/CD with GitHub Actions
Create: .github/workflows/deploy.yml
name: Deploy to GitHub Pages
on:
push:
branches: ["main"]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm install
- run: npm run build
- uses: JamesIves/github-pages-deploy-action@v4
with:
folder: dist
π― Live Demo
π Frontend: https://mdislammazharul.github.io/Heart_Failure_Prediction/
π API Endpoint: https://heart-failure-prediction-qe7o.onrender.com/docs
