A live, in-browser demo of grahan, an astronomy and Vedic-astrology (Jyotish)
TypeScript library suite. Every feature on the page is a real call into the published
@grahan/* packages running client-side, so the app doubles as an integration test and a
worked set of usage examples.
- Library source: https://github.com/svarbhanu/grahan
- API reference: https://svarbhanu.github.io/grahan/
grahan is MIT-licensed, has zero runtime dependencies, and ships as pure ESM TypeScript. It is split into three packages:
| Package | What it does |
|---|---|
@grahan/core |
Astronomy engine: Julian day conversion, Sun and Moon positions, sunrise/sunset, moon phase, next solar and lunar eclipses. |
@grahan/vedic |
Jyotish: panchang at sunrise, kundali (birth chart) with SVG rendering, Vimshottari dasha. |
@grahan/calendars |
Bikram Sambat (Nepali) and Gregorian date conversion. |
Install:
npm install @grahan/core @grahan/vedic @grahan/calendarsAll weekday indices are 0 = Sunday ... 6 = Saturday. Astronomy instants are JS Date
(UTC) or Julian Day (UT).
import { panchangAtSunrise } from '@grahan/vedic';
const p = panchangAtSunrise({
year: 2026, month: 7, day: 8,
latitude: 27.7172, longitude: 85.3240,
timezone: 'Asia/Kathmandu',
});
p.vaar.name; // weekday, e.g. "Wednesday"
p.tithi[0].name; // e.g. "Pratipada"
p.nakshatra[0]; // { name, pada, ... }
p.sunrise; // Date | null
p.rahuKaal; // { start: Date, end: Date } | null
p.moonPhase.phaseName; // e.g. "waxing-crescent"import { julianDayFromDate, nextSolarEclipseAt, nextLunarEclipse } from '@grahan/core';
const jd = julianDayFromDate(new Date());
const observer = { latitude: 27.7172, longitude: 85.3240 };
const solar = nextSolarEclipseAt(jd, observer);
solar.type; // 'partial' | 'annular' | 'total'
solar.magnitude; // number
solar.maximum; // Julian Day of greatest eclipse
const lunar = nextLunarEclipse(jd);
lunar.type; // 'penumbral' | 'partial' | 'total'import { julianDayFromDate, moonPhase } from '@grahan/core';
const m = moonPhase(julianDayFromDate(new Date()));
m.phaseName; // e.g. "full"
m.illuminatedFraction; // 0..1import { kundali, kundaliSvg, vimshottari } from '@grahan/vedic';
const k = kundali({
date: new Date('1993-08-18T05:15:00Z'),
latitude: 27.0104, longitude: 84.8821,
});
k.lagna.rashiName; // ascendant sign, e.g. "Tula"
k.grahas; // planet positions (rashi, nakshatra, bhava, retrograde)
const svg = kundaliSvg(k, { style: 'north', size: 320 }); // self-contained SVG string
const moon = k.grahas.find((g) => g.graha === 'moon')!;
const dasha = vimshottari(moon.longitude, k /* birth date */ as unknown as Date);
// dasha.mahadashas -> Vimshottari mahadasha timelineimport { bsFromDate, dateFromBs, todayBs } from '@grahan/calendars';
bsFromDate({ year: 2026, month: 7, day: 8 }); // -> BS date with Roman + Nepali month names
dateFromBs({ year: 2083, month: 3, day: 24 }); // -> AD date (throws RangeError if invalid)
todayBs({ timezone: 'Asia/Kathmandu' }); // -> today's BS dateThe supported BS range is roughly 1975 to 2100. BS months run 29 to 32 days, so month length is never assumed.
grahan-showcase is a single-page, hash-routed app with one page per feature. Each page
wraps its @grahan calls in error boundaries so one failing section never blanks the rest.
- Panchang (
#/panchang): today's Hindu almanac for a chosen location (vaar, tithi, nakshatra + pada, yoga, karana, sunrise/sunset, Rahu Kaal, moon phase). - Calendar (
#/calendar): a Hamro Patro-style Bikram Sambat month grid with Devanagari numerals; click any date to reveal that day's full panchang. - Eclipses (
#/eclipse): next local solar eclipse and next lunar eclipse for the selected location. - Birth chart (
#/kundali): birth date, time and location render an SVG North/South chart, a graha table, and the Vimshottari mahadasha timeline. - AD / BS converter (
#/converter): two-way Gregorian and Bikram Sambat converter with a "Today in Nepal" banner.
On mount the app runs a golden-fixture self-check against known library output and shows a warning banner if anything regresses. The only network call is Open-Meteo geocoding for city search; everything else is computed in the browser.
React 19, Vite 8, TypeScript, plain CSS (light and dark via prefers-color-scheme), Oxlint,
and a tiny custom hash router. No backend, database, or accounts.
npm install
npm run dev # http://localhost:5173/grahan-showcase/
npm run build # tsc -b && vite build -> dist/
npm run preview # serve the built dist/
npm run lint # oxlintThe dev and preview URLs include the /grahan-showcase/ base path set in
vite.config.ts. That base makes the build deployable as a GitHub Pages project site at
https://svarbhanu.github.io/grahan-showcase/.
MIT