Islamic Companion
An Islamic Chrome extension that displays the Hijri date, prayer times and Quranic verses right inside your browser.
What makes it good
- 1Shows the Hijri (Islamic) date
- 2Daily prayer times at a glance
- 3Rotating Quranic verses
How it works
How it works
Prayer times come from the Aladhan API, resolved either from coordinates or from a city or country name. Results are cached per day and location, so opening the popup repeatedly costs nothing.
The timezone problem
This is the detail that quietly breaks most prayer-time extensions. The API returns times in the location's timezone — "05:10" for Cairo. Feeding that to Date.setHours() interprets it in the browser's timezone, so a traveller, a VPN user, or anyone tracking a city they are not in gets alarms off by the difference between the two.
Comparing minutes-since-midnight *inside* the target zone sidesteps the conversion entirely — the gap between two wall-clock readings in the same zone is the same number of real minutes anywhere on earth:
export function minutesUntil(hhmm, timeZone) {
const [h, m] = hhmm.split(':').map(Number);
const parts = new Intl.DateTimeFormat('en-US', {
timeZone, hour12: false, hour: '2-digit', minute: '2-digit',
}).formatToParts(new Date());
const get = (t) => Number(parts.find((p) => p.type === t)?.value);
const now = (get('hour') % 24) * 60 + get('minute');
let delta = h * 60 + m - now;
if (delta < 0) delta += 1440; // already passed today → tomorrow
return delta;
}Alarms that survive the day
A service worker is not a running process; it is woken by events. Scheduling every prayer once at install means the alarms expire after a single day and never come back. Instead a daily alarm just after midnight recomputes the schedule, and each prayer alarm re-arms itself for the next occurrence as soon as it fires.
chrome.alarms.create('dailyRefresh', { when: nextMidnight, periodInMinutes: 1440 });
// after a prayer alarm fires, schedule the next one
const delay = minutesUntil(timings[prayer], timezone);
chrome.alarms.create(alarm.name, { delayInMinutes: Math.max(delay, 1) });Qibla
The direction to the Kaaba is a great-circle initial bearing, not a heading off a flat map. The difference is not academic — from Jakarta or the Americas a flat bearing is wrong by tens of degrees.
export function qiblaBearing(lat, lng) {
const phi1 = toRad(lat), phi2 = toRad(KAABA.lat);
const dLambda = toRad(KAABA.lng - lng);
const y = Math.sin(dLambda);
const x = Math.cos(phi1) * Math.tan(phi2)
- Math.sin(phi1) * Math.cos(dLambda);
return (toDeg(Math.atan2(y, x)) + 360) % 360;
}Checked against published bearings for seven cities across the globe, all within one degree: Cairo 136.8°, Riyadh 244.5°, Jakarta 295.1°, London 119.2°, New York 58.6°, Istanbul 152.1°, Cape Town 23.2°.
The rest
A tasbih counter with a ring that fills toward each dhikr's traditional target, a prayer tracker with a streak that does not count an unfinished today as a failure, the Hijri date with a ±2 day adjustment for local moon sighting, and a toolbar badge counting down to the next prayer — because the popup is closed almost all of the time.