MediTrack: Privacy-First Medication Adherence PWA
📖 Project Story
What Inspired MediTrack
Medication non-adherence is a silent crisis. According to the World Health Organization (WHO), approximately 50% of patients in developed countries fail to adhere to their chronic disease medications, leading to worsened medical outcomes, preventable hospitalizations, and increased healthcare costs. The irony? The problem is rarely due to lack of access to medications—it's forgetfulness, competing priorities, and the friction of managing multiple prescriptions across fragmented reminder systems.
During research into healthcare technology challenges, I encountered a pattern: existing medication management apps either depend heavily on cloud synchronization, require user authentication (adding friction), or rely on external APIs that introduce privacy concerns. For patients managing chronic conditions, privacy and reliability shouldn't be negotiable.
The inspiration for MediTrack crystallized around a single principle: What if a patient could manage their entire medication regimen on their device, entirely offline, with zero surveillance, and still receive intelligent insights about their adherence?
This aligned perfectly with UN Sustainable Development Goal 3 (Good Health and Well-being)—a commitment to ensure healthy lives and promote well-being for all. MediTrack became a vehicle to demonstrate how privacy-first architecture and thoughtful UX design could tangibly improve adherence and, by extension, health outcomes.
🔍 Problem Statement
The Multi-Layered Challenge
Non-Adherence Prevalence
- 50% medication non-adherence rate in developed countries
- Leads to ~125,000 deaths annually and costs the U.S. healthcare system ~$290 billion/year
Existing Solution Gaps
- Most reminder apps require cloud accounts, introducing privacy friction
- Fragmented data across multiple platforms (Google Calendar, Notes, etc.)
- Limited analytics for understanding adherence patterns
- Dependency on consistent internet connectivity
- No integrations with emergency response workflows
User Trust Issues
- Concerns about personal health data storage and monetization
- Limited transparency in how health information is processed
- Vendor lock-in; difficulty exporting data
Who Suffers?
- Patients managing chronic conditions (diabetes, hypertension, asthma, etc.)
- Elderly users uncomfortable with cloud-first paradigms
- Individuals in regions with unreliable internet
- Privacy-conscious individuals
💡 Solution: MediTrack
MediTrack addresses this challenge through a local-first, progressive web app that delivers enterprise-grade medication management capabilities entirely within the user's browser.
Core Philosophy
✅ No cloud servers — All data lives on your device
✅ No user accounts — Install and use immediately
✅ Intelligent, not intrusive — Smart insights without external APIs
✅ Offline-first — Fully functional without internet
✅ Accessible — Works on any browser, installable as a PWA
✨ Key Features
1. Smart Medicine Scheduling
- Add multiple prescriptions with custom dosages
- Define flexible reminder intervals (e.g., "every 8 hours" or "daily at 8 AM")
- Visual schedule view with upcoming doses clearly highlighted
- Edit or remove medicines at any time
2. Real-Time Adherence Tracking
- Tap "Taken" when you consume a dose → Logged to local IndexedDB
- Visual confirmation and timestamp recording
- Mark doses as "missed" to maintain honest adherence history
- Automatic refill quantity deduction
3. Dynamic Health Score
A weighted algorithmic score that updates in real-time: $$\text{Health Score} = (0.5 \times \text{Adherence}\%) + (0.3 \times \text{Streak Days}) + (0.2 \times \text{Inventory Health})$$
- Adherence %: Recent dose compliance (last 7, 14, 30 days)
- Streak Days: Consecutive days with 100% adherence
- Inventory Health: Refill sufficiency metric
Users see their score evolve as they build habits, creating a feedback loop that reinforces consistency.
4. Advanced Local Analytics
- Daily, Weekly, Monthly Views: Adherence breakdown by time period
- Medication-Specific Insights: Which medicines have the highest missed-dose risk?
- Refill Predictions: "You'll run out of Lisinopril in 5 days" alerts
- No external APIs — All computation occurs on-device
5. Gamified Motivation
- Achievement badges ("7-Day Streak", "Perfect Week")
- Persistent streak tracking across app sessions
- Visual progress indicators to encourage consistency
6. Emergency Medical Profile
- Store blood type, allergies, critical medical conditions, emergency contact
- Generate a scannable QR code linking to encrypted emergency summary
- First responders can access critical info without authentication
7. Offline-First Architecture
- Service Worker caches all assets for full offline functionality
- Browser notifications work even when tab is closed
- IndexedDB persists all data locally; syncing across tabs via custom
DBEventTarget - Zero dependency on network availability
8. Data Portability & Sovereignty
- Export: Download entire health dataset as JSON
- Import: Restore data on new device or browser
- Users own and control their medical history
9. Adaptive UI & Accessibility
- Fully responsive design (desktop, tablet, mobile)
- Intelligent Dark/Light mode switching
- Keyboard navigation and screen reader support
- WCAG 2.1 AA compliance target
🛠 Technology Stack
| Layer | Technology | Rationale |
|---|---|---|
| Framework | Next.js 14+ (App Router) | Server-side rendering, static generation, optimal performance |
| Language | TypeScript | Type safety, developer experience, maintainability |
| Styling | Tailwind CSS v4 | Utility-first, minimal CSS, rapid iteration |
| Animation | Framer Motion | Smooth, declarative animations for UX polish |
| Local Storage | IndexedDB (via idb) |
Handles structured data at scale without network |
| Forms & Validation | React Hook Form + Zod | Lightweight, type-safe form handling |
| UI Components | Lucide React | Minimal, customizable icon library |
| PWA | Custom Service Worker | Full offline support, push notifications |
| Deployment | Vercel | Seamless Next.js integration, auto-scaling |
Architecture Diagram (Conceptual)
┌─────────────────────────────────────────────┐
│ Next.js Application (Client) │
│ ┌──────────────────────────────────────┐ │
│ │ React Components & Pages (TS/TSX) │ │
│ │ - Dashboard, Medicines, Schedule │ │
│ └──────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────┐ │
│ │ Custom React Hooks │ │
│ │ - use-db: Sync DB changes to state │ │
│ └──────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────┐ │
│ │ IndexedDB Schema & Logic │ │
│ │ - Medicines, Logs, Profile tables │ │
│ │ - Indexed queries (date, medicine) │ │
│ └──────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────┐ │
│ │ Service Worker (sw.js) │ │
│ │ - Asset caching, offline support │ │
│ │ - Push notification handling │ │
│ └──────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
↓ (All local, no external servers)
┌──────────────────────────────────┐
│ Browser Storage (IndexedDB) │
│ - Medicines, Logs, Emergency │
└──────────────────────────────────┘
Folder Organization
meditrack/
├── public/
│ ├── sw.js # Service Worker
│ ├── manifest.json # PWA Manifest
│ ├── icons/ # App icons (192x192, 512x512)
│ └── screenshots/ # Demo screenshots
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── (dashboard)/ # Main dashboard route group
│ │ ├── medicines/ # Medicine management
│ │ ├── schedule/ # Daily schedule view
│ │ ├── analytics/ # Insights & trends
│ │ ├── profile/ # Emergency profile
│ │ └── layout.tsx # Root layout
│ ├── components/ # Reusable React components
│ │ ├── Dialogs/ # Modal dialogs
│ │ ├── Navigation/ # Header/sidebar
│ │ ├── Cards/ # Data display cards
│ │ └── Forms/ # Input forms
│ ├── hooks/
│ │ └── use-db.ts # Custom hook for DB reactivity
│ └── lib/
│ ├── db/ # IndexedDB schema, queries
│ ├── insights/ # Health score, analytics logic
│ ├── notifications/ # Push notification handlers
│ └── utils/ # Helper functions
├── next.config.ts
├── tailwind.config.ts
├── tsconfig.json
└── package.json
🚀 How It Was Built
Phase 1: Architecture & Data Model (Week 1-2)
Designed IndexedDB schema with three main object stores:
medicines: Prescription metadata (name, dosage, frequency, inventory)logs: Dose intake records (timestamp, medicine ID, status: taken/missed)profile: Emergency medical info (singleton)
Architected the state sync layer (
DBEventTarget) to enable reactive updates:- Each DB transaction dispatches a custom
dbchangeevent - React hooks listen to these events and trigger re-renders
- Eliminates manual state management complexity
- Each DB transaction dispatches a custom
Phase 2: Core Features (Week 3-4)
Implemented medicine management UI
- Add/edit/delete medicines with validation
- Timezone-aware reminder scheduling
- Inventory tracking
Built adherence logging
- Tap-to-log interface for minimal friction
- Timestamp recording with refill deduction
Developed health score algorithm
- Weighted calculation across adherence, streaks, inventory
- Real-time updates as logs are created
Phase 3: Analytics & Insights (Week 5)
Created data analysis engine
- Query logs by date range, medicine, status
- Compute adherence percentages
- Generate refill warnings
Designed analytics dashboard
- Interactive charts (daily, weekly, monthly views)
- Medication-specific breakdowns
- Visual trend indicators
Phase 4: PWA & Emergency Features (Week 6)
Implemented Service Worker
- Registered in
next.config.ts - Caches all assets for offline access
- Handles periodic sync (if available)
- Registered in
Built emergency profile & QR code
- Secure local QR generation (no cloud dependencies)
- Emergency-only data structure
Added browser notifications
- Service Worker push notification listeners
- Silent notifications for missed doses
Phase 5: Polish & Deployment (Week 7-8)
UI/UX refinement
- Dark/Light mode toggle with system preference detection
- Responsive breakpoints for all device sizes
- Accessibility audit (keyboard nav, ARIA labels)
Performance optimization
- Code splitting with Next.js dynamic imports
- Image optimization (WebP with fallbacks)
- Lazy loading for off-screen components
Vercel deployment
- Zero-config deployment
- Automatic HTTPS for PWA notifications
🎯 Challenges Faced & Solutions
Challenge 1: Reactive State Management Without Redux
Problem: IndexedDB operations are asynchronous and isolated. How to keep React components in sync when DB changes occur?
Solution: Built a custom DBEventTarget class that:
- Wraps all DB transactions
- Emits
dbchangeevents on mutations - Custom hooks (
use-db.ts) listen to these events and trigger re-renders - Achieves Redux-like reactivity without the boilerplate
// Simplified approach
class DBEventTarget extends EventTarget {
async logDose(medicineId, status) {
await db.logs.add({ medicineId, status, timestamp: Date.now() });
this.dispatchEvent(new Event('dbchange'));
}
}
// In React component
const useDBSync = () => {
const [, forceUpdate] = useState({});
useEffect(() => {
dbTarget.addEventListener('dbchange', () => forceUpdate({}));
return () => dbTarget.removeEventListener('dbchange', forceUpdate);
}, []);
};
Challenge 2: Offline-First Data Sync Across Tabs
Problem: If user opens MediTrack in two browser tabs, logging a dose in Tab A doesn't reflect in Tab B.
Solution: Leveraged BroadcastChannel API:
- Tab A broadcasts
dbchangeevent to all other tabs - Tab B listens and re-queries IndexedDB
- Seamless multi-tab consistency without complexity
Challenge 3: Service Worker Lifecycle & Asset Caching
Problem: Stale Service Workers can prevent new app versions from loading correctly.
Solution: Implemented:
- Version-aware asset cache keys
- Programmatic cache invalidation in next.config.ts
- User-friendly "Update Available" prompt
Challenge 4: Timezone-Aware Reminders
Problem: User schedules dose for "8 AM" but navigates to different timezone. Reminder fires at wrong time.
Solution:
- Store reminder times as duration offsets from midnight local time
- Calculate next reminder trigger using
Date.now()adjusted bygetTimezoneOffset() - Works correctly across timezone changes
Challenge 5: Algorithm for Health Score
Problem: How to weight adherence, streaks, and inventory into a meaningful 0-100 score that motivates users?
Solution: Used a weighted formula validated against clinical adherence metrics: $$\text{Score} = (0.5 \times \text{Adherence}\%) + (0.3 \times \min(\text{Streak}/30, 1)) + (0.2 \times \text{Inventory Health})$$
- Tested with synthetic data to ensure score sensitivity
- Tuned weights based on UX feedback
Challenge 6: QR Code Generation Without External API
Problem: Most QR libraries require external servers or encode URLs that require backend infrastructure.
Solution: Used qrcode.react library:
- Generates QR codes client-side as canvas
- Encodes sanitized emergency profile as data URI
- Zero external dependencies
Challenge 7: PWA Installability & Notifications on iOS
Problem: iOS PWAs have limited notification support and strict HTTPS requirements.
Solution:
- Deployed exclusively to HTTPS (Vercel handles this)
- Noted iOS limitations in README
- Focused on Android as primary mobile platform for notifications
📚 Lessons Learned
1. Local-First Architecture is Powerful
Building without a backend forced elegant API design and made every component responsible for its own data concerns. The app is faster, more private, and easier to reason about.
2. IndexedDB Deserves Better Abstractions
Raw IndexedDB is verbose. Investing time in the idb wrapper and custom hooks paid dividends in code readability.
3. Health Data Demands Accessibility
Users with visual, motor, or cognitive impairments must be able to manage medications. WCAG compliance isn't optional—it's fundamental.
4. Gamification Works (If Aligned with Goals)
Streaks and achievements significantly boosted engagement in testing. But they must align with actual adherence, not just app usage.
5. TypeScript + Next.js is a Joy
Type safety caught entire classes of bugs before runtime. Server components reduced client-side complexity.
6. Users Value Privacy Over Features
When explaining MediTrack, the "no cloud account" aspect resonated more than advanced analytics. Privacy is a feature.
7. Deployment Matters Early
Deploying to Vercel on Day 1 exposed real-world issues (Service Worker caching, mobile viewport) that local dev never caught.
🌍 UN SDG 3 Alignment
MediTrack directly supports United Nations Sustainable Development Goal 3: Good Health and Well-being.
How:
- Reduces medication non-adherence from 50% to targeted <30% through smart reminders and gamification
- Improves long-term health outcomes by making adherence tracking accessible to underserved populations
- Promotes digital equity with a zero-cost, privacy-first alternative to expensive healthcare apps
- Enables self-management of chronic conditions, reducing clinical burden
- Protects health data through local-first architecture, aligning with privacy-centric healthcare
🎯 What Makes MediTrack Unique
| Aspect | MediTrack | Typical Competitor |
|---|---|---|
| Cloud Dependency | Zero—fully local-first | Cloud-required, account mandatory |
| Offline Functionality | 100% offline, push notifications | Limited or unavailable |
| Cost | Free, open-source | Freemium or subscription |
| Privacy | 100% user-controlled data | Cloud-stored, subject to ToS |
| Analytics | Intelligent local insights | Generic adherence reports |
| Emergency Integration | QR-based emergency profile | None or requires separate app |
| Setup Friction | Install & use immediately | Sign-up, verification, wait |
| Data Export | JSON export, full control | Locked-in or complex export |
The Differentiator: MediTrack proves that a healthcare app can be powerful, intelligent, and privacy-first without requiring a backend or user account. This architectural choice resonates with privacy-conscious users and populations in regions with unreliable internet.
🔮 Future Roadmap
Short-term (3-6 months)
- [ ] Wearable Integration: Sync reminders to Apple Watch / WearOS via Web Bluetooth
- [ ] Caregiver Mode: Allow family members to monitor adherence (with explicit consent)
- [ ] Pharmacy Integration: One-tap refill requests sent to local pharmacies
Medium-term (6-12 months)
- [ ] Prescription Scanning: OCR integration to auto-populate medicine details from images
- [ ] Symptom Tracking: Log side effects alongside adherence
- [ ] Mobile Apps: Native iOS/Android wrappers for app store distribution
Long-term (12+ months)
- [ ] Federated Learning: Privacy-preserving insights shared with researchers
- [ ] Integration with EHR Systems: Secure, user-controlled data sharing with healthcare providers
- [ ] Multilingual Support: Localization for non-English speaking populations
📖 References & Data
- WHO Medication Adherence Report: ~50% non-adherence in developed countries
- U.S. Healthcare Cost of Non-Adherence: ~$290 billion annually
- UN SDG 3: https://sdgs.un.org/goals/goal3
- Next.js App Router Docs: https://nextjs.org/docs/app
- IndexedDB Spec: https://w3c.github.io/IndexedDB/
✅ Submission Checklist
- ✅ GitHub repository (public, well-organized)
- ✅ Comprehensive README with installation guide
- ✅ Clear project description & problem statement
- ✅ Technology stack documentation
- ✅ Architecture overview & folder structure
- ✅ Challenges & lessons learned section
- ✅ Live deployment (Vercel:
medi-track-rose.vercel.app) - ✅ Demo screenshots included
- ✅ Open-source (MIT License)
- ✅ UN SDG 3 alignment articulated
🙏 Acknowledgments
- Technoviz Summer of Code (TSOC) 2026 for the opportunity and structure
- WHO for highlighting the medication non-adherence crisis
- Next.js & Vercel for exceptional developer tooling
- Open-source community for IndexedDB wrappers, UI libraries, and best practices
Built with ❤️ to improve global health and well-being.
Author: Priyanshu (@insanityatpeak)
Live Demo: https://medi-track-rose.vercel.app
Repository: https://github.com/insanityatpeak/MediTrack
Built With
- framer-motion
- indexeddb
- lucide-react
- next.js
- progressive-web-app-(pwa)
- react
- react-hook-form
- service-worker
- tailwind-css
- typescript
- vercel
- zod
Log in or sign up for Devpost to join the conversation.