Your Secure Digital Health Locker - Manage, share, and control access to your medical records with ease.
- Overview
- Features
- Tech Stack
- Architecture
- Getting Started
- Environment Setup
- Database Setup
- API Documentation
- Deployment
- Security
- Contributing
- License
HealthVault is a modern, secure digital health records management system that empowers patients to:
- Upload and store medical documents securely
- Share records with healthcare providers via OTP or QR code
- Control and revoke access to their medical data
- Track who accessed their records and when
Built with privacy and security at its core, HealthVault uses end-to-end encryption, temporary access tokens, and granular access controls to ensure your medical data remains strictly under your control.
- π Secure Authentication - Email/password login with Supabase Auth
- π€ Upload Medical Records - Support for PDFs, images (JPG, PNG)
- π Flexible Sharing Options:
- OTP-based sharing - Generate 6-digit codes for doctors
- QR code sharing - Instant access via QR scan
- π Time-limited Access - All shared access expires automatically
- β Revoke Access - Instantly revoke doctor access at any time
- π Access Logs - View who accessed your records and when
- ποΈ Delete Records - Permanently remove records from the system
- π§ Email Notifications - Real-time alerts when records are accessed
- π Quick Access - Verify via OTP or QR code scan
- π± Mobile-Friendly - QR scanner works on mobile devices
- π View & Download - Access shared medical records
- β±οΈ Session Management - Secure, time-limited access tokens
- π Read-Only Access - View records without modification rights
- π‘οΈ Row-Level Security (RLS) - Database-level access control
- π JWT Authentication - Secure token-based authentication
- π Encrypted Storage - Files stored in Supabase secure storage
- π Access Logging - Complete audit trail of all record access
- β²οΈ Token Expiration - Auto-expiring access grants (15 minutes for doctors)
- π« No Data Leakage - Signed URLs expire after 1 hour
- React 19.2 - Modern React with Hooks
- Vite 7.2 - Lightning-fast build tool
- React Router 7.9 - Client-side routing
- Tailwind CSS 3.4 - Utility-first CSS framework
- React Hot Toast - Beautiful toast notifications
- React QR Reader - QR code scanning
- React QR Code - QR code generation
- Vercel Serverless Functions - API routes
- Supabase - Backend-as-a-Service
- PostgreSQL database
- Authentication
- File storage
- Row-Level Security (RLS)
- JWT - JSON Web Tokens for doctor sessions
- SendGrid - Email notifications
- Vercel - Hosting & CI/CD
- GitHub - Version control
- ESLint - Code linting
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Client (React SPA) β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β
β β Login β βDashboard β β Share β β Doctor β β
β β Signup β β Upload β β Record β β Portal β β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Vercel Serverless API Routes β
β /api/upload-record /api/generate-otp β
β /api/get-records /api/generate-qr β
β /api/verify-otp /api/verify-qr β
β /api/revoke-access /api/log-access β
β /api/delete-record /api/signed-url β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Supabase Backend β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β PostgreSQL β β Auth β β Storage β β
β β Database β β (Users) β β (Files) β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β Tables: records, grants, access_logs β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- Records table
records (
id UUID PRIMARY KEY,
patient_id UUID REFERENCES auth.users(id),
title TEXT,
description TEXT,
file_url TEXT,
uploaded_at TIMESTAMP
)
-- Access grants table
grants (
id UUID PRIMARY KEY,
patient_id UUID REFERENCES auth.users(id),
doctor_email TEXT,
otp_hash TEXT,
qr_token TEXT,
expires_at TIMESTAMP,
is_active BOOLEAN,
records JSONB,
created_at TIMESTAMP
)
-- Access logs table
access_logs (
id UUID PRIMARY KEY,
grant_id UUID REFERENCES grants(id),
doctor_id TEXT,
record_id UUID REFERENCES records(id),
accessed_at TIMESTAMP
)- Node.js 18+ and npm
- Supabase account (supabase.com)
- Vercel account (for deployment)
- Clone the repository
git clone https://github.com/Th-Shivam/HealthVault.git
cd HealthVault- Install dependencies
npm install --legacy-peer-deps- Set up environment variables
Create a .env file in the root directory:
# Frontend (Vite)
VITE_SUPABASE_URL=your_supabase_project_url
VITE_SUPABASE_ANON_KEY=your_supabase_anon_key
# Backend (Serverless functions)
SUPABASE_URL=your_supabase_project_url
SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key
# Email Notifications (SendGrid)
SENDGRID_API_KEY=your_sendgrid_api_key_here- Set up Supabase database
Run the SQL commands in supabase_setup.sql:
# Copy the contents of supabase_setup.sql
# Paste and execute in Supabase SQL Editor- Run development server
# For frontend only
npm run dev
# For full-stack (API routes + frontend)
npx vercel dev- Access the application
http://localhost:3000
- Create a new project at supabase.com
- Navigate to Settings β API
- Copy the following values:
- Project URL β
VITE_SUPABASE_URLandSUPABASE_URL - Anon/Public Key β
VITE_SUPABASE_ANON_KEY - Service Role Key β
SUPABASE_SERVICE_ROLE_KEYβ οΈ (Keep this secret!)
- Project URL β
- Go to Storage in Supabase dashboard
- Create a new bucket named
medical-records - Set it to Public (for now) or configure RLS policies
- Note: For production, use private buckets with signed URLs
- Create a free account at sendgrid.com
- Verify your sender email address
- Navigate to Settings β API Keys
- Create a new API key with Full Access permissions
- Copy the API key to your
.envfile asSENDGRID_API_KEY - Important: Replace
noreply@healthvault.appinapi/services/email-service.jswith your verified sender email
Note: Without SendGrid configured, the app will work perfectly but email notifications will be skipped.
Execute the following SQL in your Supabase SQL Editor:
# Run the complete setup script
cat supabase_setup.sql | supabase db resetThis creates:
- β
recordstable with RLS policies - β
grantstable with RLS policies - β
access_logstable with RLS policies - β
medical-recordsstorage bucket - β Storage policies for authenticated uploads
Upload a medical record.
Request:
{
"patient_id": "uuid",
"title": "Blood Test Report",
"description": "Annual checkup",
"file": "base64_encoded_file",
"file_name": "report.pdf"
}Response:
{
"success": true,
"record_id": "uuid"
}Generate OTP for sharing records.
Request:
{
"patient_id": "uuid",
"doctor_email": "doctor@example.com",
"record_ids": ["uuid1", "uuid2"]
}Response:
{
"success": true,
"otp": "123456"
}Generate QR code token for sharing.
Request:
{
"patient_id": "uuid",
"record_ids": ["uuid1", "uuid2"]
}Response:
{
"success": true,
"qr_token": "signed_token_string"
}Revoke doctor access to records.
Request:
{
"grant_id": "uuid"
}Response:
{
"success": true
}Delete a medical record (requires auth).
Headers:
Authorization: Bearer <supabase_access_token>
Request:
{
"record_id": "uuid",
"file_path": "path/to/file",
"patient_id": "uuid"
}Response:
{
"success": true,
"message": "Record deleted successfully"
}Verify OTP and get access token.
Request:
{
"doctor_email": "doctor@example.com",
"otp": "123456"
}Response:
{
"success": true,
"token": "jwt_access_token"
}Verify QR token and get access.
Request:
{
"qr_token": "signed_token_string"
}Response:
{
"success": true,
"token": "jwt_access_token"
}Get shared medical records (requires doctor JWT).
Headers:
Authorization: Bearer <doctor_jwt_token>
Response:
{
"success": true,
"records": [
{
"id": "uuid",
"title": "Blood Test",
"description": "Annual checkup",
"file_url": "original_url",
"signed_url": "signed_url_with_token",
"uploaded_at": "2024-01-01T00:00:00Z"
}
],
"grant_id": "uuid",
"doctor_email": "doctor@example.com"
}Log when a doctor views a record.
Request:
{
"grant_id": "uuid",
"doctor_id": "doctor@example.com",
"record_id": "uuid"
}Response:
{
"success": true
}- Install Vercel CLI
npm install -g vercel- Link your project
vercel link-
Set environment variables in Vercel
- Go to your project settings on vercel.com
- Add all environment variables from
.env
-
Deploy
git push origin main
# Vercel auto-deploys on pushThe project uses the following build settings:
- Framework: Vite
- Build Command:
npm run build - Output Directory:
dist - Install Command:
npm install --legacy-peer-deps
β Authentication & Authorization
- Supabase Auth for patient login
- JWT tokens for doctor sessions
- Row-Level Security (RLS) on all tables
β Data Protection
- Encrypted file storage
- Signed URLs with expiration
- OTP hashing (SHA-256)
- HMAC-signed QR tokens
β Access Control
- Temporary access grants (15 min for doctors)
- Manual revocation capability
- Audit logging for all access
β API Security
- CORS headers configured
- Input validation
- Error handling without data leakage
- Use a dedicated JWT secret (not Supabase service key)
- Set storage bucket to private
- Implement rate limiting
- Add CAPTCHA to signup/login
- Enable MFA for patient accounts
- Regular security audits
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
- Follow existing code style
- Write meaningful commit messages
- Add comments for complex logic
- Test your changes thoroughly
- Update documentation as needed
This project is licensed under the MIT License - see the LICENSE file for details.
- Shivam - @Th-Shivam
- Supabase - Backend infrastructure
- Vercel - Hosting platform
- Tailwind CSS - UI framework
- React - Frontend framework
For support, email support@healthvault.com or open an issue on GitHub.
Made with β€οΈ for better healthcare