Page 1 of 45
System Requirements Document for pure-adhkar
1. Introduction
pure-adhkar is the project name for the native Android application delivered under the product name نور الذكر (Noor Al-Dhikr). It is a complete, production-quality, Arabic-first Qur’an companion for Android, built in Kotlin with Jetpack Compose and Material 3, following Clean Architecture with MVVM. The product serves everyday Qur’an reading, listening, tafsir exploration, and adhkar (remembrance) practice for regular Muslims of all ages.
The product intent is a spiritually calming, trustworthy, premium-feeling application that is simple to use daily, scalable for future features, and technically excellent — while maintaining complete privacy and authentic Qur’an accuracy through the Quran.com API as the primary trusted source for Qur’an text, translations, recitations, tafsir references, and verse metadata.
The audience is Arabic-first readers: daily Qur’an readers, recitation listeners, tafsir and translation students, and adhkar practitioners who open the app in quiet moments — before Fajr, after Maghrib, in the last minutes before sleep. The emotional register is spiritual calm, respect, and trust — never entertainment, never urgency, never commerce.
Page 2 of 45
2. System Overview
Noor Al-Dhikr is a native Android application delivered as a single installable app with a modular internal architecture. All Qur’an content — text, translations, tafsir references, recitation audio URLs, word-level data, and verse timing — is retrieved from the Quran.com API as the primary trusted source, cached locally, and made available offline. The app is fully Arabic-first with RTL support across all screens, and it is ad-free, tracking-free, and collects no user data.
Current delivery shape: custom first-party Android UI plus background automation (media playback service and locally scheduled reminders).
Actors:
- Qur’an Reader — reads the Holy Qur’an daily in Arabic, browsing by Surah, Juz, Hizb, or Page.
- Recitation Listener — streams or downloads recitations from the ten named reciters and follows synchronized highlighting.
- Tafsir & Translation Student — studies meaning through translations, parallel reading, and tafsir.
- Adhkar Practitioner — performs daily remembrance with count tracking and locally scheduled reminders.
Accepted behavior: full Qur’an browsing by Surah/Juz/Hizb/Page; Mushaf reading mode; verse-by-verse reading; bookmarks; Continue Reading; daily verse reflection; favorites; cross-source search; Tajweed-aware rendering if available; night/sepia/paper Mushaf modes; translations and tafsir (Ibn Kathir, Al-Saadi, Al-Jalalayn, Saheeh International, plus downloadable translation architecture); instant translation switching; parallel reading; verse tafsir bottom sheet; translation audio synchronization; ten named reciters with streaming, optional offline caching, background playback, lock screen controls, sleep timer, repeat verse/range, auto-next surah, and verse-synchronized highlighting via Media3/ExoPlayer; a dedicated الأذكار section with six adhkar categories, electronic tasbih, favorites, daily reminders, count tracking, and offline storage; local reminders for daily verse, morning adhkar, and evening adhkar plus optional reading goals; and a full Settings screen.
Narrow exclusions (binding): no ads; no in-app purchases; no tracking; no analytics SDKs; no tracking SDKs; no user data collection; no camera, microphone, location, or contacts permissions; no unnecessary storage permission. Only INTERNET and FOREGROUND_SERVICE_MEDIA_PLAYBACK (if needed) are used.
Page 3 of 45
2a. Product Interpretation and Delivery Boundary
Noor Al-Dhikr is delivered as a first-party Android application. All reading, listening, tafsir, adhkar, favorites, reminders, and settings surfaces are owned and rendered by the application itself. Qur’an content is not authored by the app; it is retrieved from the Quran.com API, which is the authoritative external content provider for Qur’an text, translations, recitations, tafsir references, and verse metadata. The application caches that content locally and falls back to the cache when the network is unavailable, so reading, adhkar, and optionally audio continue to work offline.
The application does not require an account, sign-in, or any identity establishment. All personal state — reading position, bookmarks, favorites, adhkar counts, preferences, and cached content — is stored locally on the device. No user data leaves the device. Reminders are scheduled locally with no cloud dependency. Background recitation playback is handled by a foreground media playback service when the user enables it.
Current scope covers everything described in this document. Future scope (kept out of current pages and acceptance) includes the future scalability roadmap items listed in Section 11.
Page 4 of 45
2b. Source Content Inventory
The Quran.com API is an authoritative content source. The following verified factual entities, endpoints, fields, and values are preserved from the reference directive:
API Families
- Content APIs — programmatic access to Qur’an text (chapters, verses), translations, tafsir, audio (recitations), recitations listings, pages, juz, hizb, ruku, manzil.
- Search APIs — allow Quran search queries and retrieval of search results.
- User APIs — allow user-specific data (bookmarks, reading sessions, preferences, notes, collections, goals); require OAuth2 user tokens.
Authentication Requirements
- Content APIs: grant type
client_credentials; required headers x-auth-token and x-client-id.
- User APIs: require OAuth2 user session token plus client ID.
Recitations Listing Endpoint
- Endpoint:
/resources/recitations
- Response fields:
id, reciter_name, style, translated_name, name, language_name
- Usage: IDs from this list are used in audio query parameters and specific recitation endpoints.
Translation Endpoint
- Endpoint:
/quran/translations/:translation_id
- Parameters:
fields (e.g. chapter_id, verse_number, verse_key, juz_number, etc.), foot_notes (boolean), chapter_number, juz_number, page_number, hizb_number, rub_el_hizb_number, manzil_number, ruku_number, verse_key
- Response includes: translation text, metadata such as
resource_name, language_name, verse_key, verse numbering, plus optional footnotes.
Word-Level and Font Rendering Support
- Endpoint:
/verses/by_chapter/{chapter}?words=true
- Parameters:
words (boolean), word_fields (e.g. code_v2, text_qpc_hafs, text_uthmani_simple, text_indopak), mushaf (layout/format ID), optionally translations IDs.
- Word fields described:
code_v1, code_v2, text_qpc_hafs, text_indopak; plus char_type_name values such as word, end, pause, sajdah, rub-el-hizb with rendering guidance.
Page Layout Verses Fetch
- Endpoint:
/verses/by_page/{page_number}
- Parameters:
words=true, mushaf layout
- Usage: fetch verses for Mushaf page using page boundaries from separate page lookup; includes word-level data with positions.
Content Sync / Offline Sync Features
- Resources supported:
quran_core, mushafs, translations, word_by_word_translations, word_by_word_transliterations, tafsirs, recitations, chapter_recitations, articles
- First sync (bootstrap): use
GET /resources/sync?bootstrap=true&resources=... with snapshot_url for full resource copy.
- Subsequent sync: pass
sync_token to get only incremental changes; snapshot URLs help refresh full resource state.
Feature Reference — Behaviors and Capabilities
- Browse full Qur’an content (chapters, verses, translations, tafsir, audio)
- List available reciters and fetch audio URLs
- Fetch translations by ID with rich filtering (verses, pages, juz, footnotes)
- Retrieve word-level data for typography and Mushaf font rendering
- Fetch verses structured by page for Mushaf-style layout
- Perform efficient offline content synchronization with change tracking and snapshots via sync tokens
Feature Reference — Flows & Interactions
- Obtain access token via
client_credentials grant, include x-auth-token and x-client-id in each request
- List recitations to choose reciter IDs; use recitation ID in verse or chapter recitation audio parameter
- Fetch translations resource list, then fetch individual translation content with filters
- Use
words=true and word_fields to receive word-level data and tailor rendering
- Use
by_page endpoint for page-based verse layout; prefetch with page lookup
- Initialize offline sync using bootstrap flag; later sync differences with stored
sync_token, apply snapshots or incremental updates
Feature Reference — Capabilities
- Rich, structured Qur’an data: text, translations, tafsir, recitations, metadata (juz, hizb, ruku, manzil, page)
- Word-level font rendering support with multiple fonts and markers
- Audio integration including timing segments via recitations/chapter_recitations resources
- Efficient offline capabilities via content sync APIs
Page 5 of 45
2c. Page Content and Component Coverage
Landing
- Information/state: Anonymous first impression explaining Noor Al-Dhikr and its Arabic Qur’an reading, listening, tafsir, and adhkar purpose. The top 40% of the viewport is paper-white
#F7F4EE with a single centred line of Amiri Arabic — the app name نور الذكر — at 44px mobile to 72px desktop, in charcoal ink #23211E, with a 1px brass hairline #A87B3F beneath it spanning exactly the width of the text.
- Primary actions: A single full-width rectangle in deep mosque green
#3E4A3D with the word «اقرأ» centred in paper-white — one button, one colour, one action — entering the app.
- Supporting actions: A quiet secondary text link to continue without reading (entering Home directly).
- Domain entities: App identity, product purpose statement.
- Component responsibilities: Hero wordmark block; single primary action button; hairline rule; optional secondary text link.
- States: Loading (brief, static wordmark only); empty (not applicable — static content); success (primary action navigates to Home); error (not applicable); recovery (not applicable).
Home
- Information/state: Arabic daily hub. Continue Reading block as one oversized Arabic line (surah name + ayah number in Arabic-Indic numerals) at 40/52/64px, flush right, with a small brass «متابعة» label above it in 13px tracked Amiri. Daily verse card crowned by a hairline mihrab arch (1px ogee stroke). Quick adhkar row of six square tiles, no radius. Recently opened surahs as a plain ruled list. Last played recitation line. Prayer-inspired calming visuals and minimalist Islamic geometric accents (single hairline eight-point star as section divider, never tiled).
- Primary actions: Tap Continue Reading to resume at the saved position; tap the daily verse card to open the verse in the reader; tap an adhkar tile to open that adhkar set; tap a recently opened surah to open it; tap the last played recitation to resume playback.
- Supporting actions: Navigate to Quran Browse, Search, الأذكار, Favorites, Reminders, Settings via the bottom bar of five 1.5px-stroke pictograms with Arabic labels beneath.
- Domain entities: Reading position, daily verse, adhkar categories, recently opened surahs, last played recitation.
- Component responsibilities: Continue Reading block; mihrab-arched daily verse card; six-tile adhkar row; ruled recently-opened list; last-played recitation line; bottom navigation bar.
- States: Loading (skeleton ruled blocks); empty (first launch — Continue Reading and recently opened hidden, daily verse still shown); success (all blocks populated); error (content fetch failure — cached content shown with a quiet inline notice); recovery (retry via pull-to-refresh hairline that extends and retracts).
Quran Browse
- Information/state: Browsing and selection of Qur’an content by Surah, Juz, Hizb, or Page. Tabbed or segmented selection of the four browse modes; each mode lists its items with Arabic-Indic numerals for surah numbers and juz markers.
- Primary actions: Select a browse mode; select an item to open it in the Quran Reader.
- Supporting actions: Search entry; filter by browse mode.
- Domain entities: Surah, Juz, Hizb, Page, verse metadata.
- Component responsibilities: Browse-mode selector; item list with Arabic-Indic numerals; search entry point.
- States: Loading (ruled list skeleton); empty (no items for a mode — not expected, but shown as a quiet empty frame with the hairline mihrab arch); success (list populated); error (fetch failure — cached list shown with inline notice); recovery (retry).
Page 6 of 45
Quran Reader
- Information/state: Focused Mushaf and verse reading workspace. Mushaf reading mode with realistic page-style layout; verse-by-verse reading; smooth Arabic typography; verse highlighting during audio playback (1px brass underline that fades in over 400ms and holds); Tajweed-aware text rendering if available; night/sepia/paper Mushaf modes. A persistent 1px vertical hairline runs down the right edge of the reading column, carrying juz/hizb tick marks and a small moving dot for the current verse.
- Primary actions: Read; scroll; tap a verse to select it; bookmark a verse; add to favorites; open the verse tafsir bottom sheet; start or resume recitation for the current verse; toggle focus mode.
- Supporting actions: Open Reading Settings; switch translation; open Search; navigate to Favorites.
- Domain entities: Surah, verse, word-level data, bookmark, favorite, reading position, tafsir reference, translation.
- Component responsibilities: Mushaf page renderer; verse-by-verse renderer; wayfinding rail; verse selection and highlight; bookmark and favorite controls; tafsir bottom sheet; focus mode toggle; playback controls.
- States: Loading (page skeleton with ruled baselines); empty (not applicable); success (page rendered); error (content fetch failure — cached page shown, or a respectful error frame with retry); recovery (retry; offline fallback to cache).
Reading Settings
- Information/state: Dedicated reading appearance and typography choices: font selection (IndoPak, Uthmani, multiple Qur’an fonts), adjustable font size, adjustable line spacing, display modes (night, sepia, paper Mushaf), focus mode, and distraction-free reading.
- Primary actions: Select font; adjust font size; adjust line spacing; select display mode; toggle focus mode.
- Supporting actions: Preview of the current typography settings.
- Domain entities: Font preference, size preference, spacing preference, display mode preference.
- Component responsibilities: Font selector; size slider; spacing slider; display-mode selector; focus-mode toggle; live preview.
- States: Loading (not applicable — local preferences); empty (not applicable); success (settings applied immediately); error (not applicable); recovery (not applicable).
Search
- Information/state: Cross-source search for Arabic Qur’an text, translations, and tafsir, with verse result navigation. Search results show the matched source and the verse reference.
- Primary actions: Enter a query; select a source scope (Arabic text, translations, tafsir); select a result to open the verse in the Quran Reader.
- Supporting actions: Clear query; refine source scope.
- Domain entities: Search query, search result, verse reference, source type.
- Component responsibilities: Search input; source-scope selector; result list; result-to-verse navigation.
- States: Loading (hairline progress); empty (no query — quiet prompt; no results — respectful empty frame with the hairline mihrab arch); success (results listed); error (search failure — inline notice with retry); recovery (retry).
Page 7 of 45
Translations
- Information/state: Parallel Arabic and translation reading with instant translation selection and downloadable resources. Supported translations: Arabic Tafsir Ibn Kathir, Tafsir Al-Saadi, Tafsir Al-Jalalayn, English Saheeh International, plus an architecture for additional downloadable translations.
- Primary actions: Select a translation; switch translations instantly; toggle parallel reading mode; download an additional translation.
- Supporting actions: Open the verse tafsir bottom sheet; navigate to Tafsir.
- Domain entities: Translation resource, translation text, verse reference, download state.
- Component responsibilities: Translation selector; parallel reading layout; download control; verse reference display.
- States: Loading (translation fetch); empty (no translation selected — prompt); success (translation rendered); error (fetch failure — cached translation shown with inline notice); recovery (retry; offline fallback).
Tafsir
- Information/state: Verse study destination for trusted tafsir references and additional translation resources. Tafsir is presented in a bottom sheet from the reader and as a dedicated study view.
- Primary actions: Select a tafsir source; read tafsir for a verse; navigate between verses; download additional tafsir resources.
- Supporting actions: Open the verse in the reader; switch translation.
- Domain entities: Tafsir resource, tafsir text, verse reference, download state.
- Component responsibilities: Tafsir source selector; tafsir text view; verse navigation; download control.
- States: Loading (tafsir fetch); empty (no tafsir selected — prompt); success (tafsir rendered); error (fetch failure — cached tafsir shown with inline notice); recovery (retry; offline fallback).
Recitations
- Information/state: Reciter selection and streaming or offline audio resource management for the ten named reciters: مشاري راشد العفاسي، عبد الباسط عبد الصمد، ماهر المعيقلي، السديس، سعد الغامدي، ياسر الدوسري، فارس عباد، أحمد العجمي، المنشاوي، الحذيفي.
- Primary actions: Select a reciter; start streaming; download a recitation for offline caching; remove a download.
- Supporting actions: View download state and size; navigate to the Audio Player.
- Domain entities: Reciter, recitation resource, audio URL, download state, verse timing.
- Component responsibilities: Reciter list; download controls; download state display; navigation to player.
- States: Loading (reciter list fetch); empty (no reciters loaded — prompt with retry); success (reciters listed); error (fetch failure — cached list shown with inline notice); recovery (retry).
Page 8 of 45
Audio Player
- Information/state: Playback workspace for synchronized recitation, translation audio, repeat modes, sleep timer, and continuation. Shows the current surah, verse, reciter name in deep mosque green when playing, and the currently-reciting verse marked by a 1px brass underline.
- Primary actions: Play/pause; seek; skip verse; set sleep timer; set repeat verse mode; set repeat range mode; toggle auto-next surah; toggle translation audio playback; adjust playback.
- Supporting actions: Open the reader at the current verse; change reciter; download for offline.
- Domain entities: Playback session, reciter, verse timing, repeat mode, sleep timer, translation audio.
- Component responsibilities: Transport controls; verse-synchronized highlight; repeat-mode controls; sleep-timer control; translation-audio toggle; lock screen control integration.
- States: Loading (buffering indicator); empty (no recitation selected — prompt); success (playing with synchronized highlight); error (stream failure — inline notice with retry and offline fallback); recovery (retry; switch to cached audio).
الأذكار
- Information/state: The dedicated source-named adhkar section. Categories: أذكار الصباح، أذكار المساء، أذكار النوم، أذكار الصلاة، أذكار الاستيقاظ، أذكار السفر، تسبيح إلكتروني، favorites, and daily reminders. Adhkar cards are square-cornered ruled panels with a right-aligned count ring drawn in a single 1px brass stroke.
- Primary actions: Select an adhkar category; tap anywhere on a panel to increment the count (180ms Arabic-Indic numeral swap); mark a favorite; open the electronic tasbih; set daily reminders.
- Supporting actions: Navigate to Favorites; navigate to Reminders.
- Domain entities: Adhkar category, adhkar item, count, favorite, reminder.
- Component responsibilities: Category list; adhkar panel with count ring; tasbih counter; favorite control; reminder entry.
- States: Loading (local content — near-instant); empty (not applicable — content is bundled); success (panels rendered with counts); error (not applicable — offline storage); recovery (not applicable).
Favorites
- Information/state: Revisitable collection of bookmarked Qur’an verses and favored adhkar.
- Primary actions: Open a favorited verse in the reader; open a favorited adhkar item; remove a favorite.
- Supporting actions: Filter by type (verses, adhkar).
- Domain entities: Favorite verse, favorite adhkar item.
- Component responsibilities: Favorites list; type filter; removal control; navigation to source.
- States: Loading (local content — near-instant); empty (no favorites — quiet empty frame with the hairline mihrab arch); success (favorites listed); error (not applicable — local storage); recovery (not applicable).
Page 9 of 45
Reminders
- Information/state: Local scheduling and management of daily verse, morning adhkar, and evening adhkar reminders, plus optional reading goals. All reminders are respectful, non-intrusive, locally scheduled, and have no cloud dependency.
- Primary actions: Enable/disable daily verse reminder; enable/disable morning adhkar reminder; enable/disable evening adhkar reminder; set optional reading goals; set reminder times.
- Supporting actions: View scheduled reminders.
- Domain entities: Reminder, reminder time, reading goal.
- Component responsibilities: Reminder toggles; time pickers; reading-goal control; local scheduling integration.
- States: Loading (local — near-instant); empty (no reminders enabled — prompt); success (reminders scheduled); error (scheduling failure — inline notice with retry); recovery (retry).
Settings
- Information/state: Application-wide preferences as a ruled list of label/value pairs, right-aligned values, hairline dividers: font selection, theme selection, audio quality, download management, translation preferences, tafsir preferences, reminder settings, cache cleanup, accessibility settings.
- Primary actions: Change any preference; manage downloads; clean cache; configure accessibility.
- Supporting actions: Navigate to Reading Settings; navigate to Reminders.
- Domain entities: Preference, download, cache entry, accessibility setting.
- Component responsibilities: Ruled preference list; value controls; download manager; cache cleanup control; accessibility controls.
- States: Loading (local — near-instant); empty (not applicable); success (preferences applied); error (cache cleanup failure — inline notice); recovery (retry).
3. Functional Requirements
Each requirement is a distinct story point with provenance, lifecycle facts, and observable acceptance.
Page 10 of 45
Core Qur’an Features
FR-1 — Browse the Holy Qur’an by Surah (explicit)
As a Qur’an Reader, I should browse the full Holy Qur’an by Surah so that I can select any surah to read.
- Trigger/input: Open Quran Browse and select the Surah mode.
- Observable result: A list of surahs with Arabic-Indic numerals for surah numbers.
- Access state: No account required; content available online and from cache.
- Failure/recovery: If the surah list cannot be fetched, the cached list is shown with a quiet inline notice and retry.
- Continuation: Selecting a surah opens it in the Quran Reader.
FR-2 — Browse the Holy Qur’an by Juz (explicit)
As a Qur’an Reader, I should browse the full Holy Qur’an by Juz so that I can read by juz division.
- Trigger/input: Open Quran Browse and select the Juz mode.
- Observable result: A list of juz with Arabic-Indic juz markers.
- Access state: No account required; content available online and from cache.
- Failure/recovery: Cached list shown with inline notice and retry on fetch failure.
- Continuation: Selecting a juz opens it in the Quran Reader.
FR-3 — Browse the Holy Qur’an by Hizb (explicit)
As a Qur’an Reader, I should browse the full Holy Qur’an by Hizb so that I can read by hizb division.
- Trigger/input: Open Quran Browse and select the Hizb mode.
- Observable result: A list of hizb with Arabic-Indic markers.
- Access state: No account required; content available online and from cache.
- Failure/recovery: Cached list shown with inline notice and retry on fetch failure.
- Continuation: Selecting a hizb opens it in the Quran Reader.
FR-4 — Browse the Holy Qur’an by Page (explicit)
As a Qur’an Reader, I should browse the full Holy Qur’an by Page so that I can read by Mushaf page.
- Trigger/input: Open Quran Browse and select the Page mode.
- Observable result: A list of pages with Arabic-Indic page numbers.
- Access state: No account required; content available online and from cache.
- Failure/recovery: Cached list shown with inline notice and retry on fetch failure.
- Continuation: Selecting a page opens it in the Quran Reader.
FR-5 — Mushaf reading mode with realistic page-style layout (explicit)
As a Qur’an Reader, I should read in Mushaf mode with a realistic page-style layout so that reading feels like a printed mushaf.
- Trigger/input: Open a page in the Quran Reader and select Mushaf mode.
- Observable result: Verses rendered in page-style layout using page boundaries and word-level data.
- Access state: No account required; content available online and from cache.
- Failure/recovery: Cached page shown on fetch failure; respectful error frame with retry if no cache.
- Continuation: Page turns use a 300ms horizontal paper-fold crossfade.
FR-6 — Verse-by-verse reading (explicit)
As a Qur’an Reader, I should read verse by verse so that I can focus on individual ayahs.
- Trigger/input: Open a surah in the Quran Reader and select verse-by-verse mode.
- Observable result: Verses rendered individually with Arabic-Indic ayah numbers.
- Access state: No account required; content available online and from cache.
- Failure/recovery: Cached verses shown on fetch failure; retry available.
- Continuation: Scrolling continues through the surah.
FR-7 — Smooth Arabic typography (explicit)
As a Qur’an Reader, I should see smooth Arabic typography so that reading is comfortable and respectful.
- Trigger/input: Open any reading surface.
- Observable result: Arabic text rendered in Amiri (display) and Noto Naskh Arabic (body) with generous line-height (2.0 for Qur’an).
- Access state: No account required.
- Failure/recovery: Font fallback to a bundled Naskh face if a font fails to load.
- Continuation: Typography settings persist across sessions.
FR-8 — Verse highlighting during audio playback (explicit)
As a Recitation Listener, I should see the currently-reciting verse highlighted so that I can follow along.
- Trigger/input: Start recitation playback.
- Observable result: The currently-reciting verse is marked by a 1px brass underline that fades in over 400ms and holds — no pulsing, no glow.
- Access state: No account required.
- Failure/recovery: If timing data is unavailable, highlighting falls back to verse-level advance on audio position.
- Continuation: Highlight advances with playback.
FR-9 — Bookmark verses (explicit)
As a Qur’an Reader, I should bookmark verses so that I can return to them.
- Trigger/input: Tap a verse and select bookmark.
- Observable result: The verse is saved as a bookmark and appears in Favorites.
- Access state: No account required; stored locally.
- Failure/recovery: If local storage write fails, an inline notice is shown and the action can be retried.
- Continuation: The bookmark persists across sessions.
FR-10 — Continue reading feature (explicit)
As a Qur’an Reader, I should continue reading from where I left off so that I can resume without searching.
- Trigger/input: Open Home.
- Observable result: The Continue Reading block shows the last surah name and ayah number in Arabic-Indic numerals.
- Access state: No account required; reading position stored locally.
- Failure/recovery: If no position exists, the block is hidden.
- Continuation: Tapping the block opens the reader at the saved position.
FR-11 — Daily verse reflection widget/card (explicit)
As a Qur’an Reader, I should see a daily verse reflection card so that I have a moment of reflection each day.
- Trigger/input: Open Home.
- Observable result: A daily verse card crowned by a hairline mihrab arch (1px ogee stroke).
- Access state: No account required; content from cache or API.
- Failure/recovery: Cached daily verse shown on fetch failure.
- Continuation: Tapping the card opens the verse in the reader.
FR-12 — Favorites system (explicit)
As a Qur’an Reader, I should keep favorites so that I can revisit verses and adhkar.
- Trigger/input: Mark a verse or adhkar item as favorite.
- Observable result: The item appears in Favorites.
- Access state: No account required; stored locally.
- Failure/recovery: Inline notice and retry on storage failure.
- Continuation: Favorites persist across sessions.
FR-13 — Search in Arabic Qur’an text (explicit)
As a Qur’an Reader, I should search the Arabic Qur’an text so that I can locate verses.
- Trigger/input: Enter a query in Search with the Arabic text scope.
- Observable result: Matching verses listed with references.
- Access state: No account required.
- Failure/recovery: Inline notice with retry on search failure.
- Continuation: Selecting a result opens the verse in the reader.
FR-14 — Search in translations (explicit)
As a Tafsir & Translation Student, I should search translations so that I can find verses by meaning.
- Trigger/input: Enter a query in Search with the translations scope.
- Observable result: Matching translation passages listed with verse references.
- Access state: No account required.
- Failure/recovery: Inline notice with retry on search failure.
- Continuation: Selecting a result opens the verse in the reader.
FR-15 — Search in tafsir (explicit)
As a Tafsir & Translation Student, I should search tafsir so that I can find explanations.
- Trigger/input: Enter a query in Search with the tafsir scope.
- Observable result: Matching tafsir passages listed with verse references.
- Access state: No account required.
- Failure/recovery: Inline notice with retry on search failure.
- Continuation: Selecting a result opens the verse in the reader.
FR-16 — Tajweed-aware text rendering if available (explicit)
As a Qur’an Reader, I should see Tajweed-aware rendering when available so that recitation rules are visible.
- Trigger/input: Open a reading surface where Tajweed data is available.
- Observable result: Tajweed-aware rendering applied.
- Access state: No account required.
- Failure/recovery: If Tajweed data is unavailable, standard rendering is used without error.
- Continuation: Rendering preference persists.
FR-17 — Night mode, sepia mode, and paper Mushaf mode (explicit)
As a Qur’an Reader, I should switch between night, sepia, and paper Mushaf modes so that reading suits my environment.
- Trigger/input: Select a display mode in Reading Settings.
- Observable result: Night mode uses warm graphite ground
#141413 with paper-white type #EDE8DE and brass accent; sepia uses #F1E4CE ground with #2E2A24 ink; paper Mushaf uses #FBF6EA with a faint ruled baseline grid.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Mode persists across sessions.
Page 11 of 45
Arabic-First UI
FR-18 — Entire app interface in Arabic (explicit)
As a Qur’an Reader, I should see the entire interface in Arabic so that the app feels native to my language.
- Trigger/input: Open any screen.
- Observable result: All labels, controls, and copy are in Arabic.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Arabic is the default and only interface language.
FR-19 — RTL support across all screens (explicit)
As a Qur’an Reader, I should see RTL layout across all screens so that reading direction is correct.
- Trigger/input: Open any screen.
- Observable result: Layout is RTL-first with correct alignment and reading order.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: RTL is the default layout direction.
FR-20 — Elegant Islamic-inspired typography (explicit)
As a Qur’an Reader, I should see elegant Islamic-inspired typography so that the app feels respectful and premium.
- Trigger/input: Open any screen.
- Observable result: Amiri for Arabic display and surah titles; Noto Naskh Arabic for interface body and adhkar text; Arabic-Indic numerals in Amiri for surah numbers, juz markers, and tasbih counts.
- Access state: No account required.
- Failure/recovery: Font fallback to bundled Naskh face.
- Continuation: Typography persists.
FR-21 — Readable spacing and calm visual hierarchy (explicit)
As a Qur’an Reader, I should see readable spacing and a calm visual hierarchy so that reading is comfortable.
- Trigger/input: Open any screen.
- Observable result: Generous line-height (1.9–2.1 for Arabic), single-column centred reading measure of 34em max, margins that grow with viewport (24px at 375, 64px at 768, 120px at 1280).
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Layout persists.
FR-22 — Material 3 design system (explicit)
As a Qur’an Reader, I should see a Material 3 design system so that the app follows modern Android guidance.
- Trigger/input: Open any screen.
- Observable result: Material 3 components and tokens applied.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Design system persists.
FR-23 — Minimal and respectful animations (explicit)
As a Qur’an Reader, I should see minimal and respectful animations so that nothing distracts from the Word.
- Trigger/input: Navigate or interact.
- Observable result: Screen transitions are 220ms crossfades with no slide; verse highlight fades in over 400ms; tasbih count increments with a 180ms number swap; page turns are a 300ms paper-fold crossfade.
- Access state: No account required.
- Failure/recovery: Reduced-motion mode removes the fold and fades, leaving instant state changes.
- Continuation: Motion preferences persist.
FR-24 — Large readable Arabic text sizes (explicit)
As a Qur’an Reader, I should see large readable Arabic text sizes so that reading is easy at any age.
- Trigger/input: Open any reading surface.
- Observable result: Qur’an verse text 34px mobile / 44px tablet / 52px desktop-reading; surah title 40/52/64; body 17/18/19; metadata 14/14/15; tasbih count 72/96/120.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Sizes persist.
FR-25 — Accessibility-friendly colors and contrast (explicit)
As a Qur’an Reader, I should see accessible colors and contrast so that I can read comfortably.
- Trigger/input: Open any screen.
- Observable result: Palette uses paper-white ground
#F7F4EE, charcoal-ink text #23211E, deep mosque green #3E4A3D, brass accent #A87B3F, muted grey-brown #8A857B; contrast meets accessibility guidance.
- Access state: No account required.
- Failure/recovery: High contrast themes available.
- Continuation: Contrast preferences persist.
Page 12 of 45
Translations & Tafsir
FR-26 — Arabic Tafsir Ibn Kathir (explicit)
As a Tafsir & Translation Student, I should read Tafsir Ibn Kathir in Arabic so that I can study trusted explanation.
- Trigger/input: Select Tafsir Ibn Kathir in Tafsir or the verse tafsir bottom sheet.
- Observable result: Tafsir text rendered for the selected verse.
- Access state: No account required; content from API or cache.
- Failure/recovery: Cached tafsir shown on fetch failure; retry available.
- Continuation: Selection persists.
FR-27 — Tafsir Al-Saadi (explicit)
As a Tafsir & Translation Student, I should read Tafsir Al-Saadi so that I can study trusted explanation.
- Trigger/input: Select Tafsir Al-Saadi.
- Observable result: Tafsir text rendered for the selected verse.
- Access state: No account required; content from API or cache.
- Failure/recovery: Cached tafsir shown on fetch failure; retry available.
- Continuation: Selection persists.
FR-28 — Tafsir Al-Jalalayn (explicit)
As a Tafsir & Translation Student, I should read Tafsir Al-Jalalayn so that I can study trusted explanation.
- Trigger/input: Select Tafsir Al-Jalalayn.
- Observable result: Tafsir text rendered for the selected verse.
- Access state: No account required; content from API or cache.
- Failure/recovery: Cached tafsir shown on fetch failure; retry available.
- Continuation: Selection persists.
FR-29 — English Saheeh International (explicit)
As a Tafsir & Translation Student, I should read English Saheeh International so that I can study the meaning in English.
- Trigger/input: Select Saheeh International in Translations.
- Observable result: English translation rendered alongside the Arabic text.
- Access state: No account required; content from API or cache.
- Failure/recovery: Cached translation shown on fetch failure; retry available.
- Continuation: Selection persists.
FR-30 — Additional downloadable translations architecture (explicit)
As a Tafsir & Translation Student, I should download additional translations so that I can expand my study resources.
- Trigger/input: Select a downloadable translation in Translations.
- Observable result: The translation is downloaded and available offline.
- Access state: No account required; stored locally.
- Failure/recovery: Download failure shows inline notice with retry.
- Continuation: Downloaded translations persist.
FR-31 — Switching translations instantly (explicit)
As a Tafsir & Translation Student, I should switch translations instantly so that I can compare meanings without losing my place.
- Trigger/input: Select a different translation in Translations.
- Observable result: The translation switches immediately without losing reading position.
- Access state: No account required.
- Failure/recovery: Cached translation shown on fetch failure.
- Continuation: Reading position preserved.
FR-32 — Parallel reading mode (explicit)
As a Tafsir & Translation Student, I should read in parallel mode so that I can compare Arabic and translation side by side.
- Trigger/input: Toggle parallel reading mode in Translations.
- Observable result: Arabic text and translation rendered in parallel.
- Access state: No account required.
- Failure/recovery: Cached content shown on fetch failure.
- Continuation: Parallel mode persists.
FR-33 — Verse tafsir bottom sheet (explicit)
As a Tafsir & Translation Student, I should open a verse tafsir bottom sheet so that I can study a verse without leaving the reader.
- Trigger/input: Tap a verse and select tafsir.
- Observable result: A bottom sheet opens with the tafsir for that verse.
- Access state: No account required.
- Failure/recovery: Cached tafsir shown on fetch failure; retry available.
- Continuation: Closing the sheet returns to the reader at the same position.
FR-34 — Translation audio synchronization (explicit)
As a Recitation Listener, I should hear translation audio synchronized with the Arabic text so that I can follow both.
- Trigger/input: Enable translation audio playback in the Audio Player.
- Observable result: Translation audio plays in sync with the Arabic recitation and the verse highlight.
- Access state: No account required.
- Failure/recovery: If translation audio is unavailable, an inline notice is shown and Arabic-only playback continues.
- Continuation: Synchronization persists across verses.
Page 13 of 45
Audio Recitation Features
FR-35 — Top 10 reciters (explicit)
As a Recitation Listener, I should select from the top 10 reciters so that I can listen to my preferred recitation.
- Trigger/input: Open Recitations.
- Observable result: The ten named reciters are listed: مشاري راشد العفاسي، عبد الباسط عبد الصمد، ماهر المعيقلي، السديس، سعد الغامدي، ياسر الدوسري، فارس عباد، أحمد العجمي، المنشاوي، الحذيفي.
- Access state: No account required; reciter list from API or cache.
- Failure/recovery: Cached reciter list shown on fetch failure; retry available.
- Continuation: Selection persists.
FR-36 — Stream recitations (explicit)
As a Recitation Listener, I should stream recitations so that I can listen without downloading.
- Trigger/input: Select a reciter and start playback.
- Observable result: Audio streams and plays.
- Access state: No account required.
- Failure/recovery: Stream failure shows inline notice with retry and offline fallback.
- Continuation: Playback continues to the next verse or surah.
FR-37 — Optional offline download caching (explicit)
As a Recitation Listener, I should optionally download recitations so that I can listen offline.
- Trigger/input: Select download for a recitation in Recitations.
- Observable result: The recitation is cached locally and available offline.
- Access state: No account required; stored locally.
- Failure/recovery: Download failure shows inline notice with retry.
- Continuation: Downloaded recitations persist.
FR-38 — Background playback (explicit)
As a Recitation Listener, I should continue listening in the background so that I can use other apps.
- Trigger/input: Start playback and leave the app.
- Observable result: Playback continues via the foreground media playback service.
- Access state: No account required;
FOREGROUND_SERVICE_MEDIA_PLAYBACK used if needed.
- Failure/recovery: If the service is interrupted, playback pauses and can be resumed.
- Continuation: Playback resumes from the last position.
FR-39 — Lock screen controls (explicit)
As a Recitation Listener, I should control playback from the lock screen so that I can pause or skip without unlocking.
- Trigger/input: Start playback and lock the device.
- Observable result: Lock screen controls are available.
- Access state: No account required.
- Failure/recovery: If controls are unavailable, playback continues and can be controlled in-app.
- Continuation: Controls remain available during playback.
FR-40 — Sleep timer (explicit)
As a Recitation Listener, I should set a sleep timer so that playback stops after a chosen duration.
- Trigger/input: Set a sleep timer in the Audio Player.
- Observable result: Playback stops after the chosen duration.
- Access state: No account required.
- Failure/recovery: If the timer fails, playback continues and the timer can be reset.
- Continuation: Timer setting persists for the session.
FR-41 — Repeat verse mode (explicit)
As a Recitation Listener, I should repeat a verse so that I can memorize it.
- Trigger/input: Enable repeat verse mode in the Audio Player.
- Observable result: The current verse repeats.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Repeat continues until disabled.
FR-42 — Repeat range mode (explicit)
As a Recitation Listener, I should repeat a range of verses so that I can memorize a passage.
- Trigger/input: Enable repeat range mode and select a range.
- Observable result: The selected range repeats.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Repeat continues until disabled.
FR-43 — Auto-next surah (explicit)
As a Recitation Listener, I should have auto-next surah so that playback continues without manual selection.
- Trigger/input: Enable auto-next surah in the Audio Player.
- Observable result: Playback continues to the next surah when the current one ends.
- Access state: No account required.
- Failure/recovery: If the next surah cannot be loaded, playback pauses with an inline notice.
- Continuation: Playback resumes when the next surah is available.
FR-44 — Translation audio playback (explicit)
As a Recitation Listener, I should play translation audio so that I can hear the meaning.
- Trigger/input: Enable translation audio playback in the Audio Player.
- Observable result: Translation audio plays in sync with the Arabic recitation.
- Access state: No account required.
- Failure/recovery: If translation audio is unavailable, an inline notice is shown and Arabic-only playback continues.
- Continuation: Translation audio continues across verses.
FR-45 — Verse synchronized highlighting (explicit)
As a Recitation Listener, I should see verse-synchronized highlighting so that I can follow the recitation.
- Trigger/input: Start recitation playback.
- Observable result: The currently-reciting verse is marked by a 1px brass underline that fades in over 400ms and holds.
- Access state: No account required.
- Failure/recovery: If timing data is unavailable, highlighting falls back to verse-level advance on audio position.
- Continuation: Highlight advances with playback.
FR-46 — Media3 / ExoPlayer (explicit)
As a Recitation Listener, I should have reliable playback so that listening is uninterrupted.
- Trigger/input: Start any playback.
- Observable result: Playback is handled by Media3/ExoPlayer.
- Access state: No account required.
- Failure/recovery: Playback errors show inline notice with retry.
- Continuation: Playback resumes from the last position.
Page 14 of 45
Adhkar Section
FR-47 — Dedicated الأذكار section (explicit)
As an Adhkar Practitioner, I should open a dedicated الأذكار section so that I can perform daily remembrance.
- Trigger/input: Navigate to الأذكار.
- Observable result: The adhkar section opens with its categories.
- Access state: No account required; content stored offline.
- Failure/recovery: Not applicable — content is bundled.
- Continuation: Section remains available offline.
FR-48 — أذكار الصباح (explicit)
As an Adhkar Practitioner, I should read أذكار الصباح so that I can perform morning remembrance.
- Trigger/input: Select أذكار الصباح.
- Observable result: Morning adhkar panels rendered with count rings.
- Access state: No account required; offline storage.
- Failure/recovery: Not applicable.
- Continuation: Counts persist.
FR-49 — أذكار المساء (explicit)
As an Adhkar Practitioner, I should read أذكار المساء so that I can perform evening remembrance.
- Trigger/input: Select أذكار المساء.
- Observable result: Evening adhkar panels rendered with count rings.
- Access state: No account required; offline storage.
- Failure/recovery: Not applicable.
- Continuation: Counts persist.
FR-50 — أذكار النوم (explicit)
As an Adhkar Practitioner, I should read أذكار النوم so that I can perform sleep remembrance.
- Trigger/input: Select أذكار النوم.
- Observable result: Sleep adhkar panels rendered with count rings.
- Access state: No account required; offline storage.
- Failure/recovery: Not applicable.
- Continuation: Counts persist.
FR-51 — أذكار الصلاة (explicit)
As an Adhkar Practitioner, I should read أذكار الصلاة so that I can perform prayer remembrance.
- Trigger/input: Select أذكار الصلاة.
- Observable result: Prayer adhkar panels rendered with count rings.
- Access state: No account required; offline storage.
- Failure/recovery: Not applicable.
- Continuation: Counts persist.
FR-52 — أذكار الاستيقاظ (explicit)
As an Adhkar Practitioner, I should read أذكار الاستيقاظ so that I can perform waking remembrance.
- Trigger/input: Select أذكار الاستيقاظ.
- Observable result: Waking adhkar panels rendered with count rings.
- Access state: No account required; offline storage.
- Failure/recovery: Not applicable.
- Continuation: Counts persist.
FR-53 — أذكار السفر (explicit)
As an Adhkar Practitioner, I should read أذكار السفر so that I can perform travel remembrance.
- Trigger/input: Select أذكار السفر.
- Observable result: Travel adhkar panels rendered with count rings.
- Access state: No account required; offline storage.
- Failure/recovery: Not applicable.
- Continuation: Counts persist.
FR-54 — تسبيح إلكتروني (explicit)
As an Adhkar Practitioner, I should use an electronic tasbih so that I can count my remembrance.
- Trigger/input: Open تسبيح إلكتروني.
- Observable result: A tasbih counter with a 1px brass count ring and Arabic-Indic numerals at display scale (72/96/120).
- Access state: No account required; offline storage.
- Failure/recovery: Not applicable.
- Continuation: Count persists.
FR-55 — Adhkar favorites (explicit)
As an Adhkar Practitioner, I should favorite adhkar so that I can revisit them.
- Trigger/input: Mark an adhkar item as favorite.
- Observable result: The item appears in Favorites.
- Access state: No account required; stored locally.
- Failure/recovery: Inline notice and retry on storage failure.
- Continuation: Favorites persist.
FR-56 — Daily reminders (explicit)
As an Adhkar Practitioner, I should receive daily reminders so that I remember my adhkar.
- Trigger/input: Enable daily reminders in Reminders.
- Observable result: Reminders are scheduled locally.
- Access state: No account required; no cloud dependency.
- Failure/recovery: Scheduling failure shows inline notice with retry.
- Continuation: Reminders persist.
FR-57 — Count tracking (explicit)
As an Adhkar Practitioner, I should track counts so that I complete each adhkar set accurately.
- Trigger/input: Tap anywhere on an adhkar panel.
- Observable result: The count increments with a 180ms Arabic-Indic numeral swap and a 1px ring progress stroke that draws forward.
- Access state: No account required; stored locally.
- Failure/recovery: Inline notice and retry on storage failure.
- Continuation: Counts persist.
FR-58 — Elegant card UI (explicit)
As an Adhkar Practitioner, I should see elegant card UI so that the experience feels respectful.
- Trigger/input: Open الأذكار.
- Observable result: Adhkar cards are square-cornered ruled panels with a right-aligned count ring drawn in a single 1px brass stroke.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: UI persists.
FR-59 — Soft animations (explicit)
As an Adhkar Practitioner, I should see soft animations so that the experience feels calm.
- Trigger/input: Interact with adhkar.
- Observable result: Count increments with a 180ms number swap; no pulsing, bouncing, or glowing.
- Access state: No account required.
- Failure/recovery: Reduced-motion mode removes animations.
- Continuation: Motion preferences persist.
FR-60 — Offline storage (explicit)
As an Adhkar Practitioner, I should use adhkar offline so that I can perform remembrance anywhere.
- Trigger/input: Open الأذكار without network.
- Observable result: Adhkar content and counts are available offline.
- Access state: No account required; stored locally.
- Failure/recovery: Not applicable.
- Continuation: Offline use persists.
Page 15 of 45
Privacy & Security Requirements
FR-61 — No ads (explicit)
As a Qur’an Reader, I should see no ads so that my reading is undisturbed.
- Trigger/input: Open any screen.
- Observable result: No ads are displayed anywhere.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: No ads ever.
FR-62 — No in-app purchases (explicit)
As a Qur’an Reader, I should see no in-app purchases so that the app remains free of commerce.
- Trigger/input: Open any screen.
- Observable result: No in-app purchase flows exist.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: No in-app purchases ever.
FR-63 — No camera permission (explicit)
As a Qur’an Reader, I should not be asked for camera permission so that my privacy is protected.
- Trigger/input: Install and use the app.
- Observable result: The app does not declare or request camera permission.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: No camera permission ever.
FR-64 — No microphone permission (explicit)
As a Qur’an Reader, I should not be asked for microphone permission so that my privacy is protected.
- Trigger/input: Install and use the app.
- Observable result: The app does not declare or request microphone permission.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: No microphone permission ever.
FR-65 — No location permission (explicit)
As a Qur’an Reader, I should not be asked for location permission so that my privacy is protected.
- Trigger/input: Install and use the app.
- Observable result: The app does not declare or request location permission.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: No location permission ever.
FR-66 — No contacts permission (explicit)
As a Qur’an Reader, I should not be asked for contacts permission so that my privacy is protected.
- Trigger/input: Install and use the app.
- Observable result: The app does not declare or request contacts permission.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: No contacts permission ever.
FR-67 — No unnecessary storage permission (explicit)
As a Qur’an Reader, I should not be asked for unnecessary storage permission so that my privacy is protected.
- Trigger/input: Install and use the app.
- Observable result: The app does not declare or request unnecessary storage permission.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: No unnecessary storage permission ever.
FR-68 — Only INTERNET and FOREGROUND_SERVICE_MEDIA_PLAYBACK if needed (explicit)
As a Qur’an Reader, I should see only the necessary permissions so that my privacy is protected.
- Trigger/input: Install and use the app.
- Observable result: Only
INTERNET and FOREGROUND_SERVICE_MEDIA_PLAYBACK (if needed) are declared.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Permission set remains minimal.
FR-69 — No analytics SDKs (explicit)
As a Qur’an Reader, I should see no analytics SDKs so that my usage is not tracked.
- Trigger/input: Install and use the app.
- Observable result: No analytics SDKs are included.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: No analytics SDKs ever.
FR-70 — No tracking SDKs (explicit)
As a Qur’an Reader, I should see no tracking SDKs so that my usage is not tracked.
- Trigger/input: Install and use the app.
- Observable result: No tracking SDKs are included.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: No tracking SDKs ever.
FR-71 — No user data collection (explicit)
As a Qur’an Reader, I should have no user data collected so that my privacy is protected.
- Trigger/input: Install and use the app.
- Observable result: No user data is collected or transmitted.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: No user data collection ever.
Page 16 of 45
Architecture Requirements
FR-72 — Kotlin (explicit)
As a developer, I should use Kotlin so that the codebase follows modern Android practice.
- Trigger/input: Build the project.
- Observable result: All code is written in Kotlin.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Kotlin is the language.
FR-73 — Jetpack Compose (explicit)
As a developer, I should use Jetpack Compose so that UI is declarative and modern.
- Trigger/input: Build the UI.
- Observable result: All UI is built with Jetpack Compose.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Compose is the UI toolkit.
FR-74 — Material 3 (explicit)
As a developer, I should use Material 3 so that the app follows modern design guidance.
- Trigger/input: Build the UI.
- Observable result: Material 3 components and tokens are used.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Material 3 is the design system.
FR-75 — Clean Architecture (explicit)
As a developer, I should use Clean Architecture so that the codebase is maintainable.
- Trigger/input: Structure the project.
- Observable result: Layers are separated into presentation, domain, data, core, and designsystem.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Clean Architecture is the structure.
FR-76 — MVVM (explicit)
As a developer, I should use MVVM so that UI and logic are separated.
- Trigger/input: Structure the presentation layer.
- Observable result: ViewModels mediate between UI and domain.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: MVVM is the pattern.
FR-77 — Repository Pattern (explicit)
As a developer, I should use the Repository Pattern so that data access is abstracted.
- Trigger/input: Structure the data layer.
- Observable result: Repositories mediate between data sources and domain.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Repository Pattern is used.
FR-78 — Hilt Dependency Injection (explicit)
As a developer, I should use Hilt so that dependencies are injected cleanly.
- Trigger/input: Configure DI.
- Observable result: Hilt provides dependencies.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Hilt is the DI framework.
FR-79 — Retrofit + OkHttp (explicit)
As a developer, I should use Retrofit + OkHttp so that API calls are reliable.
- Trigger/input: Configure networking.
- Observable result: Retrofit + OkHttp handle API calls.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Retrofit + OkHttp are the networking stack.
FR-80 — Room Database (explicit)
As a developer, I should use Room so that local data is persisted.
- Trigger/input: Configure local storage.
- Observable result: Room stores local data.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Room is the local database.
FR-81 — Coroutines + Flow (explicit)
As a developer, I should use Coroutines + Flow so that async work is clean.
- Trigger/input: Configure async.
- Observable result: Coroutines + Flow handle async work.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Coroutines + Flow are used.
FR-82 — DataStore Preferences (explicit)
As a developer, I should use DataStore Preferences so that preferences are stored cleanly.
- Trigger/input: Configure preferences.
- Observable result: DataStore stores preferences.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: DataStore is used.
FR-83 — Media3 ExoPlayer (explicit)
As a developer, I should use Media3 ExoPlayer so that playback is reliable.
- Trigger/input: Configure playback.
- Observable result: Media3 ExoPlayer handles playback.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Media3 ExoPlayer is used.
FR-84 — Project layers (explicit)
As a developer, I should organize the project into presentation, domain, data, core, and designsystem layers so that the codebase is maintainable.
- Trigger/input: Structure the project.
- Observable result: The five layers exist.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Layers persist.
FR-85 — Feature modularization (explicit)
As a developer, I should modularize features into feature_quran, feature_audio, feature_tafsir, feature_adhkar, feature_bookmarks, and feature_settings so that the codebase is scalable.
- Trigger/input: Structure the project.
- Observable result: The six feature modules exist.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Modules persist.
Page 17 of 45
Quran.com API Integration
FR-86 — Use Quran.com API for Surahs (explicit)
As a developer, I should use the Quran.com API for surahs so that Qur’an content is accurate.
- Trigger/input: Fetch surah data.
- Observable result: Surah data comes from the Quran.com API.
- Access state: Content APIs use
client_credentials grant with x-auth-token and x-client-id headers.
- Failure/recovery: Cached data shown on fetch failure; retry available.
- Continuation: Data persists in cache.
FR-87 — Use Quran.com API for Ayahs (explicit)
As a developer, I should use the Quran.com API for ayahs so that Qur’an text is accurate.
- Trigger/input: Fetch ayah data.
- Observable result: Ayah data comes from the Quran.com API.
- Access state: Content APIs use
client_credentials grant with x-auth-token and x-client-id headers.
- Failure/recovery: Cached data shown on fetch failure; retry available.
- Continuation: Data persists in cache.
FR-88 — Use Quran.com API for Audio URLs (explicit)
As a developer, I should use the Quran.com API for audio URLs so that recitations are accurate.
- Trigger/input: Fetch audio URLs.
- Observable result: Audio URLs come from the Quran.com API.
- Access state: Content APIs use
client_credentials grant with x-auth-token and x-client-id headers.
- Failure/recovery: Cached URLs shown on fetch failure; retry available.
- Continuation: URLs persist in cache.
FR-89 — Use Quran.com API for Translations (explicit)
As a developer, I should use the Quran.com API for translations so that translations are accurate.
- Trigger/input: Fetch translations.
- Observable result: Translations come from the Quran.com API.
- Access state: Content APIs use
client_credentials grant with x-auth-token and x-client-id headers.
- Failure/recovery: Cached translations shown on fetch failure; retry available.
- Continuation: Translations persist in cache.
FR-90 — Use Quran.com API for Tafsir metadata (explicit)
As a developer, I should use the Quran.com API for tafsir metadata so that tafsir references are accurate.
- Trigger/input: Fetch tafsir metadata.
- Observable result: Tafsir metadata comes from the Quran.com API.
- Access state: Content APIs use
client_credentials grant with x-auth-token and x-client-id headers.
- Failure/recovery: Cached metadata shown on fetch failure; retry available.
- Continuation: Metadata persists in cache.
FR-91 — Use Quran.com API for Word-level data (explicit)
As a developer, I should use the Quran.com API for word-level data so that Mushaf rendering is accurate.
- Trigger/input: Fetch word-level data.
- Observable result: Word-level data comes from the Quran.com API.
- Access state: Content APIs use
client_credentials grant with x-auth-token and x-client-id headers.
- Failure/recovery: Cached data shown on fetch failure; retry available.
- Continuation: Data persists in cache.
FR-92 — Use Quran.com API for Verse timing (explicit)
As a developer, I should use the Quran.com API for verse timing so that synchronized highlighting is accurate.
- Trigger/input: Fetch verse timing.
- Observable result: Verse timing comes from the Quran.com API.
- Access state: Content APIs use
client_credentials grant with x-auth-token and x-client-id headers.
- Failure/recovery: Cached timing shown on fetch failure; retry available.
- Continuation: Timing persists in cache.
FR-93 — API caching (explicit)
As a developer, I should implement API caching so that content is available offline.
- Trigger/input: Fetch content.
- Observable result: Content is cached locally.
- Access state: Not applicable.
- Failure/recovery: Cache miss falls back to network.
- Continuation: Cache persists.
FR-94 — Offline fallback (explicit)
As a developer, I should implement offline fallback so that reading works without network.
- Trigger/input: Open content without network.
- Observable result: Cached content is shown.
- Access state: Not applicable.
- Failure/recovery: If no cache exists, a respectful error frame with retry is shown.
- Continuation: Offline reading persists.
FR-95 — Retry strategy (explicit)
As a developer, I should implement a retry strategy so that transient failures recover.
- Trigger/input: A request fails.
- Observable result: The request is retried according to the strategy.
- Access state: Not applicable.
- Failure/recovery: After retries are exhausted, an inline notice with manual retry is shown.
- Continuation: Manual retry available.
FR-96 — Respectful request handling (explicit)
As a developer, I should handle requests respectfully so that the API is not abused.
- Trigger/input: Make API requests.
- Observable result: Requests are throttled and batched respectfully.
- Access state: Not applicable.
- Failure/recovery: Rate-limit responses are handled with backoff.
- Continuation: Respectful handling persists.
FR-97 — Error-safe parsing to avoid text corruption (explicit)
As a developer, I should parse errors safely so that Qur’an text is never corrupted.
- Trigger/input: Parse API responses.
- Observable result: Parsing is error-safe and never corrupts text.
- Access state: Not applicable.
- Failure/recovery: Parse errors fall back to cached content and show an inline notice.
- Continuation: Text integrity persists.
Page 18 of 45
Mushaf Experience
FR-98 — IndoPak font support (explicit)
As a Qur’an Reader, I should read in IndoPak script so that I can use my preferred script.
- Trigger/input: Select IndoPak in Reading Settings.
- Observable result: Text renders in IndoPak script.
- Access state: No account required.
- Failure/recovery: Font fallback to bundled Naskh face.
- Continuation: Selection persists.
FR-99 — Uthmani script support (explicit)
As a Qur’an Reader, I should read in Uthmani script so that I can use the standard script.
- Trigger/input: Select Uthmani in Reading Settings.
- Observable result: Text renders in Uthmani script.
- Access state: No account required.
- Failure/recovery: Font fallback to bundled Naskh face.
- Continuation: Selection persists.
FR-100 — Multiple Qur’an fonts (explicit)
As a Qur’an Reader, I should choose from multiple Qur’an fonts so that I can read comfortably.
- Trigger/input: Select a font in Reading Settings.
- Observable result: Text renders in the selected font.
- Access state: No account required.
- Failure/recovery: Font fallback to bundled Naskh face.
- Continuation: Selection persists.
FR-101 — Adjustable font size (explicit)
As a Qur’an Reader, I should adjust font size so that I can read comfortably.
- Trigger/input: Adjust font size in Reading Settings.
- Observable result: Text size changes immediately.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Size persists.
FR-102 — Adjustable line spacing (explicit)
As a Qur’an Reader, I should adjust line spacing so that I can read comfortably.
- Trigger/input: Adjust line spacing in Reading Settings.
- Observable result: Line spacing changes immediately.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Spacing persists.
FR-103 — Realistic Mushaf page transitions (explicit)
As a Qur’an Reader, I should see realistic Mushaf page transitions so that reading feels like a printed mushaf.
- Trigger/input: Turn a page in Mushaf mode.
- Observable result: A 300ms horizontal paper-fold crossfade (a subtle 3D fold at the spine edge) is shown.
- Access state: No account required.
- Failure/recovery: Reduced-motion mode removes the fold, leaving instant state changes.
- Continuation: Transitions persist.
FR-104 — Focus mode (explicit)
As a Qur’an Reader, I should use focus mode so that I can read without distraction.
- Trigger/input: Toggle focus mode in Reading Settings or the reader.
- Observable result: Distracting elements are hidden.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Focus mode persists.
FR-105 — Distraction-free reading (explicit)
As a Qur’an Reader, I should read without distraction so that I can focus on the Word.
- Trigger/input: Enable focus mode.
- Observable result: Only the reading content is shown.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Distraction-free reading persists.
Page 19 of 45
Home Screen
FR-106 — Continue reading on Home (explicit)
As a Qur’an Reader, I should see Continue Reading on Home so that I can resume quickly.
- Trigger/input: Open Home.
- Observable result: The Continue Reading block shows the last surah name and ayah number in Arabic-Indic numerals.
- Access state: No account required.
- Failure/recovery: Hidden if no position exists.
- Continuation: Tapping opens the reader at the saved position.
FR-107 — Daily verse on Home (explicit)
As a Qur’an Reader, I should see the daily verse on Home so that I have a moment of reflection.
- Trigger/input: Open Home.
- Observable result: A daily verse card crowned by a hairline mihrab arch.
- Access state: No account required.
- Failure/recovery: Cached daily verse shown on fetch failure.
- Continuation: Tapping opens the verse in the reader.
FR-108 — Last played recitation on Home (explicit)
As a Recitation Listener, I should see the last played recitation on Home so that I can resume listening.
- Trigger/input: Open Home.
- Observable result: The last played recitation is shown.
- Access state: No account required.
- Failure/recovery: Hidden if no recitation has been played.
- Continuation: Tapping resumes playback.
FR-109 — Quick access to adhkar on Home (explicit)
As an Adhkar Practitioner, I should have quick access to adhkar on Home so that I can perform remembrance quickly.
- Trigger/input: Open Home.
- Observable result: A row of six square adhkar tiles.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Tapping opens the adhkar set.
FR-110 — Recently opened surahs on Home (explicit)
As a Qur’an Reader, I should see recently opened surahs on Home so that I can return to them.
- Trigger/input: Open Home.
- Observable result: A plain ruled list of recently opened surahs.
- Access state: No account required.
- Failure/recovery: Hidden if no surahs have been opened.
- Continuation: Tapping opens the surah.
FR-111 — Prayer-inspired calming visuals (explicit)
As a Qur’an Reader, I should see prayer-inspired calming visuals so that the app feels spiritually calming.
- Trigger/input: Open Home.
- Observable result: Paper-white ground with a single soft directional shadow under the daily-verse card (blur 24, y-offset 2, 4% black).
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Visuals persist.
FR-112 — Minimalist Islamic geometric accents (explicit)
As a Qur’an Reader, I should see minimalist Islamic geometric accents so that the app feels respectful.
- Trigger/input: Open Home.
- Observable result: A single hairline eight-point star drawn as a 1px stroke used only as a section divider, never tiled.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Accents persist.
Page 20 of 45
Settings Screen
FR-113 — Font selection (explicit)
As a Qur’an Reader, I should select a font in Settings so that I can read comfortably.
- Trigger/input: Select a font in Settings.
- Observable result: The font is applied.
- Access state: No account required.
- Failure/recovery: Font fallback to bundled Naskh face.
- Continuation: Selection persists.
FR-114 — Theme selection (explicit)
As a Qur’an Reader, I should select a theme in Settings so that I can read in my preferred mode.
- Trigger/input: Select a theme in Settings.
- Observable result: The theme is applied.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Selection persists.
FR-115 — Audio quality (explicit)
As a Recitation Listener, I should select audio quality in Settings so that I can balance quality and data.
- Trigger/input: Select audio quality in Settings.
- Observable result: The audio quality is applied.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Selection persists.
FR-116 — Download management (explicit)
As a Recitation Listener, I should manage downloads in Settings so that I can control offline storage.
- Trigger/input: Open download management in Settings.
- Observable result: Downloads are listed with state and size.
- Access state: No account required.
- Failure/recovery: Removal failure shows inline notice with retry.
- Continuation: Download state persists.
FR-117 — Translation preferences (explicit)
As a Tafsir & Translation Student, I should set translation preferences in Settings so that my preferred translation is used.
- Trigger/input: Set translation preferences in Settings.
- Observable result: The preferred translation is applied.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Preferences persist.
FR-118 — Tafsir preferences (explicit)
As a Tafsir & Translation Student, I should set tafsir preferences in Settings so that my preferred tafsir is used.
- Trigger/input: Set tafsir preferences in Settings.
- Observable result: The preferred tafsir is applied.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Preferences persist.
FR-119 — Reminder settings (explicit)
As an Adhkar Practitioner, I should set reminder settings in Settings so that I can control my reminders.
- Trigger/input: Set reminder settings in Settings.
- Observable result: Reminders are configured.
- Access state: No account required.
- Failure/recovery: Scheduling failure shows inline notice with retry.
- Continuation: Settings persist.
FR-120 — Cache cleanup (explicit)
As a Qur’an Reader, I should clean cache in Settings so that I can manage storage.
- Trigger/input: Select cache cleanup in Settings.
- Observable result: Cache is cleared.
- Access state: No account required.
- Failure/recovery: Cleanup failure shows inline notice with retry.
- Continuation: Cache state persists.
FR-121 — Accessibility settings (explicit)
As a Qur’an Reader, I should set accessibility settings in Settings so that I can read comfortably.
- Trigger/input: Set accessibility settings in Settings.
- Observable result: Accessibility settings are applied.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Settings persist.
Page 21 of 45
Notifications & Reminders
FR-122 — Daily verse reminder (explicit)
As a Qur’an Reader, I should receive a daily verse reminder so that I remember to read.
- Trigger/input: Enable the daily verse reminder in Reminders.
- Observable result: A local notification is scheduled.
- Access state: No account required; no cloud dependency.
- Failure/recovery: Scheduling failure shows inline notice with retry.
- Continuation: Reminder persists.
FR-123 — Morning adhkar reminder (explicit)
As an Adhkar Practitioner, I should receive a morning adhkar reminder so that I remember my morning remembrance.
- Trigger/input: Enable the morning adhkar reminder in Reminders.
- Observable result: A local notification is scheduled.
- Access state: No account required; no cloud dependency.
- Failure/recovery: Scheduling failure shows inline notice with retry.
- Continuation: Reminder persists.
FR-124 — Evening adhkar reminder (explicit)
As an Adhkar Practitioner, I should receive an evening adhkar reminder so that I remember my evening remembrance.
- Trigger/input: Enable the evening adhkar reminder in Reminders.
- Observable result: A local notification is scheduled.
- Access state: No account required; no cloud dependency.
- Failure/recovery: Scheduling failure shows inline notice with retry.
- Continuation: Reminder persists.
FR-125 — Optional reading goals (explicit)
As a Qur’an Reader, I should set optional reading goals so that I can track my reading.
- Trigger/input: Set a reading goal in Reminders.
- Observable result: The goal is saved and progress is tracked locally.
- Access state: No account required; stored locally.
- Failure/recovery: Storage failure shows inline notice with retry.
- Continuation: Goal persists.
FR-126 — Respectful, non-intrusive, locally scheduled, no cloud dependency (explicit)
As a Qur’an Reader, I should receive respectful, non-intrusive reminders so that I am not disturbed.
- Trigger/input: Receive a reminder.
- Observable result: The reminder is respectful and non-intrusive.
- Access state: No account required; no cloud dependency.
- Failure/recovery: Not applicable.
- Continuation: Reminders remain respectful.
Page 22 of 45
Performance Requirements
FR-127 — Start fast (explicit)
As a Qur’an Reader, I should have the app start fast so that I can begin reading quickly.
- Trigger/input: Launch the app.
- Observable result: The app starts quickly.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Fast start persists.
FR-128 — Scroll smoothly (explicit)
As a Qur’an Reader, I should have smooth scrolling so that reading is comfortable.
- Trigger/input: Scroll through content.
- Observable result: Scrolling is smooth.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Smooth scrolling persists.
FR-129 — Work on low-end Android devices (explicit)
As a Qur’an Reader, I should have the app work on low-end devices so that I can use it on any phone.
- Trigger/input: Use the app on a low-end device.
- Observable result: The app works on low-end devices.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Low-end support persists.
FR-130 — Cache intelligently (explicit)
As a Qur’an Reader, I should have the app cache intelligently so that content is available offline.
- Trigger/input: Use the app.
- Observable result: Content is cached intelligently.
- Access state: No account required.
- Failure/recovery: Cache miss falls back to network.
- Continuation: Cache persists.
FR-131 — Avoid memory leaks (explicit)
As a Qur’an Reader, I should have the app avoid memory leaks so that it remains stable.
- Trigger/input: Use the app.
- Observable result: No memory leaks occur.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Stability persists.
FR-132 — Use lazy loading (explicit)
As a Qur’an Reader, I should have the app use lazy loading so that content loads efficiently.
- Trigger/input: Scroll through content.
- Observable result: Content loads lazily.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Lazy loading persists.
FR-133 — Support offline reading (explicit)
As a Qur’an Reader, I should read offline so that I can read anywhere.
- Trigger/input: Open content without network.
- Observable result: Cached content is shown.
- Access state: No account required.
- Failure/recovery: If no cache exists, a respectful error frame with retry is shown.
- Continuation: Offline reading persists.
Page 23 of 45
Accessibility Requirements
FR-134 — Dynamic text scaling (explicit)
As a Qur’an Reader, I should have dynamic text scaling so that I can read at my preferred size.
- Trigger/input: Change system text size.
- Observable result: Text scales accordingly.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Scaling persists.
FR-135 — TalkBack (explicit)
As a Qur’an Reader, I should have TalkBack support so that I can use the app with screen reader.
- Trigger/input: Enable TalkBack.
- Observable result: All controls are accessible.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: TalkBack support persists.
FR-136 — High contrast themes (explicit)
As a Qur’an Reader, I should have high contrast themes so that I can read comfortably.
- Trigger/input: Enable high contrast theme.
- Observable result: High contrast theme is applied.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Theme persists.
FR-137 — Large tap targets (explicit)
As a Qur’an Reader, I should have large tap targets so that I can interact easily.
- Trigger/input: Interact with controls.
- Observable result: Tap targets are large.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Large tap targets persist.
FR-138 — RTL perfection (explicit)
As a Qur’an Reader, I should have perfect RTL layout so that reading direction is correct.
- Trigger/input: Open any screen.
- Observable result: RTL layout is perfect.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: RTL persists.
FR-139 — Reduced motion mode (explicit)
As a Qur’an Reader, I should have reduced motion mode so that I can avoid motion.
- Trigger/input: Enable reduced motion mode.
- Observable result: Animations are removed, leaving instant state changes.
- Access state: No account required.
- Failure/recovery: Not applicable.
- Continuation: Mode persists.
Page 24 of 45
Deliverables
FR-140 — Full Android project structure (explicit)
As a developer, I should have a full Android project structure so that the project is organized.
- Trigger/input: Build the project.
- Observable result: The project structure is complete.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Structure persists.
FR-141 — Package organization (explicit)
As a developer, I should have package organization so that the codebase is maintainable.
- Trigger/input: Build the project.
- Observable result: Packages are organized.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Organization persists.
FR-142 — Gradle setup (explicit)
As a developer, I should have Gradle setup so that the project builds.
- Trigger/input: Build the project.
- Observable result: Gradle is configured.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Gradle setup persists.
FR-143 — API layer (explicit)
As a developer, I should have an API layer so that API calls are organized.
- Trigger/input: Build the project.
- Observable result: The API layer exists.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: API layer persists.
FR-144 — Repository examples (explicit)
As a developer, I should have repository examples so that data access is clear.
- Trigger/input: Build the project.
- Observable result: Repository examples exist.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Examples persist.
FR-145 — Compose UI examples (explicit)
As a developer, I should have Compose UI examples so that UI patterns are clear.
- Trigger/input: Build the project.
- Observable result: Compose UI examples exist.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Examples persist.
FR-146 — Navigation graph (explicit)
As a developer, I should have a navigation graph so that navigation is organized.
- Trigger/input: Build the project.
- Observable result: The navigation graph exists.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Navigation graph persists.
FR-147 — Room schemas (explicit)
As a developer, I should have Room schemas so that local data is structured.
- Trigger/input: Build the project.
- Observable result: Room schemas exist.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Schemas persist.
FR-148 — Media playback service (explicit)
As a developer, I should have a media playback service so that playback is reliable.
- Trigger/input: Build the project.
- Observable result: The media playback service exists.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Service persists.
FR-149 — State management approach (explicit)
As a developer, I should have a state management approach so that state is organized.
- Trigger/input: Build the project.
- Observable result: The state management approach exists.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Approach persists.
FR-150 — Design system tokens (explicit)
As a developer, I should have design system tokens so that design is consistent.
- Trigger/input: Build the project.
- Observable result: Design system tokens exist.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Tokens persist.
FR-151 — Example screens (explicit)
As a developer, I should have example screens so that UI patterns are clear.
- Trigger/input: Build the project.
- Observable result: Example screens exist.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Examples persist.
FR-152 — Testing strategy (explicit)
As a developer, I should have a testing strategy so that quality is ensured.
- Trigger/input: Build the project.
- Observable result: The testing strategy exists.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Strategy persists.
FR-153 — CI/CD recommendation (explicit)
As a developer, I should have a CI/CD recommendation so that delivery is automated.
- Trigger/input: Build the project.
- Observable result: The CI/CD recommendation exists.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Recommendation persists.
FR-154 — Play Store release checklist (explicit)
As a developer, I should have a Play Store release checklist so that release is smooth.
- Trigger/input: Build the project.
- Observable result: The Play Store release checklist exists.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Checklist persists.
FR-155 — Security checklist (explicit)
As a developer, I should have a security checklist so that security is ensured.
- Trigger/input: Build the project.
- Observable result: The security checklist exists.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Checklist persists.
FR-156 — Future scalability roadmap (explicit)
As a developer, I should have a future scalability roadmap so that the project can grow.
- Trigger/input: Build the project.
- Observable result: The future scalability roadmap exists.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Roadmap persists.
Page 25 of 45
Code Quality Requirements
FR-157 — Production-grade code (explicit)
As a developer, I should write production-grade code so that the app is reliable.
- Trigger/input: Write code.
- Observable result: Code is production-grade.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Quality persists.
FR-158 — Kotlin best practices (explicit)
As a developer, I should follow Kotlin best practices so that the codebase is clean.
- Trigger/input: Write code.
- Observable result: Kotlin best practices are followed.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Practices persist.
FR-159 — Meaningful Arabic-friendly naming where suitable (explicit)
As a developer, I should use meaningful Arabic-friendly naming where suitable so that the codebase is readable.
- Trigger/input: Write code.
- Observable result: Naming is meaningful and Arabic-friendly where suitable.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Naming persists.
FR-160 — Modular and maintainable (explicit)
As a developer, I should write modular and maintainable code so that the codebase is scalable.
- Trigger/input: Write code.
- Observable result: Code is modular and maintainable.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Modularity persists.
FR-161 — Comments for complex logic (explicit)
As a developer, I should comment complex logic so that the codebase is understandable.
- Trigger/input: Write code.
- Observable result: Complex logic is commented.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Comments persist.
FR-162 — Avoid deprecated Android APIs (explicit)
As a developer, I should avoid deprecated Android APIs so that the app is future-proof.
- Trigger/input: Write code.
- Observable result: No deprecated Android APIs are used.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Modern APIs persist.
FR-163 — Follow latest Android official guidance (explicit)
As a developer, I should follow latest Android official guidance so that the app is modern.
- Trigger/input: Write code.
- Observable result: Latest Android official guidance is followed.
- Access state: Not applicable.
- Failure/recovery: Not applicable.
- Continuation: Guidance persists.
Page 26 of 45
Required Inference
FR-164 — Local device storage (required_inference)
As a Qur’an Reader, I should have my reading position, bookmarks, favorites, adhkar counts, preferences, and cached content stored locally so that my state persists across sessions.
- Trigger/input: Use the app.
- Observable result: State is stored locally.
- Access state: No account required.
- Failure/recovery: Storage failure shows inline notice with retry.
- Continuation: State persists.
FR-165 — Quran.com API access and trusted-content validation (required_inference)
As a developer, I should access the Quran.com API and validate trusted content so that Qur’an content is accurate.
- Trigger/input: Fetch content.
- Observable result: Content is validated against the trusted source.
- Access state: Content APIs use
client_credentials grant with x-auth-token and x-client-id headers.
- Failure/recovery: Validation failure falls back to cached content and shows an inline notice.
- Continuation: Validation persists.
FR-166 — Offline caches and downloaded resources (required_inference)
As a Qur’an Reader, I should have offline caches and downloaded resources so that reading, adhkar, and optionally audio work without cloud dependency.
- Trigger/input: Use the app offline.
- Observable result: Cached and downloaded content is available.
- Access state: No account required.
- Failure/recovery: If no cache exists, a respectful error frame with retry is shown.
- Continuation: Offline use persists.
FR-167 — Local scheduling for reminders (required_inference)
As an Adhkar Practitioner, I should have local scheduling for daily verse, morning adhkar, and evening adhkar reminders so that reminders work without cloud dependency.
- Trigger/input: Enable reminders.
- Observable result: Reminders are scheduled locally.
- Access state: No account required.
- Failure/recovery: Scheduling failure shows inline notice with retry.
- Continuation: Reminders persist.
FR-168 — Media playback service support (required_inference)
As a Recitation Listener, I should have media playback service support so that background recitation and lock-screen controls work when enabled.
- Trigger/input: Start playback and leave the app.
- Observable result: Playback continues via the foreground media playback service.
- Access state: No account required;
FOREGROUND_SERVICE_MEDIA_PLAYBACK used if needed.
- Failure/recovery: If the service is interrupted, playback pauses and can be resumed.
- Continuation: Playback resumes from the last position.
Page 27 of 45
4. User Personas
Qur’an Reader
A regular Muslim user who reads the Holy Qur’an daily in Arabic. They browse by Surah, Juz, Hizb, or Page and use Mushaf page-style or verse-by-verse reading with adjustable fonts, line spacing, and focus mode. They bookmark verses, keep favorites, resume via Continue Reading, and switch between night, sepia, and paper Mushaf modes.
- Product context: Opens the app in quiet moments — before Fajr, after Maghrib, in the last minutes before sleep. Values calm, accuracy, and respect.
- Primary goal: A calm, distraction-free, accurate reading session that resumes where they left off.
- Distinct accepted responsibilities: Browsing by Surah/Juz/Hizb/Page; Mushaf and verse-by-verse reading; bookmarking; favorites; Continue Reading; daily verse reflection; search in Arabic text; Tajweed-aware rendering if available; display modes; typography settings; focus mode.
- Relevant inputs or decisions: Which surah/juz/hizb/page to read; which display mode; which font and size; whether to bookmark or favorite; whether to search.
- Interactions with other accepted participants: Shares the reader with the Recitation Listener (highlighting during playback) and the Tafsir & Translation Student (tafsir bottom sheet, translations). Shares Favorites and Reminders with the Adhkar Practitioner.
- Observable success: Reading position resumes correctly; bookmarks and favorites persist; typography and display mode persist; search returns accurate results.
Recitation Listener
A user who streams or downloads recitations from the ten named reciters, uses background playback with lock screen controls, sleep timer, repeat verse or range, and auto-next surah, and follows verse-synchronized highlighting. They also play translation audio in sync with the Arabic text.
- Product context: Listens during commutes, chores, or before sleep. Values uninterrupted, correctly synchronized listening.
- Primary goal: Uninterrupted, correctly synchronized listening that continues offline when cached.
- Distinct accepted responsibilities: Selecting from the ten named reciters; streaming; optional offline download caching; background playback; lock screen controls; sleep timer; repeat verse mode; repeat range mode; auto-next surah; translation audio playback; verse-synchronized highlighting.
- Relevant inputs or decisions: Which reciter; whether to stream or download; whether to enable repeat, sleep timer, or auto-next; whether to enable translation audio.
- Interactions with other accepted participants: Shares the reader with the Qur’an Reader (highlighting); shares the Audio Player with the Tafsir & Translation Student (translation audio).
- Observable success: Playback continues in background; lock screen controls work; sleep timer stops playback; repeat modes work; auto-next surah works; highlighting stays synchronized; offline playback works for cached recitations.
Page 28 of 45
Tafsir & Translation Student
A user who studies meaning by switching translations instantly, reading in parallel mode, and opening verse tafsir in a bottom sheet across Tafsir Ibn Kathir, Al-Saadi, Al-Jalalayn, and Saheeh International, with additional downloadable translations. They search Arabic text, translations, and tafsir to locate verses.
- Product context: Studies in focused sessions, often comparing multiple sources for a single verse. Values trusted references and the ability to compare without losing position.
- Primary goal: Finding and comparing trusted explanations for a verse without losing their reading position.
- Distinct accepted responsibilities: Selecting translations; instant switching; parallel reading mode; verse tafsir bottom sheet; reading Tafsir Ibn Kathir, Al-Saadi, Al-Jalalayn, and Saheeh International; downloading additional translations; searching Arabic text, translations, and tafsir.
- Relevant inputs or decisions: Which translation; which tafsir; whether to read in parallel; which search scope; which result to open.
- Interactions with other accepted participants: Shares the reader with the Qur’an Reader; shares the Audio Player with the Recitation Listener (translation audio).
- Observable success: Translations switch instantly without losing position; parallel mode works; tafsir bottom sheet opens and closes without losing position; search returns accurate results across all three scopes.
Adhkar Practitioner
A user who performs daily remembrance using the dedicated الأذكار section covering morning, evening, sleep, prayer, waking, and travel adhkar plus an electronic tasbih. They track counts, mark favorites, and rely on locally scheduled daily reminders with offline storage.
- Product context: Performs remembrance at fixed times of day. Values accurate counts, gentle prompts, and offline availability.
- Primary goal: Completing each adhkar set with accurate counts and gentle, non-intrusive prompts.
- Distinct accepted responsibilities: Reading the six adhkar categories; using the electronic tasbih; tracking counts; marking favorites; receiving daily reminders; using adhkar offline.
- Relevant inputs or decisions: Which adhkar category; when to increment counts; which items to favorite; which reminders to enable.
- Interactions with other accepted participants: Shares Favorites and Reminders with the Qur’an Reader.
- Observable success: Counts persist accurately; favorites persist; reminders arrive respectfully and non-intrusively; adhkar work offline.
5. Core User Flows
Page 29 of 45
Flow 1 — Qur’an Reader: Daily reading session
- The Qur’an Reader opens the app and lands on Landing, which shows the app name نور الذكر in Amiri with a 1px brass hairline beneath it and a single full-width rectangle in deep mosque green with the word «اقرأ».
- The reader taps «اقرأ» and arrives at Home, which shows the Continue Reading block with the last surah name and ayah number in Arabic-Indic numerals.
- The reader taps the Continue Reading block, which opens Quran Reader at the saved position.
- The reader reads in Mushaf mode or verse-by-verse mode, scrolling through the page. The wayfinding rail on the right edge shows juz/hizb tick marks and a small moving dot for the current verse.
- The reader taps a verse to select it and chooses to bookmark it. The verse is saved and appears in Favorites.
- The reader taps the verse again and opens the tafsir bottom sheet, reading the tafsir for that verse, then closes the sheet and returns to the same position.
- The reader opens Reading Settings and adjusts font size and line spacing, then selects paper Mushaf mode. The changes apply immediately.
- The reader continues reading. The reading position is saved locally.
- Failure/recovery: If content cannot be fetched, the cached page is shown with a quiet inline notice and retry. If no cache exists, a respectful error frame with retry is shown.
- Continuation: The reader returns to Home, where the Continue Reading block now shows the updated position.
Flow 2 — Qur’an Reader: Browse by Juz
- The Qur’an Reader opens Quran Browse from the bottom navigation bar.
- The reader selects the Juz mode. A list of juz with Arabic-Indic juz markers is shown.
- The reader selects a juz, which opens Quran Reader at the start of that juz.
- The reader reads and bookmarks a verse.
- Failure/recovery: If the juz list cannot be fetched, the cached list is shown with an inline notice and retry.
- Continuation: The reader returns to Quran Browse and selects another juz.
Page 30 of 45
Flow 3 — Qur’an Reader: Search for a verse
- The Qur’an Reader opens Search from the bottom navigation bar.
- The reader enters a query and selects the Arabic Qur’an text scope.
- Matching verses are listed with references.
- The reader selects a result, which opens Quran Reader at that verse.
- Failure/recovery: If search fails, an inline notice with retry is shown.
- Continuation: The reader returns to Search and refines the query.
Flow 4 — Recitation Listener: Stream a recitation
- The Recitation Listener opens Recitations from the bottom navigation bar.
- The reader selects one of the ten named reciters: مشاري راشد العفاسي، عبد الباسط عبد الصمد، ماهر المعيقلي، السديس، سعد الغامدي، ياسر الدوسري، فارس عباد، أحمد العجمي، المنشاوي، الحذيفي.
- The listener starts streaming. The Audio Player opens and playback begins.
- The currently-reciting verse is marked by a 1px brass underline that fades in over 400ms and holds.
- The listener leaves the app. Playback continues via the foreground media playback service, and lock screen controls are available.
- The listener sets a sleep timer. Playback stops after the chosen duration.
- Failure/recovery: If the stream fails, an inline notice with retry and offline fallback is shown.
- Continuation: The listener returns to Home, where the last played recitation is shown and can be resumed.
Flow 5 — Recitation Listener: Download a recitation for offline use
- The Recitation Listener opens Recitations.
- The listener selects a reciter and selects download for a recitation.
- The recitation is cached locally and available offline.
- The listener opens Settings and opens download management, where the download is listed with state and size.
- Failure/recovery: If the download fails, an inline notice with retry is shown.
- Continuation: The listener plays the downloaded recitation offline.
Page 31 of 45
Flow 6 — Recitation Listener: Repeat a verse for memorization
- The Recitation Listener opens the Audio Player during playback.
- The listener enables repeat verse mode. The current verse repeats.
- The listener enables repeat range mode and selects a range. The selected range repeats.
- The listener enables auto-next surah. Playback continues to the next surah when the current one ends.
- Failure/recovery: If the next surah cannot be loaded, playback pauses with an inline notice.
- Continuation: The listener disables repeat and continues listening.
Flow 7 — Recitation Listener: Translation audio synchronization
- The Recitation Listener opens the Audio Player during playback.
- The listener enables translation audio playback.
- Translation audio plays in sync with the Arabic recitation and the verse highlight.
- Failure/recovery: If translation audio is unavailable, an inline notice is shown and Arabic-only playback continues.
- Continuation: Synchronization continues across verses.
Flow 8 — Tafsir & Translation Student: Study a verse
- The Tafsir & Translation Student opens Quran Reader at a verse.
- The student taps the verse and opens the tafsir bottom sheet, reading Tafsir Ibn Kathir.
- The student switches to Tafsir Al-Saadi, then Tafsir Al-Jalalayn, comparing explanations.
- The student closes the sheet and opens Translations, selecting Saheeh International.
- The student toggles parallel reading mode and reads the Arabic text and English translation side by side.
- The student switches translations instantly without losing position.
- Failure/recovery: If a translation or tafsir cannot be fetched, the cached version is shown with an inline notice and retry.
- Continuation: The student returns to Quran Reader at the same position.
Page 32 of 45
Flow 9 — Tafsir & Translation Student: Search tafsir
- The Tafsir & Translation Student opens Search.
- The student enters a query and selects the tafsir scope.
- Matching tafsir passages are listed with verse references.
- The student selects a result, which opens Quran Reader at that verse.
- Failure/recovery: If search fails, an inline notice with retry is shown.
- Continuation: The student opens the tafsir bottom sheet for the verse.
Flow 10 — Tafsir & Translation Student: Download an additional translation
- The Tafsir & Translation Student opens Translations.
- The student selects a downloadable translation.
- The translation is downloaded and available offline.
- Failure/recovery: If the download fails, an inline notice with retry is shown.
- Continuation: The student selects the downloaded translation and reads it.
Flow 11 — Adhkar Practitioner: Morning adhkar
- The Adhkar Practitioner opens Home and taps the أذكار الصباح tile, or opens الأذكار from the bottom navigation bar and selects أذكار الصباح.
- Morning adhkar panels are rendered as square-cornered ruled panels with a right-aligned count ring drawn in a single 1px brass stroke.
- The practitioner taps anywhere on a panel to increment the count. The count increments with a 180ms Arabic-Indic numeral swap and a 1px ring progress stroke that draws forward.
- The practitioner marks an adhkar item as favorite. The item appears in Favorites.
- Failure/recovery: If local storage write fails, an inline notice is shown and the action can be retried.
- Continuation: The practitioner completes the set and returns to الأذكار.
Page 33 of 45
Flow 12 — Adhkar Practitioner: Electronic tasbih
- The Adhkar Practitioner opens الأذكار and selects تسبيح إلكتروني.
- A tasbih counter is shown with a 1px brass count ring and Arabic-Indic numerals at display scale (72/96/120).
- The practitioner taps to increment the count. The count increments with a 180ms Arabic-Indic numeral swap.
- Failure/recovery: Not applicable — offline storage.
- Continuation: The count persists across sessions.
Flow 13 — Adhkar Practitioner: Set daily reminders
- The Adhkar Practitioner opens Reminders from the bottom navigation bar.
- The practitioner enables the morning adhkar reminder and sets a time.
- The practitioner enables the evening adhkar reminder and sets a time.
- The practitioner enables the daily verse reminder and sets a time.
- The practitioner sets an optional reading goal.
- Reminders are scheduled locally with no cloud dependency.
- Failure/recovery: If scheduling fails, an inline notice with retry is shown.
- Continuation: The practitioner receives reminders respectfully and non-intrusively.
Flow 14 — Adhkar Practitioner: Offline adhkar
- The Adhkar Practitioner opens الأذكار without network.
- Adhkar content and counts are available offline.
- The practitioner completes the set and counts persist.
- Failure/recovery: Not applicable — content is bundled.
- Continuation: Offline use persists.
Page 34 of 45
Flow 15 — Qur’an Reader: Set a reading goal
- The Qur’an Reader opens Reminders.
- The reader sets an optional reading goal.
- The goal is saved and progress is tracked locally.
- Failure/recovery: If storage fails, an inline notice with retry is shown.
- Continuation: The goal persists and progress is visible.
Flow 16 — Qur’an Reader: Change display mode
- The Qur’an Reader opens Reading Settings.
- The reader selects night mode. The display switches to warm graphite ground
#141413 with paper-white type #EDE8DE and brass accent.
- The reader selects sepia mode. The display switches to
#F1E4CE ground with #2E2A24 ink.
- The reader selects paper Mushaf mode. The display switches to
#FBF6EA with a faint ruled baseline grid.
- The reader toggles focus mode. Distracting elements are hidden.
- Failure/recovery: Not applicable.
- Continuation: The selected mode persists across sessions.
Flow 17 — Qur’an Reader: Manage cache
- The Qur’an Reader opens Settings.
- The reader selects cache cleanup.
- The cache is cleared.
- Failure/recovery: If cleanup fails, an inline notice with retry is shown.
- Continuation: The reader continues reading; content is re-fetched as needed.
Page 35 of 45
6. Visuals Colors and Theme
The creative direction is Emptiness as devotion — the page breathes before it speaks, with Kenya Hara as the muse. The headline is: the interface should recede until only the sacred text and the act of remembrance remain. Hara’s “white” is not a colour but a discipline — it makes the page itself an act of respect, and it makes large Arabic script (Uthmani and IndoPak) the only ornament the screen ever needs.
Page 36 of 45
Colour Tokens
Light mode
- Background:
#F7F4EE (paper-white ground)
- Surface:
#FCFAF6 (cards, with a single hairline #E3DED3 border and no shadow)
- Text:
#23211E (charcoal ink for Qur’an and body)
- Primary:
#3E4A3D (deep muted mosque green — used only for the active state, the reading progress hairline, and the reciter’s name when playing)
- Accent:
#A87B3F (unbleached brass/wood tone — reserved for one thing per screen: the current-verse marker, the tasbih count ring, the bookmark filled state)
- Muted:
#8A857B (metadata, surah numbers, timestamps)
- Hairline:
#E3DED3
Night mode
- Background:
#141413 (warm graphite ground — never pure black)
- Text:
#EDE8DE (paper-white type — never pure white)
- Accent:
#A87B3F (same brass accent)
Sepia mode
- Background:
#F1E4CE
- Text:
#2E2A24
Paper Mushaf mode
- Background:
#FBF6EA
- Faint ruled baseline grid
Page 37 of 45
Typography
- Headings: Amiri — a Naskh revival with real calligraphic contrast, set at light-to-regular weight with wide letter-spacing on Latin transliterations and generous line-height (1.9–2.1) so the Arabic never crowds itself.
- Body: Noto Naskh Arabic for interface body and adhkar text.
- Numerals: Arabic-Indic (٠١٢٣) in Amiri for surah numbers, juz markers, and tasbih counts; Latin numerals in Noto Naskh for timestamps and download sizes.
- No uppercase, no all-caps labels — Arabic has no case, and the Latin micro-labels are set in small size with tracking instead.
- Type scale (1.25 modular): Qur’an verse text 34px mobile / 44px tablet / 52px desktop-reading; surah title 40/52/64; section eyebrow 13/14/15 with 0.12em tracking; body 17/18/19; metadata 14/14/15; tasbih count 72/96/120.
- Line-height: Qur’an 2.0; body 1.7.
Shape Language
- Square and near-square proportions throughout — cards are 4px-radius rectangles, never pills.
- Rules are 1px hairlines in
#E3DED3.
- The single ornamental gesture is a hairline mihrab arch (a pointed ogee drawn as a 1px stroke) used as the top edge of the daily-verse card and as the empty-state frame.
- Buttons are rectangles with 2px radius, full-width, text-centred, with a 1px border; the primary action is the only filled element on a screen.
- Icons are 1.5px-stroke line pictograms, no fills except the active state.
Layout
- RTL-first, single-column, centred reading measure of 34em max with margins that grow with the viewport (24px at 375, 64px at 768, 120px at 1280).
- A persistent 1px vertical hairline runs down the right edge of the reading column, carrying the juz/hizb tick marks — a quiet wayfinding rail that doubles as a scroll position indicator.
- Home is a vertical rhythm of breathing blocks: continue-reading (one line, large), daily verse (mihrab-arched card), quick adhkar row (six square tiles, no radius), recently opened (a plain ruled list, not cards).
- Navigation is a bottom bar of five 1.5px-stroke pictograms with Arabic labels beneath — no labels on the icons alone, no badges, no floating action button.
- Settings is a ruled list of label/value pairs, right-aligned values, hairline dividers.
Page 38 of 45
Imagery
- No photography of people, no stock imagery, no 3D.
- The visual vocabulary is paper and light: unbleached paper texture at 3% opacity on the ground, a single soft directional shadow under the daily-verse card (blur 24, y-offset 2, 4% black), faint ruled baselines in Mushaf mode, and one hairline Islamic geometric motif — an eight-point star drawn as a 1px stroke — used only as a section divider, never tiled.
- Surah headers in Mushaf mode use the traditional ornamental frame drawn in the same 1px brass stroke.
- App icon is a single brass eight-point star on paper-white.
Avoid
- Blue, indigo, violet or teal as a primary or accent colour — the palette is paper, ink, mosque green and brass only.
- Gradients of any kind, including gradient-blob heroes, glowing edges, glassmorphism or frosted panels.
- Cards with hover-lift shadows, rounded-pill buttons, floating action buttons or badge counters.
- Tiled Islamic geometric wallpaper or repeated arabesque patterns as background texture.
- Rounded modern sans-serif Arabic faces (Cairo, Tajawal, Almarai) for display type — the Arabic voice is Naskh, not geometric sans.
- Any animation that pulses, bounces, glows or draws attention to itself; motion is a fade, a fold, or a single number swap.
- Uppercase Latin labels, all-caps micro-copy, or Latin numerals in places where Arabic-Indic numerals belong.
- Photography of people, stock mosque imagery, sunset/dune stock photos, or any 3D render.
Page 39 of 45
7. Signature Design Concept
The Breathing Page — the public entry (Landing) opens on emptiness. The top 40% of the viewport is paper-white #F7F4EE with nothing on it but a single centred line of Amiri Arabic — the app’s name نور الذكر — set at 44px mobile to 72px desktop, in charcoal ink #23211E, with a 1px brass hairline #A87B3F beneath it that spans exactly the width of the text.
Below, the continue-reading block appears as one oversized Arabic line (surah name + ayah number in Arabic-Indic numerals) at 40/52/64px, flush right, with a small brass «متابعة» label above it in 13px tracked Amiri. The rest of the screen is a slow vertical descent of ruled, breathing blocks separated by 1px hairlines — no cards float, no shadows lift, no gradients, no coloured buttons. The only filled element on the entire first screen is a single full-width rectangle in deep mosque green #3E4A3D with the word «اقرأ» centred in paper-white — one button, one colour, one action.
The signature moves that carry the concept across the app:
- A hairline wayfinding rail down the right edge of every reading screen, with 1px brass ticks marking juz and hizb boundaries and a small moving dot for the current verse — the scroll position becomes a piece of navigation, not a progress bar.
- The daily-verse card is crowned by a hairline mihrab arch (a 1px ogee stroke) instead of a rounded top edge; the arch is the only ornamental curve in the entire app.
- Arabic-Indic numerals set in Amiri at display scale everywhere a number matters — surah numbers, juz markers, tasbih count, ayah numbers in the reading view — so the numerals themselves carry the app’s voice.
- The currently-reciting verse is marked only by a 1px brass underline that fades in and holds; no background highlight, no glow, no bouncing — recitation is indicated by a line, not a colour.
- Adhkar cards are square-cornered ruled panels with a right-aligned count ring drawn in a single 1px brass stroke; tapping anywhere on the panel increments the count with a 180ms Arabic-Indic numeral swap, not a button press.
8. Interaction Model & Motion Direction
Interaction Model: Static (direction)
Motion Tempo: still
Hero Dimensionality: flat
Page 40 of 45
Landing Hero Motion Brief
- Focal subject: The app name نور الذكر in Amiri Arabic, centred on paper-white, with a 1px brass hairline beneath it spanning exactly the width of the text.
- Input → transformation → outcome thesis: On first paint, the wordmark and its hairline are already present — nothing animates in. When the user taps «اقرأ», the Landing crossfades (220ms) to Home. The transformation is the removal of emptiness: the page that breathed becomes the page that speaks. No other motion is used.
- Motion vocabulary: 220ms crossfades with no slide; a 400ms fade-in for the verse highlight; a 180ms number swap for tasbih counts; a 300ms horizontal paper-fold crossfade for Mushaf page turns; a hairline that extends and retracts for pull-to-refresh.
- Composed first frame: Paper-white ground
#F7F4EE; centred Amiri wordmark نور الذكر at 44px mobile to 72px desktop in charcoal ink #23211E; 1px brass hairline #A87B3F beneath it spanning exactly the width of the text; below, the continue-reading block as one oversized Arabic line flush right with a small brass «متابعة» label above it; a single full-width rectangle in deep mosque green #3E4A3D with «اقرأ» centred in paper-white.
- Reduced-motion state: Reduced-motion mode removes the fold and the fades, leaving instant state changes. The first frame is identical; only the transitions become instant.
Page 41 of 45
9. Non-Functional Requirements
NFR-1 — No ads (explicit)
The app must have no ads. Rationale: explicit hard constraint; the reading experience must be undisturbed.
NFR-2 — No in-app purchases (explicit)
The app must have no in-app purchases. Rationale: explicit hard constraint; the app must remain free of commerce.
NFR-3 — No tracking (explicit)
The app must have no tracking. Rationale: explicit hard constraint; user privacy is paramount.
NFR-4 — No analytics SDKs and no tracking SDKs (explicit)
The app must include no analytics SDKs and no tracking SDKs. Rationale: explicit hard constraint.
NFR-5 — No user data collection (explicit)
The app must collect no user data. Rationale: explicit hard constraint.
NFR-6 — No camera permission (explicit)
The app must require no camera permission. Rationale: explicit hard constraint.
NFR-7 — No microphone permission (explicit)
The app must require no microphone permission. Rationale: explicit hard constraint.
NFR-8 — No location permission (explicit)
The app must require no location permission. Rationale: explicit hard constraint.
NFR-9 — No contacts permission (explicit)
The app must require no contacts permission. Rationale: explicit hard constraint.
NFR-10 — No unnecessary storage permission (explicit)
The app must require no unnecessary storage permission. Rationale: explicit hard constraint.
NFR-11 — Only INTERNET and FOREGROUND_SERVICE_MEDIA_PLAYBACK if needed (explicit)
The app must only use INTERNET and FOREGROUND_SERVICE_MEDIA_PLAYBACK if needed. Rationale: explicit hard constraint.
NFR-12 — Arabic-first UX (explicit)
The app must be Arabic-first. Rationale: explicit hard constraint.
NFR-13 — Respectful Islamic design (explicit)
The app must use respectful Islamic design. Rationale: explicit hard constraint.
NFR-14 — Accurate Qur’an text only from trusted sources (explicit)
The app must use accurate Qur’an text only from trusted sources. Rationale: explicit hard constraint; the Quran.com API is the primary trusted source.
NFR-15 — Maintain high performance on mid-range Android phones (explicit)
The app must maintain high performance on mid-range Android phones. Rationale: explicit hard constraint.
NFR-16 — Fully scalable architecture (explicit)
The app must have a fully scalable architecture. Rationale: explicit hard constraint.
NFR-17 — Clean and maintainable codebase (explicit)
The app must have a clean and maintainable codebase. Rationale: explicit hard constraint.
NFR-18 — Reminders must be respectful, non-intrusive, locally scheduled, and have no cloud dependency (explicit)
Reminders must be respectful, non-intrusive, locally scheduled, and have no cloud dependency. Rationale: explicit hard constraint.
NFR-19 — Start fast (explicit)
The app must start fast. Rationale: explicit performance requirement.
NFR-20 — Scroll smoothly (explicit)
The app must scroll smoothly. Rationale: explicit performance requirement.
NFR-21 — Work on low-end Android devices (explicit)
The app must work on low-end Android devices. Rationale: explicit performance requirement.
NFR-22 — Cache intelligently (explicit)
The app must cache intelligently. Rationale: explicit performance requirement.
NFR-23 — Avoid memory leaks (explicit)
The app must avoid memory leaks. Rationale: explicit performance requirement.
NFR-24 — Use lazy loading (explicit)
The app must use lazy loading. Rationale: explicit performance requirement.
NFR-25 — Support offline reading (explicit)
The app must support offline reading. Rationale: explicit performance requirement.
NFR-26 — Dynamic text scaling (explicit)
The app must support dynamic text scaling. Rationale: explicit accessibility requirement.
NFR-27 — TalkBack (explicit)
The app must support TalkBack. Rationale: explicit accessibility requirement.
NFR-28 — High contrast themes (explicit)
The app must support high contrast themes. Rationale: explicit accessibility requirement.
NFR-29 — Large tap targets (explicit)
The app must support large tap targets. Rationale: explicit accessibility requirement.
NFR-30 — RTL perfection (explicit)
The app must support RTL perfection. Rationale: explicit accessibility requirement.
NFR-31 — Reduced motion mode (explicit)
The app must support reduced motion mode. Rationale: explicit accessibility requirement.
NFR-32 — Production-grade code (explicit)
All code must be production-grade. Rationale: explicit code quality requirement.
NFR-33 — Kotlin best practices (explicit)
All code must follow Kotlin best practices. Rationale: explicit code quality requirement.
NFR-34 — Meaningful Arabic-friendly naming where suitable (explicit)
All code must use meaningful Arabic-friendly naming where suitable. Rationale: explicit code quality requirement.
NFR-35 — Modular and maintainable (explicit)
All code must be modular and maintainable. Rationale: explicit code quality requirement.
NFR-36 — Comments for complex logic (explicit)
All code must include comments for complex logic. Rationale: explicit code quality requirement.
NFR-37 — Avoid deprecated Android APIs (explicit)
All code must avoid deprecated Android APIs. Rationale: explicit code quality requirement.
NFR-38 — Follow latest Android official guidance (explicit)
All code must follow latest Android official guidance. Rationale: explicit code quality requirement.
NFR-39 — Respectful request handling (explicit)
API requests must be handled respectfully. Rationale: explicit API integration requirement.
NFR-40 — Error-safe parsing to avoid text corruption (explicit)
API parsing must be error-safe to avoid text corruption. Rationale: explicit API integration requirement.
Page 42 of 45
10. Tech Stack
All technology choices are source-specified and preserved exactly.
- Language: Kotlin
- UI toolkit: Jetpack Compose
- Design system: Material 3
- Architecture: Clean Architecture + MVVM + Repository Pattern
- Dependency injection: Hilt
- Networking: Retrofit + OkHttp
- Local database: Room
- Async: Coroutines + Flow
- Preferences: DataStore Preferences
- Media playback: Media3 / ExoPlayer
- Project layers: presentation, domain, data, core, designsystem
- Feature modules: feature_quran, feature_audio, feature_tafsir, feature_adhkar, feature_bookmarks, feature_settings
- Content source: Quran.com API (Content APIs, Search APIs; User APIs require OAuth2 user tokens and are not used because the app collects no user data)
- Content API authentication:
client_credentials grant with x-auth-token and x-client-id headers
- Content sync:
GET /resources/sync?bootstrap=true&resources=... with snapshot_url for first sync; sync_token for incremental sync
- Permissions:
INTERNET and FOREGROUND_SERVICE_MEDIA_PLAYBACK (if needed) only
11. Assumptions and Constraints
Page 43 of 45
Assumptions
- A-1 (required_inference): Local device storage is available for reading position, bookmarks, favorites, adhkar counts, preferences, and cached content.
- A-2 (required_inference): The Quran.com API is reachable for online content retrieval; when it is not, cached content is used.
- A-3 (required_inference): Offline caches and downloaded resources are sufficient for reading, adhkar, and optionally audio without cloud dependency.
- A-4 (required_inference): Local scheduling is available for daily verse, morning adhkar, and evening adhkar reminders.
- A-5 (required_inference): Media playback service support is available for background recitation and lock-screen controls when enabled.
- A-6 (required_inference): The app does not require an account, sign-in, or identity establishment; all personal state is stored locally.
- A-7 (required_inference): The ten named reciters are available through the Quran.com API recitations listing; if a named reciter is not available, the closest available recitation is offered with a clear label.
Page 44 of 45
Constraints
- C-1 (explicit): No ads.
- C-2 (explicit): No in-app purchases.
- C-3 (explicit): No tracking.
- C-4 (explicit): No analytics SDKs and no tracking SDKs.
- C-5 (explicit): No user data collection.
- C-6 (explicit): Require NO camera permission.
- C-7 (explicit): Require NO microphone permission.
- C-8 (explicit): Require NO location permission.
- C-9 (explicit): Require NO contacts permission.
- C-10 (explicit): Require NO unnecessary storage permission.
- C-11 (explicit): Only use
INTERNET and FOREGROUND_SERVICE_MEDIA_PLAYBACK if needed.
- C-12 (explicit): Arabic-first UX.
- C-13 (explicit): Respectful Islamic design.
- C-14 (explicit): Accurate Qur’an text only from trusted sources.
- C-15 (explicit): Maintain high performance on mid-range Android phones.
- C-16 (explicit): Fully scalable architecture.
- C-17 (explicit): Clean and maintainable codebase.
- C-18 (explicit): Reminders must be respectful, non-intrusive, locally scheduled, and have no cloud dependency.
Future Scope
The following are explicitly future and are kept out of current pages and acceptance:
- F-1: Future scalability roadmap (deliverable).
- F-2: Additional downloadable translations architecture (the architecture is current; the specific additional translations are future).
- F-3: Any future features enabled by the scalable architecture.
Page 45 of 45
12. Glossary
- Adhkar (الأذكار): Remembrance of Allah; the dedicated section covering أذكار الصباح، أذكار المساء، أذكار النوم، أذكار الصلاة، أذكار الاستيقاظ، أذكار السفر، and تسبيح إلكتروني.
- Ayah (آية): A verse of the Holy Qur’an.
- Clean Architecture: A layered architecture separating presentation, domain, data, core, and designsystem.
- Continue Reading: A feature that resumes reading at the last saved position.
- Hizb (حزب): A division of the Qur’an; one of sixty.
- IndoPak: A Qur’an script style used in South Asia.
- Juz (جزء): A division of the Qur’an; one of thirty.
- Mushaf (مصحف): A printed copy of the Qur’an; in the app, the page-style reading mode.
- MVVM: Model-View-ViewModel, the presentation pattern used.
- Noor Al-Dhikr (نور الذكر): The product name of the application.
- pure-adhkar: The project name.
- Quran.com API: The primary trusted source for Qur’an text, translations, recitations, tafsir references, and verse metadata.
- Surah (سورة): A chapter of the Holy Qur’an.
- Tafsir (تفسير): Explanation or commentary on the Qur’an.
- Tajweed (تجويد): The rules of Qur’anic recitation.
- Tasbih (تسبيح): Glorification of Allah; the electronic tasbih is a digital counter.
- Uthmani: The standard Qur’an script style.
- Wayfinding rail: The 1px vertical hairline down the right edge of reading screens, carrying juz/hizb tick marks and a moving dot for the current verse.
No comments yet. Be the first!