Rafiq (رفيق, "companion") is a private, offline-first Islamic companion app for prayer times, Qur'an, audio recitation, adhkar, and qibla — no ads, no tracking, no accounts. Built with Expo, React Native, and TypeScript.
Rafiq (رفيق) means companion — the kind that walks with you quietly, asks for nothing, and is there when you need it. That's the goal of this app.
Why Rafiq
Most Islamic apps ship with banner ads, request notification permission on launch, and ping analytics for every tap. Rafiq doesn't. The only network traffic is the prayer-times API call (your coordinates → times), and the only data on your device is your settings. That's it.
- Private by default — no SDKs, no telemetry, no third parties. Your coordinates are sent to
api.aladhan.comto compute prayer times; nothing else leaves the device. - Offline-first — last fetched times stay available without a connection. Adhkar ships as bundled JSON, no network needed.
- Arabic-first, RTL-correct — Arabic is the default language with full RTL layout. English is a first-class second.
- Beautiful by intent — a dark "night" theme by default and a warm cream mushaf paper light theme. Real Arabic typography (Amiri, Cairo), not system fallbacks.
Features
Prayers
- Five prayers with next-prayer highlight + live per-second countdown
- Current-prayer pulse on the most recently passed prayer
- Location-based (GPS + reverse-geocode) or validated city search
- Hijri date in Amiri, Arabic-Indic digits in
armode - 9 calculation methods (default: Egyptian) + Asr school (Shafi / Hanafi)
- Offline-resilient: TanStack Query cache persisted to MMKV (30-day)
Adhkar
- 12 categories from Hisn al-Muslim (الصباح، المساء، النوم، بعد الصلاة، الوضوء، المسجد، الطعام، السفر، الكرب، الاستغفار، أدعية، الاستيقاظ)
- Tap-to-count counter with haptics, progress ring, auto-advance
- Per-dhikr explanations (ar + en), inline reveal
- Daily reset, per-category progress persisted to MMKV — fully offline
Prayer notifications
- Local notifications scheduled from a cached monthly Aladhan calendar, 14-day horizon
- Per-prayer toggle (5 prayers) + optional pre-adhan reminder (5/10/15/20 min)
- Diff-based scheduler (60-item iOS cap, 150 on Android), tap → Home
- Permission flow with "open system settings" fallback; default OS sound
Qur'an reader
- 114-surah landing with search → ayah-by-ayah scroll reader
- Uthmani text in Amiri (never truncated), translation toggle, 5 editions (default: Itani's Clear Quran)
- Per-ayah audio via
expo-audiowith 5 reciters (default: Alafasy) - Global mini-player, lock-screen / background playback, auto-advance toggle
- Last-read auto-save + bookmarks strip on the Quran tab
Qibla + polish
- Magnetometer compass dial, great-circle bearing to Mecca, distance
- Lay-flat / calibrate hints, smooth spring animation
- Reduced-motion respected across ambient drift, pulse dot, completion ring, compass spring, ayah fade-in, mini-player slide
- Islamic geometric ornaments + breathing hero glows + ambient drifting background
Tech stack
| Layer | Choice |
|---|---|
| Framework | Expo SDK 55 (managed) + Expo Router (file-based routing) |
| Language | TypeScript, strict mode |
| UI | NativeWind 4 + react-native-reusables (shadcn philosophy for RN) |
| Animation | react-native-reanimated 4 (with prefers-reduced-motion respected) |
| Server state | TanStack Query + persistence to MMKV (offline cache) |
| Client state | Zustand + react-native-mmkv |
| Audio | expo-audio (background + lock-screen) |
| Location | expo-location (with reverse-geocoding) |
| Sensors | expo-sensors (magnetometer for qibla) |
| Notifications | expo-notifications |
| Fonts | Amiri (Quranic / Hijri) + Cairo (UI) via @expo-google-fonts |
| Icons | lucide-react-native |
Data sources (no API key, no auth): Aladhan for prayer times + monthly calendar, alquran.cloud for Quran text + audio. Adhkar is a vetted local JSON bundle (Hisn al-Muslim) — never fetched.
Non-negotiables
These are load-bearing — every change must respect them:
- No ads, no third-party analytics, no tracking. Only network traffic is Aladhan + alquran.cloud.
- Offline-first. Adhkar fully offline; prayer times and Quran usable from cache.
- Arabic-first, RTL-correct. Arabic-Indic digits in
armode — never raw API numbers. - Never truncate ayahs or adhkar. Quran ayah-by-ayah, full text. Adhkar dataset is a vetted local copy.
- Raw GPS coordinates never shown. A location label guard keeps coordinates off-screen and never stores them as labels.