sahih-al-bukhari
v3.1.7
Published
Complete Sahih al-Bukhari. Offline-first, zero dependencies. CLI + Node + React/Vue/Vite.
Downloads
2,182
Maintainers
Readme
✨ Features at a Glance
| | Feature | Details |
| --- | ----------------------- | ------------------------------------------------------- |
| 📚 | Complete Collection | All 7,277 authentic hadiths from Sahih al-Bukhari |
| 🌐 | Bilingual | Full Arabic text + English translation for every hadith |
| 📝 | Chapters | 4,000+ 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 useBukhari() 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/bukhari.json shared by both JS and Python |
🚀 Installation
# local (for projects)
npm install sahih-al-bukhari
# global (for CLI)
npm install -g sahih-al-bukhari# local (for projects)
pip install sahih-al-bukhari
# global CLI is included automatically🟨 JavaScript / Node.js
CommonJS & ESM
// CommonJS — require()
const bukhari = require("sahih-al-bukhari");
// ESM — import
import bukhari from "sahih-al-bukhari";
// Get by ID
bukhari.get(1); // → Hadith
// Get by chapter
bukhari.getByChapter(1); // → Hadith[]
// Full-text search
bukhari.search("prayer"); // → Hadith[]
// Random
bukhari.getRandom(); // → Hadith
// Index access
bukhari[0]; // → Hadith (first)
bukhari.length; // → 7277
// Metadata
bukhari.metadata; // → { title, author, ... }
bukhari.chapters; // → Chapter[]Hadith object shape
{
id: 1,
chapterId: 1,
arabic: "حَدَّثَنَا الْحُمَيْدِيُّ...",
english: {
narrator: "Umar bin Al-Khattab",
text: "I heard Allah's Messenger (ﷺ) saying..."
}
}Native array methods — all work
bukhari.find((h) => h.id === 23);
bukhari.filter((h) => h.chapterId === 1);
bukhari.map((h) => h.english.narrator);
bukhari.forEach((h) => console.log(h.id));
bukhari.slice(0, 10);⚛️ React / Vue / Vite
Run this once inside your React project:
cd my-react-app
bukhari --reactThis auto-generates src/hooks/useBukhari.js. Then use it anywhere:
import { useBukhari } from "../hooks/useBukhari";
function HadithOfTheDay() {
const bukhari = useBukhari();
if (!bukhari) return <p>Loading...</p>;
const h = bukhari.getRandom();
return (
<div>
<p>
<strong>{h.english.narrator}</strong>
</p>
<p>{h.english.text}</p>
</div>
);
}// Search example
function HadithSearch() {
const bukhari = useBukhari();
const [results, setResults] = useState([]);
if (!bukhari) return <p>Loading...</p>;
return (
<>
<input
placeholder="Search hadiths..."
onChange={(e) => setResults(bukhari.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_al_bukhari import Bukhari
bukhari = Bukhari() # reads bin/bukhari.json if in repo, else fetches from CDN
# Exact same API as JS
bukhari.get(1) # Hadith | None
bukhari.getByChapter(1) # list[Hadith]
bukhari.search("prayer") # list[Hadith]
bukhari.search("prayer", limit=5) # list[Hadith] — top 5
bukhari.getRandom() # Hadith
# Index access & iteration
bukhari[0] # first hadith
bukhari.length # 7277
len(bukhari) # 7277
for h in bukhari: print(h.id)
# Array-style methods (matches JS prototype)
bukhari.find(lambda h: h.id == 23)
bukhari.filter(lambda h: h.chapterId == 1)
bukhari.map(lambda h: h.narrator)
bukhari.slice(0, 10)
# Metadata
bukhari.metadata.english # {"title": ..., "author": ...}
bukhari.chapters # list[Chapter]Custom data path
# Use your own bukhari.json at any path
bukhari = Bukhari(data_path="/absolute/path/to/bukhari.json")
bukhari = Bukhari(data_path=Path(__file__).parent / "bukhari.json")Flask API example
from flask import Flask, jsonify, request
from sahih_al_bukhari import Bukhari
app = Flask(__name__)
bukhari = Bukhari()
@app.get("/api/hadith/random")
def random_hadith():
return jsonify(bukhari.getRandom().to_dict())
@app.get("/api/hadith/<int:hadith_id>")
def get_hadith(hadith_id):
h = bukhari.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 bukhari.search(request.args.get("q", ""), limit=20)])🖥️ CLI
The same bukhari command works whether installed via npm or pip.
# By ID
bukhari 1
bukhari 2345
# Within a chapter
bukhari 23 34
# Language flags
bukhari 2345 # English only (default)
bukhari 2345 -a # Arabic only
bukhari 2345 --arabic # Arabic only
bukhari 2345 -b # Arabic + English
bukhari 2345 --both # Arabic + English
# Search
bukhari --search "prayer"
bukhari --search "fasting" --all # show all results (default: top 5)
# Chapter listing
bukhari --chapter 5
# Random
bukhari --random
bukhari --random -b
# React hook generator (JS only — run inside your React project)
bukhari --react
# Info
bukhari --version
bukhari --helpExample output
════════════════════════════════════════════════════════════
Hadith #1 | Chapter: 1 — Revelation
════════════════════════════════════════════════════════════
Narrator: Umar bin Al-Khattab
I heard Allah's Messenger (ﷺ) saying, "The reward of deeds
depends upon the intentions and every person will get the
reward according to what he has intended..."
════════════════════════════════════════════════════════════🗄️ Monorepo Structure
sahih-al-bukhari/
│
├── bin/
│ ├── bukhari.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_al_bukhari/ ← Python package
│ ├── __init__.py
│ ├── bukhari.py ← auto-reads bin/bukhari.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/bukhari.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/bukhari.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,277 |
| metadata | Metadata | Title, author, introduction |
| chapters | Chapter[] | All chapters |
💡 Examples
import { MongoClient } from "mongodb";
import bukhari from "sahih-al-bukhari";
const client = new MongoClient(process.env.MONGO_URI);
await client.connect();
await client
.db("islam")
.collection("hadiths")
.insertMany([...bukhari]);
await client.close();
console.log("Seeded", bukhari.length, "hadiths");from sahih_al_bukhari import Bukhari
bukhari = Bukhari()
records = [h.to_dict() for h in bukhari]
# Insert into any DB
print(f"Seeded {len(records)} hadiths")from sahih_al_bukhari import Bukhari
bukhari = Bukhari()
topics = ["prayer", "charity", "fasting", "knowledge", "patience"]
for topic in topics:
count = len(bukhari.search(topic))
print(f"{topic:12} → {count} hadiths")import express from "express";
import bukhari from "sahih-al-bukhari";
const app = express();
app.get("/api/hadith/random", (_, res) => res.json(bukhari.getRandom()));
app.get("/api/hadith/:id", (req, res) => {
const h = bukhari.get(parseInt(req.params.id));
h ? res.json(h) : res.status(404).json({ error: "Not found" });
});
app.get("/api/search", (req, res) =>
res.json(bukhari.search(req.query.q || "")),
);
app.get("/api/chapter/:id", (req, res) =>
res.json(bukhari.getByChapter(parseInt(req.params.id))),
);
app.listen(3000, () => console.log("Running on :3000"));🔧 Development
git clone https://github.com/SENODROOM/sahih-al-bukhari.git
cd sahih-al-bukhari
npm install
# Regenerate chapters/ from bin/bukhari.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 al-Bukhari, the most authentic hadith collection 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

