No release in over 3 years
Complete Sahih al-Bukhari collection with 7,277 authentic hadiths featuring full Arabic text and English translations. Offline-first with zero external dependencies. Includes both Ruby library and command-line interface.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 13.0
~> 3.0
~> 1.21
~> 3.6
~> 0.9
 Project Readme

 sahih-al-bukhari

The complete Sahih al-Bukhari — 7,277 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,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

JavaScript / Node.js Python
# 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 --react

This 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 --help

Example 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 files

Shared 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

Seed a MongoDB database (Node.js)
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");
Seed a database (Python)
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")
Thematic search
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")
Express.js REST API
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!

  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 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!

GitHub stars GitHub forks


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

📖 Docs · 🐛 Issues · 💬 Discussions