MedAlert — Project Writeup
What Inspired Me
The inspiration for MedAlert came from watching a family member struggle with medication adherence. They kept forgetting doses, double-dosing, and dealing with the anxiety of managing multiple prescriptions.
The main goal was simple: make a minimal, reliable, and beautiful medication adherence app — a gentle nudge that makes medication management feel effortless rather than burdensome.
What I Learned
The Mathematics of Adherence
Adherence isn't just "did you take your pill?" — it's a statistical measure. The adherence rate is modeled as:
$$ \text{Adherence Rate} = \frac{\text{Doses Taken}}{\text{Total Scheduled Doses}} \times 100\% $$
Streak calculations follow a discrete pattern. For a sequence of $n$ doses with binary outcomes:
$$ x_i \in {0, 1} \quad \text{where } 0 = \text{missed}, \; 1 = \text{taken} $$
Progressive Web Apps Are Underrated
Before this project, I underestimated PWAs. Crafting a service worker with intelligent cache strategies was a revelation — the payoff is an app that works fully offline. The cache layer follows this decision tree:
| Request Type | Strategy | Rationale |
|---|---|---|
| Navigation requests | Network-first | Serve from cache if offline |
| Static assets | Cache-first | Serve cached, update in background |
| API calls (Supabase) | Network-only | Never cache dynamic data |
Real-Time Data with Supabase
Using Supabase Realtime for live medication updates taught me the elegance of PostgreSQL's LISTEN/NOTIFY mechanism, wrapped in a clean client API. Push updates arrive instantly, keeping the UI always in sync without polling.
How I Built It
Architecture Overview
The app is structured as a layered stack:
┌─────────────────────────────────────────────┐
│ React + TypeScript │
│ (Vite build, Tailwind CSS) │
├─────────────────────────────────────────────┤
│ shadcn/ui Components │
│ (Accessible, composable primitives) │
├─────────────────────────────────────────────┤
│ State Management (React Hooks) │
│ (useState, useEffect, useCallback) │
├─────────────────────────────────────────────┤
│ React Router (SPA routing) │
├─────────────────────────────────────────────┤
│ Supabase Client │
│ (REST API, Realtime, Auth, Storage) │
├─────────────────────────────────────────────┤
│ PostgreSQL Database │
│ (RLS policies, triggers, functions) │
├─────────────────────────────────────────────┤
│ Service Worker (PWA) │
│ (Cache strategies, offline support) │
└─────────────────────────────────────────────┘
Key Design Decisions
- TypeScript throughout — catches bugs at compile time, especially useful for Supabase's auto-generated types.
- Row Level Security (RLS) — every database query is scoped to the authenticated user; no server-side filtering needed.
- PWA-first — users can install the app on their home screen and receive reminders even without a browser tab open.
Built With
- composable-component-primitives-radix-ui-headless-accessible-components-(under-shadcn)-lucide-react-beautiful
- consistent-icon-set-react-router-v7-spa-routing-with-nested-routes-react-hook-form-performant
- date
- date-fns-modern
- flexible
- form
- handling
- inference
- jspdf
- library
- manipulation
- postgresql
- react18
- supabase
- typescript
- validation
- with
- zod-schema
Log in or sign up for Devpost to join the conversation.