sahih-muslim
v1.1.2
Published
Complete Sahih Muslim. Offline-first, zero dependencies. CLI + Node + React/Vue/Vite.
Maintainers
Readme
✨ 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
# 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 --reactThis 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 --helpExample 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 filesShared 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
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");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")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")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!
- Fork the repository
- Create a branch:
git checkout -b feature/my-feature - Commit:
git commit -m 'Add my feature' - Push:
git push origin feature/my-feature - 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!
Made with ❤️ for the Muslim community · Seeking knowledge together

