WellWell
Inspiration
This started with a very ordinary scene: a kitchen drawer with two boxes of medicine in it. Different brand names, different colors, different pharmacies. Same active ingredient inside.
If you take one for a headache in the afternoon and the other for a fever in the evening, you've quietly doubled your dose and nothing on either box told you so. Paracetamol is the obvious case, since it's sold under several brand names in Turkey alone, but it isn't the only one. People do this by accident constantly, and the packaging is not designed to stop them.
We wanted an app that catches it before it happens.
The second thing that shaped the whole project was a decision we made early: the AI is not allowed to decide anything. Language models hallucinate, and we were not comfortable with a system where a confident wrong sentence turns into a wrong dose. So we inverted the usual design. The model is a reader. It converts messy text from a box into structured fields, and from that point on every safety decision is made by plain rule-based code that behaves the same way every single time.
What it does
You point your camera at a medicine box and WellWell reads the label: brand name, generic name, active ingredient, strength, and expiry date.
- Verification, not guessing. Whatever comes off the label gets matched against a trusted drug database, so the app works with a known record instead of raw OCR text.
- Duplicate active ingredient warnings. If a new medicine shares an active ingredient with something already in your list, you get warned. That check never touches the AI. It's a deterministic rule, so it can't be talked out of firing.
- Reminders straight from the box. Dosage schedules are built from what the label says, and reminders fire as local notifications. No connection needed. Your phone can be in airplane mode in a village with no signal and the 8 a.m. reminder still arrives.
- Tracking that's actually motivating. Dose logging, a 30-day adherence streak, and a calendar history you can scroll back through.
- Caregiver sharing. You can give a family member access with fine-grained permissions instead of an all-or-nothing switch, plus an emergency QR card that shows your medication list to a paramedic in seconds.
- Fully bilingual. Complete English and Turkish support, and dark mode.
How we built it
Mobile: Flutter and Dart, with Riverpod for state and go_router for navigation.
Backend: .NET 8 minimal API in a vertical-slice architecture, PostgreSQL with EF Core, Redis for caching, and JWT auth with refresh-token rotation and reuse detection.
AI: GPT-4o-mini (paid tier) at four specific points in the flow, each behind a very strict system prompt with a narrow job. Every one of those four points has a deterministic fallback path, so if the model is down, slow, or returns something we don't like, the app keeps working. It just gets less chatty.
Testing: 168 automated tests, 107 unit and 61 integration.
Challenges we ran into
Designing the AI out of the critical path. It's easy to build something where the model does everything, and it demos well. Drawing a hard line between "AI may describe" and "only code may decide," then actually holding that line while building features under time pressure, took more architectural discipline than we expected.
Free text is a nightmare. Drug boxes are not standardized. Abbreviations, different dosage notations, brand names printed larger than the thing that actually matters, worn or glossy labels. Mapping all of that onto clean structured database records without silently mismatching a drug was the hardest part of the whole build.
Bilingual without creating a safety hole. Dates, plural forms, and notification strings all had to work properly in both languages. But we deliberately left drug names and active ingredients untranslated, because "translating" a medicine name is exactly how you end up with a dangerous mismatch. Deciding what not to localize turned out to be as important as the localization itself.
Accomplishments that we're proud of
- We shipped a real, deployed backend. Not a local demo running on a laptop with the URL cropped out of the video.
- Safety logic is 100% deterministic. The AI is fully isolated in the explanation layer, and we can point at the code and show exactly where that boundary is.
- All 168 tests pass.
What we learned
The biggest lesson was about scope. With two people and a weekend, the temptation is to add features, and almost every hour we spent saying no to an idea made the final product better than the hour before it.
We also learned how much of "using AI well" is actually prompt engineering plus a fallback plan. Writing the strict system prompts was maybe a third of the work; deciding what should happen when the model ignores them was the other two thirds.
And splitting the work across mobile and backend meant we had to agree on the API contract before either of us wrote much code. That felt slow on the first morning and saved us on the second night.
What's next for WellWell
- Wider drug coverage. Right now the database is our bottleneck, not the scanning. Expanding it, and adding more national medicine registries, is the single biggest improvement we can make.
- Interaction checks, not just duplicates. Same-ingredient detection is step one. Dangerous combinations between different ingredients are step two, and they need a properly sourced dataset before we'd trust ourselves to ship them.
- On-device label reading. Moving more of the recognition offline so the scan works with no connection at all, the way reminders already do.
- Getting it into people's hands. Cleaning up for App Store and Play Store review, and getting a pharmacist to audit our warning logic before anyone relies on it for real.
Built With
- .net-8
- asp.net-core-minimal-apis
- bcrypt
- dart
- dio
- entity-framework-core
- flutter
- flutter-local-notifications
- flutter-secure-storage
- go-router
- gpt-4o-mini
- ios
- jwt
- openai-api
- postgresql
- redis
- resend
- riverpod
- swagger
- xunit
Log in or sign up for Devpost to join the conversation.