Swiss Ephemeris library for Vedic astrology calculations with pre-built native binaries.
✅ Vercel Compatible - Works in serverless environments without native compilation.
- 🌟 Vedic Astrology Focus - Calculate all 9 Vedic planets (Navagraha)
- 🚀 Pre-built Binaries - No native compilation required
- ☁️ Vercel Ready - Works in serverless environments out of the box
- 📦 Pre-compiled Distribution - Ready-to-use dist files included
- 🌍 Cross-Platform - Works on macOS (Intel & ARM), Linux, and Windows
- 📦 Simple API - Clean, TypeScript-first interface
- ⚡ Fast - Native Swiss Ephemeris performance
npm install @AstroFusion/sweph
# or
pnpm add @AstroFusion/sweph
# or
yarn add @AstroFusion/swephimport {
calculatePlanets,
calculateLagna,
calculateSunTimes,
calculateMoonData
} from '@AstroFusion/sweph';
// Calculate planetary positions
const planets = calculatePlanets(new Date());
console.log(planets);
// Calculate Lagna (Ascendant)
const location = { latitude: 27.7172, longitude: 85.324, timezone: 5.75 };
const lagna = calculateLagna(new Date(), location);
console.log(`Ascendant: ${lagna.rasi} at ${lagna.degree.toFixed(2)}°`);
// Get sunrise/sunset
const sunTimes = calculateSunTimes(new Date(), location);
console.log(`Sunrise: ${sunTimes.sunrise}`);
console.log(`Sunset: ${sunTimes.sunset}`);
// Get moon phase
const moon = calculateMoonData(new Date(), location);
console.log(`Moon Phase: ${moon.phaseName} (${moon.illumination.toFixed(1)}%)`);For projects that need the pre-compiled distribution files directly:
// Import from dist files (already compiled and included in repo)
import { calculatePlanets } from './path/to/astrofusion-sweph/dist/index.js';
import type { Planet } from './path/to/astrofusion-sweph/dist/types.d.ts';
// All distribution files are committed to git for direct usage
// No build step required for consuming projectsCalculate positions for all 9 Vedic planets (Navagraha).
import { calculatePlanets, AYANAMSA, HOUSE_SYSTEMS } from '@AstroFusion/sweph';
const planets = calculatePlanets(new Date('1990-01-15T14:30:00'), {
ayanamsa: AYANAMSA.LAHIRI, // or AYANAMSA.KRISHNAMURTI
houseSystem: HOUSE_SYSTEMS.PLACIDUS,
includeSpeed: true,
location: {
latitude: 27.7172, // Kathmandu, Nepal
longitude: 85.324,
timezone: 5.75
}
});
// Access planet data
const sun = planets.find(p => p.name === 'Sun');
if (sun) {
console.log(`${sun.name}: ${sun.longitude}° in ${RASHIS[sun.rasi-1]?.name}`);
console.log(`Retrograde: ${sun.isRetrograde}, Combust: ${sun.isCombust}`);
}Returns: Array of Planet objects with ecliptic and horizontal coordinates.
Calculate position for a specific celestial body.
import { calculateSinglePlanet, PlanetId } from '@AstroFusion/sweph';
const mars = calculateSinglePlanet(PlanetId.MARS, new Date(), {
ayanamsa: AYANAMSA.LAHIRI,
location: { latitude: 40.7128, longitude: -74.0060, timezone: -5 }
});
if (mars) {
console.log(`Mars: ${mars.longitude}° (${mars.azimuth}° azimuth)`);
}Parameters:
planetId: Swiss Ephemeris planet ID (0-9 for planets, 10-15 for points)date: Date for calculationoptions: Calculation options
Calculate Ascendant (Lagna) and all 12 house cusps for Vedic chart.
import { calculateLagna, HOUSE_SYSTEMS, AYANAMSA } from '@AstroFusion/sweph';
const lagna = calculateLagna(new Date('1990-01-15T14:30:00'), {
latitude: 27.7172,
longitude: 85.324,
timezone: 5.75
}, {
ayanamsa: AYANAMSA.LAHIRI,
houseSystem: HOUSE_SYSTEMS.WHOLE_SIGN
});
console.log(`Ascendant: ${lagna.rasi}°${lagna.degree.toFixed(2)}' in ${RASHIS[lagna.rasi-1]?.name}`);
console.log(`Midheaven (MC): ${lagna.houses[9]?.toFixed(2)}°`);Returns: LagnaInfo object with ascendant details and house cusps array.
Calculate house cusps only (convenience function).
const birthDate = new Date('1990-01-15T14:30:00');
const location = { latitude: 27.7172, longitude: 85.324, timezone: 5.75 };
const houses = calculateHouses(birthDate, location);
console.log(`1st House: ${houses[0]}°, 7th House: ${houses[6]}°`);Determine which house a planet occupies.
const lagna = calculateLagna(birthDate, location);
const planets = calculatePlanets(birthDate);
const sunHouse = getHousePosition(planets[0].longitude, lagna.houses);
console.log(`Sun is in house ${sunHouse}`);Calculate sunrise, sunset, and twilight times.
const sunTimes = calculateSunTimes(new Date(), {
latitude: 51.5074, // London
longitude: -0.1278,
timezone: 0
});
console.log(`Sunrise: ${sunTimes.sunrise?.toLocaleTimeString()}`);
console.log(`Sunset: ${sunTimes.sunset?.toLocaleTimeString()}`);
console.log(`Day length: ${sunTimes.dayLength.toFixed(1)} hours`);
console.log(`Civil twilight: ${sunTimes.civilTwilightStart} - ${sunTimes.civilTwilightEnd}`);Calculate solar noon and sun's altitude at meridian.
const solarNoon = calculateSolarNoon(new Date(), location);
console.log(`Solar noon: ${solarNoon.time.toLocaleTimeString()}`);
console.log(`Sun altitude: ${solarNoon.altitude.toFixed(1)}°`);Get sun's position every hour throughout the day.
const sunPath = calculateSunPath(new Date(), location);
sunPath.forEach(pos => {
console.log(`${pos.time.getHours()}:00 - Altitude: ${pos.altitude.toFixed(1)}°, Azimuth: ${pos.azimuth.toFixed(1)}°`);
});Calculate moonrise, moonset, phase, and illumination.
const moonData = calculateMoonData(new Date(), location);
console.log(`Moonrise: ${moonData.moonrise?.toLocaleTimeString()}`);
console.log(`Phase: ${moonData.phaseName} (${moonData.illumination.toFixed(1)}%)`);
console.log(`Moon age: ${moonData.age.toFixed(1)} days`);Calculate current moon phase details.
const phase = calculateMoonPhase(new Date());
console.log(`Phase angle: ${phase.phase.toFixed(1)}°`);
console.log(`Illumination: ${phase.illumination.toFixed(1)}%`);
console.log(`Age: ${phase.age.toFixed(1)} days since new moon`);Get dates of upcoming lunar phases.
const phases = calculateNextMoonPhases(new Date());
console.log(`Next Full Moon: ${phases.fullMoon.toDateString()}`);
console.log(`Next New Moon: ${phases.newMoon.toDateString()}`);Calculate rise, set, and transit times for any celestial body.
const moonTimes = calculatePlanetRiseSetTimes(1, new Date(), location); // 1 = Moon
console.log(`Moonrise: ${moonTimes.rise?.toLocaleTimeString()}`);
console.log(`Moonset: ${moonTimes.set?.toLocaleTimeString()}`);
console.log(`Transit: ${moonTimes.transit?.toLocaleTimeString()}`);Get the ayanamsa correction value.
import { getAyanamsa, AYANAMSA } from '@AstroFusion/sweph';
const ayanamsa = getAyanamsa(new Date(), AYANAMSA.LAHIRI);
console.log(`Lahiri ayanamsa: ${ayanamsa.toFixed(4)}°`);Set custom path to Swiss Ephemeris data files.
// Set custom ephemeris path before calculations
setEphemerisPath('/custom/path/to/ephemeris');Convert between JavaScript Date and Julian Day numbers.
import { dateToJulian, julianToDate } from '@AstroFusion/sweph';
const jd = dateToJulian(new Date());
const date = julianToDate(jd + 1); // TomorrowThe library includes legacy functions for migration from older @astrofusion/sweph packages:
import { createSwephCalculator, calculateKundaliPageData } from '@AstroFusion/sweph';
const birthDate = new Date('1990-01-15T14:30:00');
const timezone = 5.75;
const location = { latitude: 27.7172, longitude: 85.324, timezone: 5.75 };
// Legacy calculator interface
const calculator = createSwephCalculator();
const planets = await calculator.calculateAllPlanetPositions(birthDate, timezone);
// Complete kundali data
const kundaliData = await calculateKundaliPageData(birthDate, location);import { AYANAMSA } from '@AstroFusion/sweph';
// Available ayanamsas
AYANAMSA.LAHIRI // 1 (default)
AYANAMSA.KRISHNAMURTI // 5
AYANAMSA.RAMAN // 3
AYANAMSA.TRUE_CITRA // 27
// ... and moreimport { HOUSE_SYSTEMS } from '@AstroFusion/sweph';
HOUSE_SYSTEMS.PLACIDUS // 'P' (default)
HOUSE_SYSTEMS.WHOLE_SIGN // 'W'
HOUSE_SYSTEMS.EQUAL // 'E'
HOUSE_SYSTEMS.SRIPATI // 'S'
// ... and moreimport {
calculatePlanets,
calculateLagna,
getHousePosition,
getNakshatra,
AYANAMSA,
HOUSE_SYSTEMS,
RASHIS,
NAKSHATRAS
} from '@AstroFusion/sweph';
function createBirthChart(birthDate: Date, location: GeoLocation) {
// Calculate all components
const planets = calculatePlanets(birthDate, {
ayanamsa: AYANAMSA.LAHIRI,
houseSystem: HOUSE_SYSTEMS.PLACIDUS,
includeSpeed: true,
location
});
const lagna = calculateLagna(birthDate, location, {
ayanamsa: AYANAMSA.LAHIRI,
houseSystem: HOUSE_SYSTEMS.PLACIDUS
});
// Create chart data
const chart = {
lagna: {
longitude: lagna.longitude,
rasi: RASHIS[lagna.rasi - 1],
degree: lagna.degree
},
planets: planets.map(planet => ({
...planet,
house: getHousePosition(planet.longitude, lagna.houses),
nakshatra: NAKSHATRAS.find(n => n.number === getNakshatra(planet.longitude).number)
})),
houses: lagna.houses.map((cusp, index) => ({
number: index + 1,
longitude: cusp,
rasi: RASHIS[Math.floor(cusp / 30)]
}))
};
return chart;
}import { calculatePlanets, AYANAMSA } from '@AstroFusion/sweph';
const birthDate = new Date('1990-01-15T14:30:00');
// Compare different ayanamsa systems
const lahiriPlanets = calculatePlanets(birthDate, { ayanamsa: AYANAMSA.LAHIRI });
const krishnamurtiPlanets = calculatePlanets(birthDate, { ayanamsa: AYANAMSA.KRISHNAMURTI });
const sunLahiri = lahiriPlanets.find(p => p.name === 'Sun');
const sunKP = krishnamurtiPlanets.find(p => p.name === 'Sun');
if (sunLahiri && sunKP) {
console.log(`Sun position (Lahiri): ${sunLahiri.longitude.toFixed(2)}°`);
console.log(`Sun position (KP): ${sunKP.longitude.toFixed(2)}°`);
console.log(`Difference: ${(sunKP.longitude - sunLahiri.longitude).toFixed(2)}°`);
}import { calculateMoonPhase, calculateNextMoonPhases } from '@AstroFusion/sweph';
// Current moon phase
const currentPhase = calculateMoonPhase(new Date());
console.log(`Current: ${currentPhase.phaseName} (${currentPhase.illumination.toFixed(1)}%)`);
// Upcoming phases
const nextPhases = calculateNextMoonPhases(new Date());
console.log(`Next Full Moon: ${nextPhases.fullMoon.toLocaleDateString()}`);
console.log(`Next New Moon: ${nextPhases.newMoon.toLocaleDateString()}`);
// Moon phase calendar for next month
function getMoonCalendar(startDate: Date, days: number) {
const calendar = [];
for (let i = 0; i < days; i++) {
const date = new Date(startDate);
date.setDate(date.getDate() + i);
const phase = calculateMoonPhase(date);
calendar.push({
date: date.toDateString(),
phase: phase.phaseName,
illumination: phase.illumination
});
}
return calendar;
}import { calculateSunTimes, calculateSunPath } from '@AstroFusion/sweph';
function analyzeDaylight(date: Date, location: GeoLocation) {
const sunTimes = calculateSunTimes(date, location);
const sunPath = calculateSunPath(date, location);
return {
sunrise: sunTimes.sunrise,
sunset: sunTimes.sunset,
dayLength: sunTimes.dayLength,
maxAltitude: Math.max(...sunPath.map(p => p.altitude)),
twilight: {
civil: {
start: sunTimes.civilTwilightStart,
end: sunTimes.civilTwilightEnd
},
nautical: {
start: sunTimes.nauticalTwilightStart,
end: sunTimes.nauticalTwilightEnd
}
}
};
}
// Compare summer vs winter solstice
const summerSolstice = analyzeDaylight(new Date('2024-06-21'), { latitude: 51.5074, longitude: -0.1278, timezone: 0 });
const winterSolstice = analyzeDaylight(new Date('2024-12-21'), { latitude: 51.5074, longitude: -0.1278, timezone: 0 });
console.log(`Summer day length: ${summerSolstice.dayLength.toFixed(1)} hours`);
console.log(`Winter day length: ${winterSolstice.dayLength.toFixed(1)} hours`);import { setEphemerisPath } from '@AstroFusion/sweph';
// Use custom ephemeris files
setEphemerisPath('/path/to/custom/ephemeris');
// Now all calculations will use the custom path
const planets = calculatePlanets(new Date());// Always work in local time for input dates
const birthDate = new Date('1990-01-15T14:30:00'); // 2:30 PM local time
const location = {
latitude: 27.7172,
longitude: 85.324,
timezone: 5.75 // Nepal Time (UTC+5:45)
};
// Library handles timezone conversion internally
const planets = calculatePlanets(birthDate, { location });
const lagna = calculateLagna(birthDate, location);import { calculatePlanets, calculateLagna } from '@AstroFusion/sweph';
try {
const planets = calculatePlanets(new Date(), {
location: { latitude: 90, longitude: 0, timezone: 0 } // Valid location
});
} catch (error) {
console.error('Calculation failed:', error.message);
// Handle error appropriately
}
// Check for null results (e.g., polar regions where sun doesn't rise/set)
const sunTimes = calculateSunTimes(new Date(), {
latitude: 80, // Near north pole
longitude: 0,
timezone: 0
});
if (!sunTimes.sunrise) {
console.log('Sun does not rise at this location today (midnight sun)');
}
if (!sunTimes.sunset) {
console.log('Sun does not set at this location today (polar day)');
}The library is written in TypeScript and provides full type definitions:
import type {
Planet,
LagnaInfo,
SunTimes,
MoonData,
GeoLocation,
CalculationOptions
} from '@AstroFusion/sweph';
// All types are exported for use in your application
function processChart(planets: Planet[], lagna: LagnaInfo) {
// Type-safe processing
}- Caching: For multiple calculations with the same date, consider caching results
- Batch Processing: Use
calculatePlanets()instead of multiplecalculateSinglePlanet()calls - Minimal Options: Only specify
locationwhen you need horizontal coordinates
// Efficient: single call for all planets
const planets = calculatePlanets(date, { ayanamsa: AYANAMSA.LAHIRI });
// Less efficient: multiple separate calls
const sun = calculateSinglePlanet(0, date);
const moon = calculateSinglePlanet(1, date);
// ... etc├── dist/ # Pre-compiled JavaScript (committed to git)
├── src/ # TypeScript source code
├── prebuilds/ # Pre-built native binaries (committed to git)
├── ephe/ # Swiss Ephemeris data files (committed to git)
├── native/ # Native addon source
└── build/ # Build configuration
Distribution files are committed to git to enable direct usage by other projects without requiring a build step.
| Platform | Architecture | Status |
|---|---|---|
| macOS | ARM64 (M1/M2) | ✅ |
| macOS | x64 (Intel) | ✅ |
| Linux | x64 | ✅ |
| Linux | ARM64 | ✅ |
| Windows | x64 | ✅ |
This library is designed to work seamlessly on Vercel's serverless environment:
- ✅ No native compilation - Pre-built binaries for linux-x64 included
- ✅ Zero configuration - Works out of the box
- ✅ Optimized for serverless - Fast cold starts with minimal bundle impact
// app/api/calculate/route.ts
import { calculatePlanets, calculateLagna } from '@af/sweph';
export async function GET() {
const planets = calculatePlanets(new Date());
return Response.json({ planets });
}import { getPlatformInfo, hasPrebuilds } from '@af/sweph';
// Check platform detection
console.log(getPlatformInfo());
// { platform: 'linux', arch: 'x64', key: 'linux-x64', isSupported: true, ... }
console.log('Has prebuilds:', hasPrebuilds());
// true-
"Failed to load Swiss Ephemeris native module"
- Ensure package version is >= 0.2.0 for Vercel compatibility
- Check that prebuilt binaries are available for your platform
- For development:
pnpm add swisseph-v2(optional fallback)
-
Vercel deployment fails with "Cannot find module swisseph.node"
- Upgrade to
@af/sweph@0.2.0or later - Clear Vercel build cache and redeploy
- Verify
node_modules/@af/sweph/prebuilds/linux-x64/swisseph.nodeexists.
- Upgrade to
-
"Ephemeris files not found"
- Ensure
ephe/directory exists with.se1files - Or set custom path:
setEphemerisPath('/path/to/ephe')
- Ensure
-
Incorrect times
- Verify timezone offset is correct (e.g., 5.5 for IST, -5 for EST)
- Ensure input dates are in local time
-
Null rise/set times
- Normal for polar regions during certain seasons
- Moon may not rise/set on some days near equator
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Make your changes with proper TypeScript types
- Add tests for new functionality
- Run the test suite:
npm test - Submit a pull request
# Install dependencies
npm install
# Build the project
npm run build
# Run tests
npm test
# Development with watch mode
npm run test:watchMIT
- Swiss Ephemeris by Astrodienst AG
- swisseph-v2 for Node.js bindings