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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1768754700607/f3937da6-cf31-4136-8bf7-0c13a0f60322.png align="center")

When I started building advanced search for [**open-mushaf-native**](https://github.com/adelpro/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`](https://github.com/adelpro/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:

```ts
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.

---

## Links

- Open Mushaf Native repo: <https://github.com/adelpro/open-mushaf-native>
- Quran Search Engine repo: <https://github.com/adelpro/quran-search-engine>

