Skip to main content

Complete Sahih Muslim — 7,563 hadiths with full Arabic text and English translations. Offline-first, zero dependencies. CLI + Python library.

Project description

 sahih-muslim

The complete Sahih Muslim — 7,563 hadiths, full Arabic & English.
One repo · one dataset · published on both npm and PyPI.


npm version PyPI version License: AGPL-3.0

npm downloads PyPI monthly downloads

GitHub stars GitHub issues Last commit

Node.jsPythonTypeScriptZero dependencies


NPM


✨ Features at a Glance

Feature Details
📚 Complete Collection All 7,563 authentic hadiths from Sahih Muslim
🌐 Bilingual Full Arabic text + English translation for every hadith
📝 Chapters 2,200+ chapters with Arabic & English names
Tiny Install ~3KB package — data loaded from CDN on demand
🔍 Full-text Search Search English text and narrator names instantly
🖥️ CLI Terminal access with Arabic/English/both flags
⚛️ React Hook One command generates useMuslim() in your project
🐍 Python Identical API — same method names as the npm package
📘 TypeScript Full type definitions, zero @types package needed
🔧 Zero Config Works out of the box everywhere
🗄️ One Dataset bin/muslim.json shared by both JS and Python

🚀 Installation

JavaScript / Node.js Python
# local (for projects)
npm install sahih-muslim

# global (for CLI)
npm install -g sahih-muslim
# local (for projects)
pip install sahih-muslim

# global CLI is included automatically

🟨 JavaScript / Node.js

CommonJS & ESM

// CommonJS — require()
const muslim = require("sahih-muslim");

// ESM — import
import muslim from "sahih-muslim";

// Get by ID
muslim.get(1); // → Hadith

// Get by chapter
muslim.getByChapter(1); // → Hadith[]

// Full-text search
muslim.search("prayer"); // → Hadith[]

// Random
muslim.getRandom(); // → Hadith

// Index access
muslim[0]; // → Hadith (first)
muslim.length; // → 7563

// Metadata
muslim.metadata; // → { title, author, ... }
muslim.chapters; // → Chapter[]

Hadith object shape

{
  id: 1,
  chapterId: 1,
  arabic: "حَدَّثَنِي يَحْيَى بْنُ يَحْيَى...",
  english: {
    narrator: "Yahya bin Yahya",
    text: "It is narrated on the authority of Amir al-Mu'minin..."
  }
}

Native array methods — all work

muslim.find((h) => h.id === 23);
muslim.filter((h) => h.chapterId === 1);
muslim.map((h) => h.english.narrator);
muslim.forEach((h) => console.log(h.id));
muslim.slice(0, 10);

⚛️ React / Vue / Vite

Run this once inside your React project:

cd my-react-app
muslim --react

This auto-generates src/hooks/useMuslim.js. Then use it anywhere:

import { useMuslim } from "../hooks/useMuslim";

function HadithOfTheDay() {
  const muslim = useMuslim();
  if (!muslim) return <p>Loading...</p>;

  const h = muslim.getRandom();
  return (
    <div>
      <p>
        <strong>{h.english.narrator}</strong>
      </p>
      <p>{h.english.text}</p>
    </div>
  );
}
// Search example
function HadithSearch() {
  const muslim = useMuslim();
  const [results, setResults] = useState([]);
  if (!muslim) return <p>Loading...</p>;

  return (
    <>
      <input
        placeholder="Search hadiths..."
        onChange={(e) => setResults(muslim.search(e.target.value, 10))}
      />
      {results.map((h) => (
        <p key={h.id}>{h.english.text}</p>
      ))}
    </>
  );
}

Data is fetched from jsDelivr CDN once and cached globally. All components share the same request — no duplicates.


🐍 Python

The Python API is identical to the npm package — same camelCase method names, same behaviour.

from sahih_muslim import Muslim

muslim = Muslim()   # reads bin/muslim.json if in repo, else fetches from CDN

# Exact same API as JS
muslim.get(1)                          # Hadith | None
muslim.getByChapter(1)                 # list[Hadith]
muslim.search("prayer")                # list[Hadith]
muslim.search("prayer", limit=5)       # list[Hadith] — top 5
muslim.getRandom()                     # Hadith

# Index access & iteration
muslim[0]                              # first hadith
muslim.length                          # 7563
len(muslim)                            # 7563
for h in muslim: print(h.id)

# Array-style methods (matches JS prototype)
muslim.find(lambda h: h.id == 23)
muslim.filter(lambda h: h.chapterId == 1)
muslim.map(lambda h: h.narrator)
muslim.slice(0, 10)

# Metadata
muslim.metadata.english   # {"title": ..., "author": ...}
muslim.chapters           # list[Chapter]

Custom data path

# Use your own muslim.json at any path
muslim = Muslim(data_path="/absolute/path/to/muslim.json")
muslim = Muslim(data_path=Path(__file__).parent / "muslim.json")

Flask API example

from flask import Flask, jsonify, request
from sahih_muslim import Muslim

app = Flask(__name__)
muslim = Muslim()

@app.get("/api/hadith/<int:hadith_id>")
def get_hadith(hadith_id):
    h = muslim.get(hadith_id)
    return jsonify(h.to_dict()) if h else ("Not found", 404)

@app.get("/api/search")
def search():
    return jsonify([h.to_dict() for h in muslim.search(request.args.get("q", ""), limit=20)])

🖥️ CLI

The same muslim command works whether installed via npm or pip.

# By ID
muslim 1
muslim 2345

# Within a chapter
muslim 23 34

# Language flags
muslim 2345              # English only (default)
muslim 2345 -a           # Arabic only
muslim 2345 --arabic     # Arabic only
muslim 2345 -b           # Arabic + English
muslim 2345 --both       # Arabic + English

# Search
muslim --search "prayer"
muslim --search "fasting" --all    # show all results (default: top 5)

# Chapter listing
muslim --chapter 5

# Random
muslim --random
muslim --random -b

# React hook generator (JS only — run inside your React project)
muslim --react

# Info
muslim --version
muslim --help

Example output

════════════════════════════════════════════════════════════
Hadith #1  |  Chapter: 1 — Faith
════════════════════════════════════════════════════════════
Narrator: Yahya bin Yahya

It is narrated on the authority of Amir al-Mu'minin, Abu Hafs
Umar ibn al-Khattab, who said: I heard the Messenger of Allah
(ﷺ) say: "Actions are judged by intentions..."
════════════════════════════════════════════════════════════

🗄️ Monorepo Structure

sahih-muslim/
│
├── bin/
│   ├── muslim.json         ← 🔑 SHARED — single source of truth for JS + Python
│   └── index.js            ← JS CLI entry
│
├── chapters/               ← 🔑 SHARED — generated by `node build.mjs`
│   ├── meta.json               used by CDN loader (JS browser) + Python CDN fallback
│   ├── 1.json
│   └── ...
│
├── sahih_muslim/           ← Python package
│   ├── __init__.py
│   ├── muslim.py           ← auto-reads bin/muslim.json
│   └── cli.py
│
├── index.js                ← JS ESM (browser-safe)
├── index.cjs               ← JS CommonJS
├── index.node.js           ← JS Node ESM
├── index.browser.js        ← JS browser / CDN (auto-generated)
├── index.d.ts              ← TypeScript definitions
├── build.mjs               ← generates chapters/ from bin/muslim.json
│
├── package.json            ← npm config
├── pyproject.toml          ← Python / Poetry config
├── MANIFEST.in             ← Python sdist: include data, exclude JS
└── .npmignore              ← npm publish: exclude Python files

Shared data — how it works

File Used by
bin/muslim.json JS Node (CJS + ESM) · Python (auto-detected from repo root)
chapters/ JS browser CDN fetch · Python CDN fallback

You never duplicate data. Both packages read the exact same file.


📊 API Reference

Methods

Method JS Python Returns
get(id) Hadith | undefined/None
getByChapter(id) Hadith[]
search(query, limit?) Hadith[]
getRandom() Hadith
find(predicate) Hadith | undefined/None
filter(predicate) Hadith[]
map(fn) any[]
forEach(fn) void/None
slice(start, end) Hadith[]

Properties

Property Type Description
length number / int Total hadiths — 7,563
metadata Metadata Title, author, introduction
chapters Chapter[] All chapters

💡 Examples

Seed a MongoDB database (Node.js)
import { MongoClient } from "mongodb";
import muslim from "sahih-muslim";

const client = new MongoClient(process.env.MONGO_URI);
await client.connect();
await client
  .db("islam")
  .collection("hadiths")
  .insertMany([...muslim]);
await client.close();
console.log("Seeded", muslim.length, "hadiths");
Seed a database (Python)
from sahih_muslim import Muslim

muslim = Muslim()
records = [h.to_dict() for h in muslim]
# Insert into any DB
print(f"Seeded {len(records)} hadiths")
Thematic search
from sahih_muslim import Muslim

muslim = Muslim()
topics = ["prayer", "charity", "fasting", "knowledge", "patience"]
for topic in topics:
    count = len(muslim.search(topic))
    print(f"{topic:12}{count} hadiths")
Express.js REST API
import express from "express";
import muslim from "sahih-muslim";

const app = express();

app.get("/api/hadith/random", (_, res) => res.json(muslim.getRandom()));
app.get("/api/hadith/:id", (req, res) => {
  const h = muslim.get(parseInt(req.params.id));
  h ? res.json(h) : res.status(404).json({ error: "Not found" });
});
app.get("/api/search", (req, res) =>
  res.json(muslim.search(req.query.q || "")),
);
app.get("/api/chapter/:id", (req, res) =>
  res.json(muslim.getByChapter(parseInt(req.params.id))),
);

app.listen(3000, () => console.log("Running on :3000"));

🔧 Development

git clone https://github.com/SENODROOM/sahih-muslim.git
cd sahih-muslim
npm install

# Regenerate chapters/ from bin/muslim.json
node build.mjs

# Publish to npm
npm publish

# Publish to PyPI
pip install build twine
python -m build
python -m twine upload dist/*

🤝 Contributing

Contributions are welcome!

  1. Fork the repository
  2. Create a branch: git checkout -b feature/my-feature
  3. Commit: git commit -m 'Add my feature'
  4. Push: git push origin feature/my-feature
  5. Open a Pull Request

📄 License

Licensed under the GNU Affero General Public License v3.0 (AGPL-3.0) — see LICENSE for details.


🙏 Acknowledgments

  • 📖 Source — Sahih Muslim, one of the most authentic hadith collections in Islam
  • 👨‍🏫 Translations — By reputable Islamic scholars
  • 💚 Inspiration — The global Muslim community seeking knowledge

🌟 If this project helped you, please give it a star!

GitHub stars GitHub forks


Made with ❤️ for the Muslim community · Seeking knowledge together

📖 Docs · 🐛 Issues · 💬 Discussions

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sahih_muslim-1.1.0.tar.gz (2.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sahih_muslim-1.1.0-py3-none-any.whl (23.5 kB view details)

Uploaded Python 3

File details

Details for the file sahih_muslim-1.1.0.tar.gz.

File metadata

  • Download URL: sahih_muslim-1.1.0.tar.gz
  • Upload date:
  • Size: 2.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for sahih_muslim-1.1.0.tar.gz
Algorithm Hash digest
SHA256 3614a2fceb63fd2c4dce9dedee5d0596732570a3adf4ea4f0a731f784b44c4d2
MD5 79efab420e907cebfc204e4b2b8cf501
BLAKE2b-256 7193a564707b56e8f151e87746fe51d86b5ba5c81eb5d9bfad70fb7b0d8f526b

See more details on using hashes here.

File details

Details for the file sahih_muslim-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: sahih_muslim-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 23.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for sahih_muslim-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bdda0aa3f9e3839883b10d12082d4340e5cd4f8acd2de0d94c40dc78c14ce94f
MD5 317d32870702c4e8b7bc7039ee4689c0
BLAKE2b-256 6912e5d7f68b35a8353e32e3b37b096f87d36775ba25ded9aa8e65409ebda1c9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page