Sanad
A hadith reader that draws each narrator chain as a graph and credits every grade to its scholar

- languages side by side: Arabic, English, Indonesian
- 3
- religious verdicts issued by the app
- 0
- finished analytics tools given their own screens
- 6
- to a feature-complete build
- ~5 days
On this page
The problem
For Muslims, the hadith, the recorded sayings of the Prophet Muhammad ﷺ, are the second most important body of text after the Quran. Students and researchers ask the same questions of each one. Who passed it on, and how reliable was each person in that chain? Where do two chains for the same hadith meet or split? Which narrators sit at the centre of the whole network?
Sites such as sunnah.com are good readers, but they offer almost nothing for these questions. Sanad is for Muslim students, general readers and Islamic-studies researchers who want to read a hadith with its chain and its grading in view.
One rule shapes the whole product. The app never issues its own religious verdicts. Arabic text is shown exactly as sourced, and every reliability grade is attributed to the classical scholar who gave it.
What I built
I compute the analytics ahead of time
Counting words, comparing texts and ranking narrators is heavy work across tens of thousands of hadith. The collection itself barely changes. So I run all of it in advance, in background jobs, and store the results. When someone opens a page, the server only reads rows that already exist. Everything else in the system builds on that decision.
Chains are pulled out of the Arabic text
The source dataset has the hadith text but no structured list of narrators. I wrote a parser that finds the chain in each Arabic text by its transmission phrases, such as "narrated to us" and "from", and pulls out the names. From those names it builds a network of teacher and student links. The app labels this as a structural estimate and shows where it came from. Clean names took many rounds of fixes. Fragments of text that aren't names are dropped. Unnamed narrators (mubham) are grouped under one placeholder, and the app never invents an identity for them.
Each graph size gets its own renderer
One hadith's chain is a handful of people. It renders as an interactive graph, and clicking a narrator opens their profile. The whole narrator network runs to hundreds of people and more, which is too many for that tool. So it renders on a canvas with a force layout, with search, focus and a shortest-path finder between any two narrators. I wrote that split into the spec from the start.
Every grade names its source
Each grade shows the scholar who issued it, and a hadith can carry grades from several scholars side by side. Narrators without an assessment show "not yet assessed" in a neutral colour that can't be read as a verdict. I reworked the grade colours once, after an early palette gave some colours meanings they shouldn't have had.
I gave finished backend work a screen
Midway through, I found six analytics endpoints that worked but had no page. I spent the next sprint building screens for them. The grade-distribution explorer, the word-frequency tool, the corpus dashboard, the parallel-narrations panel and the narrator ranking all shipped in that wave.
Result
Sanad is feature-complete and staged for launch, but not public yet. Its data depends on an ingestion pipeline I run locally. Readers get the Arabic text with vowel marks, English and Indonesian translations side by side, grade badges, a focus mode and resume-reading. Signed-in users get bookmarks, collections and reading history. Any hadith can be exported as an image card to share. The original plan had AI topic search. I shipped a curated topic browser over full counts, with no paid AI service behind it. I built Sanad in five days in June 2026, and it grew well past its original spec.
Under the hoodTechnical detail for engineers
- A Django 5.0 and DRF API owns the data and computation. A separate Next.js 14 App Router frontend talks to it over REST. SimpleJWT handles auth.
- PostgreSQL with
pg_trgmtrigram search for text similarity and fuzzy name search. - Precomputed tables
WordFrequencyHadith,NarratorStatsandBookGradeStatsare filled by management commands and Celery jobs, with Redis as the broker and cache. - Chain extraction segments the isnad using transmission verbs such as حدثنا ("narrated to us") and عن ("from"). Arabic normalisation and Arabic-to-Latin transliteration are hand-written, with no
camel_tools. - NetworkX computes centrality, shortest paths and ego networks. Centrality became an approximation for speed, in the same fix that removed a Django
distinct()bug. - Per-hadith chains render in React Flow. The global network renders on a D3-force canvas.
- Models added beyond the original schema:
HadithGrading(several scholars per hadith),Topic/HadithTopic,Collection/CollectionItemandReadingHistory. - Data: Arabic and English text from the open fawazahmed0/hadith-api dataset, and Indonesian translations from the gadingnst API. The target books are the six canonical collections plus the Muwatta and Riyadh al-Salihin.
- CI runs Ruff, a migration check and pytest on the backend, and typecheck, lint and build on the frontend. GitHub Actions publishes images to GHCR on every push to
main. - 19 models, about 30 REST routes, 18 route pages and 14 management commands. About 5,100 lines of TypeScript and 3,800 lines of Python, 86 commits from 25 to 29 June 2026.
Screenshots
Hiring, or building something similar?
I'm open to full-time roles and select freelance work.