πΊοΈ Layered map. Five layers: external services (amber), the popup UI (blue), the background service worker hub (green), the Chrome platform (violet), and content scripts in every tab (teal). Animated dashes show the live data channels. Click any node for its responsibility.
π Click a node to inspect itguide
Every box is a real file or Chrome API in the extension. The lines are message, storage and network channels β switch to the Workflow tab to watch data actually flow through them, step by step, during an Adhan event.
β Configure & Schedule
Step 1 / 11
Pick your location
β
π¦ Manifest & permissions
manifestv3 Β· background
type:module
permissionsstorage Β· alarms Β· notifications Β· scripting Β· tabs
hostapi.aladhan.com Β· http/https://*
contentall frames Β· document_idle
commandtoggle-focus β Ctrl/β+Shift+Y
π§± Components
background.jsMV3 worker: fetch Β· alarms Β· notify Β· broadcast Β· auto-resume
content.jsevery frame: 1 Hz tick Β· overlays (Shadow DOM) Β· pause/resume media
popup.*prayer list Β· countdown Β· Resume Β· location search Β· settings
lib/schedulepure: parse times Β· next prayer Β· stale-fire Β· format
lib/geocodepure: Open-Meteo place search
β° Alarms
PRAYER
adhan-prayer-fire β fires at next prayer ts
RESUMEadhan-auto-resume β now + autoResumeMinutes
TICKadhan-tick β every 15 min (self-heal)
Alarms re-armed on install, startup & each tick. isStaleFire() (β₯90 s late) skips a slept-through Adhan.
πΎ Storage schema chrome.storage.local
// settings β user config, merged over DEFAULT_SETTINGS { enabled, country, state, city, lat, lon, autoResumeMinutes:5, leadSeconds:30, focusMode:true } // schedule β today's prayers (parsed to local-tz timestamps) { date:"YYYY-MM-DD", prayers:[{name,time,ts}β¦], fetchedAt } // nextPrayer β the one alarm is armed for (test:true on dev fires) { name, time, ts } // paused β central cross-tab pause state { active, prayer, time, since, focus }
π‘ Message catalog
GET_STATE Β· SAVE_SETTINGS Β· REFRESHpopup βread state / save+refetch / refetchRESUME_NOW Β· FOCUS_NOWpopup / content βend pause Β· turn on focusPRAYER_FALLBACKcontent βtab's own countdown hit 0 firstTEST_ADHANpopup βdev-only simulated Adhan (30s)PRAYER_NOW Β· RESUMEbg β all tabspause everything Β· resume everythingFOCUS_ON Β· FOCUS_OFFbg β all tabsraise / drop focus overlayπ External services
adhan-apiVercel β
/api/prayerTimes β 5 daily times
Open-Meteokeyless geocoding β city β region + coords
No backend of its own, no API keys, no runtime deps. The popup calls Open-Meteo directly; the worker calls adhan-api.
π‘οΈ Resilience patterns
- Dual trigger β alarm and per-tab countdown both pause; idempotent.
- Self-resume β content.js resumes if
ALARM_RESUMEnever fires. - Reconcile β worker restart re-arms an in-progress pause.
- Stale skip β slept-through Adhan is ignored, not replayed.
- Single instance β token kills orphaned content scripts.
- Re-prime tabs β inject into open tabs on install & startup.
π§ͺ Stack & quality
Vanilla JS
ES modules
Shadow DOM
MV3 SW
Jest unit tests
Zero runtime deps
Pure logic in lib/ is unit-tested; manifest qualification tests gate every build.
Generated from source β
background.js Β· content.js Β· popup.js Β· lib/ β’ Adhan Caster Pro v1.6.6 β’ single self-contained file