Skip to main content

Command Palette

Search for a command to run...

How I Successfully Implemented quran-search-engine in open-mushaf-native

Clean, paginated Quran search with rich highlighting in a React Native Mushaf

Updated
6 min read
A
I am a web developer

When I started building advanced search for open-mushaf-native, I wanted three things:

  • powerful search (text, lemma, root, fuzzy)
  • good performance, with pagination and infinite scroll
  • code that stays simple and maintainable, not a mess of custom search logic

The quran-search-engine package is what made that possible. Instead of reinventing search from scratch, I delegated the heavy logic to a dedicated library and focused my app code on UI and UX.

This article explains how I integrated quran-search-engine into my app, what new features it unlocked (like pagination), and how it helped me shorten the codebase, reduce files, and still add more features and highlights.


Why I Chose quran-search-engine

Before using the package, implementing Quran search meant handling all of this myself:

  • parsing and normalizing Arabic text
  • wiring in morphology and root/lemma data
  • writing custom matching logic for different search modes
  • trying to keep it fast and memory friendly

That approach quickly becomes complex and hard to maintain.

quran-search-engine solved that by providing:

  • a single search function that takes the Quran text, morphology data, and a word map
  • support for multiple modes: exact text, lemma, root, and fuzzy
  • pagination built in, so I can fetch search results page by page
  • metadata such as matched tokens and token types that I can use for highlighting in the UI

So instead of spreading search logic across multiple files, I only need to:

  • prepare the data
  • call search(...) with the right parameters
  • render the results

Was It Easy to Implement?

Yes – the integration was straightforward because the package has a clean, focused API.

At a high level, my implementation was:

  1. Install and import the package:
    • import { search, type QuranText, type MorphologyAya, type WordMap } from 'quran-search-engine';
  2. Load the data I already had:
    • Quran text (array of verses)
    • morphology JSON
    • word map JSON
  3. Wrap the search call in a custom React hook (useQuranSearch) that:
    • accepts the current query, options, and pagination info
    • calls search
    • exposes results, counts, and helper methods for highlighting
  4. Connect that hook to a search screen with a FlatList and infinite scroll.

Because the package does the heavy lifting, the React Native side stays relatively small:

  • one hook for search logic
  • one screen for UI and infinite scroll
  • one result item component for highlighting and navigation

The hard parts (morphology, token-level matching, fuzzy search) all live inside quran-search-engine, not scattered across the app.


Pagination: The New Feature That Changed the UX

One of the biggest wins from the package is native support for pagination.

The search function accepts page and limit options. Instead of loading all matches at once, I can ask only for:

  • page 1, 50 items
  • page 2, 50 items
  • and so on

In the app, I use:

  • page: React state that tracks the current page
  • PAGE_SIZE: a constant, for example 50
  • FlatList.onEndReached: to detect when the user scrolls near the end and then increment page

Every time page changes, my useQuranSearch hook calls:

search(
  normalizedQuery,
  quranData,
  morphologyMap,
  wordMap,
  {
    lemma: advancedOptions.lemma,
    root: advancedOptions.root,
    fuzzy: advancedOptions.fuzzy,
  },
  {
    page,
    limit: PAGE_SIZE,
  },
);

This gave me infinite scroll through FlatList:

  • the package handles skipping and limiting results
  • the app just renders and appends each page
  • I don’t need to manually calculate offsets or slice arrays

From a user perspective, it feels like a smooth endless list of search results. From a developer perspective, it’s just a page number and a FlatList.


Code Shorter, Cleaner, and With Less Files

Before leaning on quran-search-engine, a search feature tends to produce:

  • multiple utility files for normalization and matching
  • custom indexing logic spread across the project
  • a mix of UI and search logic inside the same components

With the package, I was able to centralize and simplify:

  • I keep search logic in a single hook (useQuranSearch).
  • The search screen handles UI, state, and infinite scroll.
  • The result item handles only presentation and highlighting.

That means:

  • fewer files: no separate search engine implementation in my own codebase
  • shorter files: each file has a clear responsibility (hook vs screen vs item)
  • clear boundaries:
    • quran-search-engine handles how to search the Quran
    • my app handles how to display the results nicely

The result is a much cleaner architecture:

  • easier to read
  • easier to debug
  • easier to extend later

More Features and Better Highlighting

The package doesn’t just return verses; it returns rich metadata.

For each verse, it includes:

  • a list of matched tokens
  • a mapping of token to type (exact, lemma, root, fuzzy)

I use that data to build:

  • color‑coded highlighting:
    • one color for exact text matches
    • another for lemma/root matches
    • another for fuzzy matches
  • a legend component that explains the colors to the user

Because the engine already tells me which tokens matched and how, adding more features is straightforward:

  • I can tweak colors without touching search logic
  • I can show counts like:
    • “X exact matches”
    • “Y lemma matches”
    • “Z root matches”
    • “W fuzzy matches”
  • I can experiment with different UI layouts (cards, compact list, etc.) without changing how the search works

In other words, quran-search-engine lets me focus on UX, not parsing and matching.


How Much Code Did I Really Need?

If you look at the actual integration, the core parts are surprisingly small:

  • a single hook that:
    • sanitizes the query (Arabic only, trimming, etc.)
    • calls search(...) with options and pagination
    • holds pageResults and counts in React state
    • exposes a getPositiveTokens helper to classify matched tokens
  • a screen that:
    • debounces the query
    • manages page, results, hasMore, and isLoadingMore
    • wires up a FlatList with onEndReached
  • a result item component that:
    • receives a verse and matched tokens
    • passes them to a HighlightText component with colors
    • handles navigation to the specific page and aya

Compared to building a full search engine from scratch, the amount of app code is very reasonable. Most of my time went into UI design and UX details, not low‑level search algorithms.


Final Thoughts

Using quran-search-engine in open-mushaf-native gave me:

  • a powerful, production‑ready Quran search engine
  • built‑in support for pagination (enabling infinite scroll)
  • cleaner and shorter code in my own app (fewer files, clearer responsibilities)
  • richer features like lemma/root/fuzzy modes and color‑coded highlighting

Instead of being “the search engine project”, my app stays what it should be: a beautiful, focused Quran reading experience, powered under the hood by a dedicated search package.

If you are building your own Quran app, my advice is simple: let quran-search-engine do the heavy lifting and spend your energy on the user experience.


More from this blog

L

Let's Code

32 posts

Welcome to "Let's Code," a blog dedicated to web development, where I share insights, tutorials, and experiences to help you enhance your skills and stay updated with the latest industry trends.