The ultimate Swiss Ephemeris library for Vedic Astrology, supporting Node.js, Browser (WASM), and React Native with a unified API.
- β Auto-initialization - Native module loads automatically
- β TypeScript First - Complete type safety with IntelliSense
- β Vedic Astrology - Ayanamsa, Rashis, Nakshatras built-in
- β Multi-Platform - Node.js, Browser (WASM), React Native
- β
Vercel Ready - Pre-built binaries for serverless
15:
16: ##
β οΈ Vercel / Serverless Considerations 17: 18: Deploying native modules to Serverless environments involves specific challenges: 19: 20: 1. Core Problem: Compatibility between build environment (CI) and runtime environment (Lambda/Vercel). 21: 2. Common "Sloppy Code" Pitfalls: 22: * Relying on__dirnamewhich changes in bundled environments. 23: * Assumingnpm installbinaries persist (they don't). 24: * Ignoring local "Module not found" errors. 25: 26: > [!IMPORTANT] 27: > For a comprehensive guide on fixing deployment crashes, bundle size limits, and proper configuration, please read our Next.js & Vercel Deployment Guide.
# npm
npm install @af/sweph
# pnpm
pnpm add @af/sweph
# Or from GitHub
pnpm add github:astro-fusion/af-swephimport { createSweph, AYANAMSA } from '@af/sweph';
async function main() {
// Create instance (auto-initializes native module)
const sweph = await createSweph();
// Define calculation date once for consistency
const calculationDate = new Date();
// Calculate planetary positions
const planets = await sweph.calculatePlanets(calculationDate, {
ayanamsa: AYANAMSA.LAHIRI,
timezone: 5.75, // Nepal
});
console.log('Sun:', planets.find(p => p.id === 'sun'));
console.log('Moon:', planets.find(p => p.id === 'moon'));
// Calculate Lagna (Ascendant)
const lagna = await sweph.calculateLagna(
calculationDate,
{ latitude: 27.7, longitude: 85.3, timezone: 5.75 },
{ ayanamsa: AYANAMSA.LAHIRI }
);
console.log('Ascendant:', lagna.longitude, 'in', sweph.RASHIS[lagna.rasi]);
// Calculate Moon Phase
const moonPhase = await sweph.calculateMoonPhase(calculationDate);
console.log('Moon Phase:', moonPhase.phaseName, `(${Math.round(moonPhase.illumination * 100)}%)`);
}
main();Creates an auto-initialized Swiss Ephemeris instance.
const sweph = await createSweph({
ephePath: '/path/to/ephemeris', // Optional: custom ephemeris path
preWarm: true, // Optional: pre-calculate to warm cache
});// All 9 Vedic planets
const planets = await sweph.calculatePlanets(date, {
ayanamsa: AYANAMSA.LAHIRI, // Lahiri
timezone: 0, // UTC
});
// Single planet (0=Sun, 1=Moon, 2=Mars, etc.)
const sun = await sweph.calculatePlanet(0, date, { ayanamsa: AYANAMSA.LAHIRI });
// Rise, Set, Transit times
const riseSet = await sweph.calculateRiseSet(0, date, {
latitude: 27.7,
longitude: 85.3,
});const lagna = await sweph.calculateLagna(
date,
{ latitude: 27.7, longitude: 85.3 },
{ ayanamsa: AYANAMSA.LAHIRI }
);
console.log(lagna.longitude); // Ascendant in degrees
console.log(lagna.rasi); // Ascendant sign (1-12)
console.log(lagna.houses); // Array of 12 house cuspsconst date = new Date();
const location = { latitude: 27.7, longitude: 85.3 };
// Sunrise, Sunset, Solar Noon
const sunTimes = await sweph.calculateSunTimes(date, location);
// Solar Noon with altitude
const noon = await sweph.calculateSolarNoon(date, location);
// Sun path throughout the day
const path = await sweph.calculateSunPath(date, location);const date = new Date();
const location = { latitude: 27.7, longitude: 85.3 };
// Moon data (position, rise/set, phase)
const moonData = await sweph.calculateMoonData(date, location);
// Current moon phase
const phase = await sweph.calculateMoonPhase(date);
console.log(phase.phaseName); // "Waxing Crescent", "Full Moon", etc.
console.log(phase.illumination); // 0.0 to 1.0
// Next moon phases
const nextPhases = await sweph.calculateNextMoonPhases(date);
console.log('Next New Moon:', nextPhases.newMoon);
console.log('Next Full Moon:', nextPhases.fullMoon);// Get ayanamsa value
const ayanamsa = sweph.getAyanamsa(date, AYANAMSA.LAHIRI);
// Convert to Julian Day
const jd = sweph.dateToJulian(date);
// Set ephemeris path
sweph.setEphePath('/custom/path/to/ephe');import { PLANETS, AYANAMSA, RASHIS, NAKSHATRAS } from '@af/sweph';
// Planet IDs
PLANETS.SUN; // 0
PLANETS.MOON; // 1
PLANETS.MARS; // 4
PLANETS.MERCURY; // 2
PLANETS.JUPITER; // 5
PLANETS.VENUS; // 3
PLANETS.SATURN; // 6
PLANETS.RAHU; // 10
PLANETS.KETU; // 11
// Ayanamsa types
AYANAMSA.LAHIRI; // 1 (default)
AYANAMSA.KRISHNAMURTI; // 5
AYANAMSA.RAMAN; // 3
// Rashi names
RASHIS[1]; // "Aries"
RASHIS[4]; // "Cancer"
RASHIS[10]; // "Capricorn"
// Nakshatra names
NAKSHATRAS[1]; // "Ashwini"
NAKSHATRAS[14]; // "Chitra"
NAKSHATRAS[27]; // "Revati"| Package | Environment | Technology |
|---|---|---|
@af/sweph-node |
Node.js | Native C++ bindings |
@af/sweph-wasm |
Browser | WebAssembly |
@af/sweph-react-native |
Mobile | JSI/Turbo Modules |
@af/sweph-core |
All | Shared TypeScript |
@af/sweph is optimized for Vercel serverless functions. Here's the recommended setup:
# In Vercel dashboard or vercel.json
NODE_VERSION=20
SWEPH_DISABLE_CACHE=false # Enable caching for better performance// api/planets.ts
import { createSweph } from '@af/sweph';
export default async function handler(req, res) {
// Create optimized instance for serverless
const sweph = await createSweph({
serverlessMode: true,
enableCaching: true
});
const planets = await sweph.calculatePlanets(new Date());
res.status(200).json(planets);
}Important
Serverless Cold Starts: In local development, the process stays alive. In Serverless (Vercel/Lambda), every request might be a new process.
The createSweph() function above automatically awaits initialization.
However, if you use legacy functions or internal helpers, you MUST call await initializeSweph() before any calculations.
// next.config.js
module.exports = {
experimental: {
serverComponentsExternalPackages: ['@af/sweph']
},
webpack: (config) => {
// Exclude native binaries from bundling
config.externals.push({
'@af/sweph': '@af/sweph'
});
return config;
}
};For AWS Lambda, use the Node.js runtime with the provided prebuilds:
// lambda/index.js
const { createSweph } = require('@af/sweph');
let swephInstance = null;
exports.handler = async (event) => {
// Reuse instance across warm invocations
if (!swephInstance) {
swephInstance = await createSweph({
serverlessMode: true,
enableCaching: true
});
}
const result = await swephInstance.calculatePlanets(new Date());
return {
statusCode: 200,
body: JSON.stringify(result)
};
};// netlify/functions/planets.ts
import { createSweph } from '@af/sweph';
export async function handler(event) {
const sweph = await createSweph({
serverlessMode: true,
enableCaching: true
});
const planets = await sweph.calculatePlanets(new Date());
return {
statusCode: 200,
body: JSON.stringify(planets)
};
}// For memory-constrained environments
const sweph = await createSweph({
serverlessMode: true,
enableCaching: false // Disable caching to save memory
});import { withSwephInstance, createServerlessSweph } from '@af/sweph';
// Option 1: Automatic connection pooling
export default async function handler(req, res) {
const result = await withSwephInstance(async (sweph) => {
return await sweph.calculatePlanets(new Date());
});
res.json(result);
}
// Option 2: Dedicated serverless instance
let swephInstance = null;
export default async function handler(req, res) {
if (!swephInstance) {
swephInstance = await createServerlessSweph();
}
const result = await swephInstance.calculatePlanets(new Date());
res.json(result);
}// Pre-warm critical calculations
const sweph = await createSweph({
preWarm: true, // Slightly slower init, but faster first request
serverlessMode: true
});Ensure pre-built binaries are installed:
ls node_modules/@af/sweph/packages/node/prebuilds/
# Should show: linux-x64/, darwin-arm64/, etc.π For detailed Next.js and Vercel configuration, see docs/NEXTJS_VERCEL.md
Set NODE_VERSION=20 in your environment.
Disable caching to reduce memory usage:
SWEPH_DISABLE_CACHE=trueOr in code:
const sweph = await createSweph({
serverlessMode: true,
enableCaching: false
});Use dynamic imports for better tree shaking:
const { createSweph } = await import('@af/sweph');For production deployments, you can build native binaries for multiple Node.js versions:
cd packages/node
# Build ALL versions (Node 18/20/22) for ALL platforms (requires Docker)
pnpm prebuild:all
# Build single platform
pnpm prebuild:linux # Linux x64
pnpm prebuild:linux-arm64 # Linux ARM64 (Vercel/Lambda Graviton)
# Copy macOS binary from local build
pnpm copy:darwin-arm64 # macOS Apple Silicon
pnpm copy:darwin-x64 # macOS IntelThe prebuild:all script creates binaries for:
- Node.js versions: 18, 20, 22
- Platforms: linux-x64, linux-arm64, darwin-arm64, darwin-x64
π‘ Tip: Run the GitHub Actions workflow
Build Prebuildsto automatically generate all binaries.
Quick setup templates are available in the templates/ directory:
vercel-api.ts- Vercel API routes (Pages Router & App Router)aws-lambda.ts- AWS Lambda functionsnetlify-function.ts- Netlify Functionsnextjs-component.tsx- Next.js client components
# Disable caching in memory-constrained environments
SWEPH_DISABLE_CACHE=true
# Disable native module caching in serverless
SWEPH_CACHE_MODULE=false
# Set Node.js version for Vercel
NODE_VERSION=20const sweph = await createSweph({
ephePath: '/custom/path/to/ephemeris'
});The library includes pre-built binaries for:
linux-x64(Vercel, AWS Lambda, most Linux servers)linux-arm64(AWS Lambda Graviton, ARM64 Linux)darwin-arm64(macOS M1/M2/M3)darwin-x64(macOS Intel)win32-x64(Windows x64)
git clone https://github.com/astro-fusion/af-sweph
cd af-sweph
pnpm install
pnpm -r build
pnpm -r testMIT
- Swiss Ephemeris by Astrodienst AG