AlSalah — Cross-Platform Prayer Times
A Kotlin Multiplatform prayer-times app with a from-scratch astronomy engine that computes lunar-crescent visibility from the Odeh (2004) criterion.
Overview
AlSalah ships to Android, iOS, and Desktop from one shared Kotlin Multiplatform codebase — a Compose Multiplatform UI, Room persistence, and Koin dependency injection, backed by a Ktor server (Netty, Exposed ORM, SQLite, HikariCP) packaged as a WAR on Tomcat 11.
The interesting part isn't the app shell — it's the calendar underneath it.
The Hijri calendar problem
The Islamic month begins when the new lunar crescent (hilāl) first becomes visible from a given location — which is a genuine astronomy problem, not a lookup table. AlSalah computes month boundaries from per-location crescent visibility, implementing the peer-reviewed Odeh (2004) criterion on top of custom sun and moon ephemeris code.
Odeh's test reduces visibility to a single parameter, V, from the crescent's
arc of vision and its width, and sorts each sighting into four zones — from
"visible to the naked eye" down to "not visible even with optical aid." But the
calendar doesn't stop at the criterion: it computes the day's prayer times
and that evening's crescent visibility from real ephemeris, per location.
Pick a date and a city and watch both respond:
- Tahajjud01:18
- Fajr04:24
- Shurooq05:47
- Dhoha06:08
- Zawaal12:21
- Zuhr12:31
- Asr17:02
- Maghrib19:06
- Ahmar20:16
- Isha20:29
AlSalah · Hanafi Asr · local time (Asia/Riyadh)
- ARCV
- 24.1°
- W
- 2.19′
- ARCL
- 30.8°
- lag
- +112m
V = 28.38
zone A Visible to the naked eye
Visibility is a global question, though — the same young crescent is an easy naked-eye sighting in one country and impossible in another the same evening. This globe bakes Odeh's zones over the whole Earth for the first evenings after upcoming new moons (precomputed at build time), so you can watch the visibility band sweep across longitudes:
- A · naked eye
- B · perfect conditions
- C · optical aid
- D · not visible
Getting the math right
An engine like this is only worth anything if it's correct, so it ships with a 150+ test validation suite:
- Checked against NASA and JPL HORIZONS ephemeris data and textbook reference values.
- End-to-end checks against 22 years of published crescent-sighting records.
On top of the calendar, I built Python observability tooling so the team gets real-time visibility into application health and faster fault detection.
What I learned
Correctness has to be designed in, not tested in afterward. Building the validation suite alongside the ephemeris code — with authoritative references as the oracle — is what made it safe to trust the calendar for something people actually rely on.