AOY
TR EN
← All projects

Eczanow

Mobile + WebiOS · Android · Web

“The nearest open or on-duty pharmacy” — all 81 provinces plus Northern Cyprus, from the official chamber rosters.

Eczanow — on-duty pharmacy map
On-duty map
Eczanow — list sorted by distance
Sorted by distance
Eczanow — selected pharmacy card with directions and call
Selected pharmacy
Eczanow — home screen widget
Home screen widget
The Eczanow web app
01

What it does

Eczanow answers one question: which is the nearest pharmacy open right now? During the day it lists open pharmacies; after 19:00 and on Sundays it switches to the on-duty roster. Coverage is all 81 provinces of Türkiye plus Northern Cyprus; in Germany the same app runs in “open pharmacy now” mode.

Two things are always printed at the top of the screen: which mode you are in, and when that mode changes — “Open · on-duty starts at 19:00”, or “On duty until 09:00”. That is deliberate. The single most confusing part of looking for a pharmacy at night is not knowing which of the two lists you are actually reading.

With location permission the closest pharmacy moves to the top of the list, and every entry shows distance and an approximate drive time. You can also tap any point on the map and ask for “nearest to here” — useful when you want the pharmacy near where you are going, not where you are. Selecting one gets you a call or directions in a single tap.

A home screen widget shows the nearest on-duty pharmacy without opening the app at all, so that at two in the morning nobody has to go hunting through their launcher.

02

How it works

The data comes from the official on-duty rosters published by the provincial pharmacists’ chambers. It is fetched, validated and published automatically every day. The client is Flutter, the service is Fastify + PostgreSQL, and both run in Docker on my own server.

Distance is computed on the device

When location permission is granted, the app sends the coordinates nowhere. Instead the pharmacy list for the selected province is downloaded to the device and the sorting happens inside the phone. The server never learns who is where.

A list that looks broken is not published

81 chambers publish their rosters in 81 different shapes, and when one of them changes its page the scrape can break silently. So every fetch is validated before it is published: if the record count, the date or the field integrity fall outside the expected range, no new list is published for that day and the screen states how fresh the data actually is.

One dataset, three surfaces

The mobile app, the web app and the home screen widget all read the same API, and all three speak Turkish, English and German.

Two countries, two different questions

In Türkiye the question is “which pharmacy is on duty tonight”, and the data comes from the chambers’ duty rosters. In Germany the on-duty feed (Notdienst) is not connected yet, so the app runs in “open now” mode there: opening hours are interpreted and each card gets an open / closed / unknown badge.

Those two states are two separate columns in the database: does the country have a duty rota, and can we actually get it. For Germany the first is true and the second is not — collapsing them into one field would have been a lie that gets unwound from the wrong end the day the data is connected.

Decision · location

Coordinates never reach the server. A pharmacy finder has no need to know where anyone is. Sending location to the server creates data that then has to be stored, disclosed and defended — for no benefit at all.

The price is that computing distance on the device means downloading the whole province list first. A single province’s list is small enough for that, so the trade is a good one.

Decision · freshness

Showing nothing beats showing yesterday’s roster as if it were today’s. With on-duty pharmacies, wrong data is not merely inaccurate, it is harmful: somebody drives to a locked door at two in the morning.

So a fetch that fails validation is not published, and every list carries an “updated N hours ago” stamp. A list that quietly goes stale is far worse than one that openly says how old it is.

03

Architecture

Client
Flutter
API
Fastify
Data
PostgreSQL · Prisma
Deployment
Docker · nginx
Coverage
Türkiye: 81 provinces plus Northern Cyprus (on-duty + open) · Germany: “open now” mode
Data source
Official on-duty rosters published by the provincial pharmacists’ chambers, fetched daily
Platform
iOS, Android and web
Languages
Turkish, English and German — in the app and on the web
Monetisation
Free with ads; a one-time purchase removes them
04

Frequently asked

Where does the on-duty list come from?

From the official rosters the provincial pharmacists’ chambers publish themselves. They are fetched automatically every day; a fetch that fails validation is not published, and the screen states how long ago the data was refreshed.

Is my location sent to a server?

No. When location permission is granted, the pharmacy list for the selected province is downloaded to the device and the distance is computed on the phone. The coordinates are never sent anywhere.

Open or on duty — which list am I looking at?

The screen says so explicitly. During the day it lists open pharmacies and shows “on-duty starts at 19:00”; after 19:00 and on Sundays it switches to the duty roster and shows “on duty until 09:00”.

Can I use it without installing the app?

Yes — the same data is served on the web at eczanow.aliousyucex.com, in Turkish, English and German, with a separate state-by-state tree for Germany.

What does the widget show?

The nearest on-duty pharmacy with its distance, right on the home screen, without opening the app. Directions and calling work straight from the widget.

Does the app cost anything?

No, it is free. It shows ads, and there is a one-time purchase to remove them — no subscription.

05

Other projects

built by the same hand
06

Contact

Got something similar?

I build products from idea to store release. Reach me by e-mail.