Case study
PillTracker
Medication doesn't only mean your own. A prescription of your own running alongside a pet's course of treatment means two schedules, two supplies to reorder, and two histories worth keeping apart. PillTracker is a TypeScript React Native app that keeps each profile separate and works entirely offline, on iOS and Android from one codebase.
- Role
- Solo developer
- Timeline
- 2025
- Status
- Shipped via Expo / EAS
The problem
One prescription is easy enough to hold in your head. Several at once is not — each with its own timing, its own supply running down at its own rate, and its own history worth keeping straight. And when a doctor or a vet asks what's actually been taken and when, memory isn't a good enough answer.
What I built
- Separate profiles — your own, a pet's, anything else being tracked — each with its own medications, dosing schedule, and colour identity.
- A calendar view of doses taken and missed, with a home screen showing what's due right now.
- Local notifications scheduled per dose, so reminders work with no server and no account.
- Refill tracking that warns before supply runs out, with a restock flow.
- PDF adherence reports generated on-device and shared through the native share sheet, for handing to a doctor or a vet.
- JSON backup and restore, so moving to a new phone doesn't lose a year of history.
Technical notes
Offline-first by default
There is no backend. Everything persists to AsyncStorage behind a typed storage layer, which means the app works on a plane, in a hospital basement, and without anyone handing their medical data to a server I'd have to secure.
Date handling is the whole app
Most of the real complexity lives in one dates module: recurring schedules, doses that span midnight, timezone shifts, and 'did they take the 8am one yet' questions. Isolating it into pure functions made it the only part of the app I could reason about confidently.
Shipping updates without the app stores
EAS Update pushes JavaScript changes over the air with a version bump script, so a fix reaches users in minutes instead of waiting on review.
By the numbers
- 4.7k
- Lines of TypeScript
- iOS + Android
- Platforms
- 100% TS
- Type coverage
Stack
App
Device
Delivery
What I'd do differently
- The date logic deserved unit tests before it deserved a UI. It's the one part of this app where a subtle bug has real consequences, and I tested it by hand for far too long.
- Local-only storage was right for privacy and wrong for sharing — everything lives on one device, so there's no way to keep a second phone in step, or hand a profile to someone else, without a sync layer.