A while back I wrote about building mabims.dev, a free open-source API for Indonesia's Hijri calendar based on MABIMS criteria (not Umm al-Qura, which is what most Hijri libraries default to and which can be off by a day from what's officially observed here).
But an API is still an API... every time your widget renders, you're firing a network request just to answer "what's today's Hijri date?" For something that changes once a day and barely ever needs live computation, that felt like overkill.
So I built mabims-hijri, an npm package that bundles the calendar data directly into your app. Most lookups resolve instantly, with zero network calls.
The Idea
Hijri dates for 2024β2026 are already known, they're not live-computed, they come from an official curated table. So instead of hitting an API for a fact that doesn't change, the package ships that table (~72KB of JSON) right inside itself.
npm install mabims-hijri
import { today } from 'mabims-hijri'
const date = await today()
console.log(date.output)
// {
// date: '1448-03-18',
// calendar: 'hijri',
// day: 18,
// month: 3,
// month_name: 'Rabiul Awal',
// year: 1448
// }
That call resolves from bundled data. No fetch, no waiting, works offline.
Three-Tier Fallback
For dates outside the bundled range (post-2026), it falls back gracefully instead of just failing:
βββββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββββ
β Bundled MABIMS β βββΊ β In-Memory Cache β βββΊ β Live API β
β (data.json) β β (per-session) β β (mabims.dev) β
βββββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββββ
Built-in Always fast Fallback only
2024β2026 (TTL: 24h) (outside range)
- Bundled data: instant, no network, covers 2024-01-13 to 2026-12-31.
- In-memory cache: anything fetched from the API gets cached for 24h so repeat lookups stay fast.
- Live API: only touched when you ask for a date outside the bundled range.
The package also silently checks once a day for a newer version of the table and updates itself in the background, so it stays current without you having to bump the package version by hand.
Converting Dates
Same offline-first behavior applies to conversion, not just "today":
import { convert } from 'mabims-hijri'
// Gregorian β Hijri
const hijri = await convert('2026-08-31')
console.log(hijri.output.month_name) // 'Rabiul Awal'
// Hijri β Gregorian
const gregorian = await convert('1448-03-18', 'hijri')
Rendering a Widget (React example)
import { useState, useEffect } from 'react'
import { today, type HijriDate } from 'mabims-hijri'
function HijriToday() {
const [date, setDate] = useState<HijriDate | null>(null)
useEffect(() => {
today().then((res) => setDate(res.output))
}, [])
if (!date) return <span>Loading...</span>
return <span>{date.day} {date.month_name} {date.year} H</span>
}
First render, no spinner needed in practice! The bundled lookup is fast enough that useEffect resolves almost immediately.
Works Anywhere fetch Exists
Node 18+, browsers, edge runtimes (Cloudflare Workers, Vercel Edge, Deno), and React Native. For React Native, there's no localStorage, so persistent caching needs a storage adapter... but good news! The package exposes a simple interface for that:
import { setStorageAdapter } from 'mabims-hijri'
import AsyncStorage from '@react-native-async-storage/async-storage'
setStorageAdapter({
get: (key) => AsyncStorage.getItem('mabims_' + key),
set: (key, value) => AsyncStorage.setItem('mabims_' + key, value),
has: async (key) => (await AsyncStorage.getItem('mabims_' + key)) !== null,
})
Without it, caching just falls back to in-memory (works fine, just doesn't persist across app restarts).
Other Things It Covers
Beyond today() and convert(), the package wraps the full API surface: range() for bulk date conversion, month()/year() for rendering calendar grids, events() for Islamic holidays (Ramadan, Idul Fitri, Idul Adha, etc.), and hilal.info() for moon-visibility data used to determine the start of a Hijri month. Full reference is in the README.
Try It
npm install mabims-hijri
- npm: npmjs.com/package/mabims-hijri
- Source: github.com/PijarAdiluhung/mabims-hijri
- API docs: mabims.dev
MIT licensed, zero dependencies beyond native fetch. If you build something with it or hit an edge case, issues and PRs are welcome.
Top comments (0)