Getting Started

Computing Charts

engine.chart() accepts the calendar fields in UT, a latitude, a longitude (east positive), and either a house-system name or an options object.

Calendar fields, not a Julian Day

The first six arguments are calendar fields in UT, in order: year, month, day, hour, minute, second. They are followed by latitude and east-positive longitude.

signature.ts
//                         y     mo  d   h   mi  s   lat     lonEast
const chart = engine.chart(1990, 6, 10, 14, 30, 0, 27.95, -82.46, "placidus");

Passing a Julian Day in the year slot is a common mistake: the engine reads it as a calendar year, builds an instant far outside the fitted range, and the first body to check its range throws RangeError: jd ... outside fitted range.

If you already hold a Julian Day in UT, use engine.chartAt(): the same chart, no calendar round-trip. (engine.chart() is just chartAt() with the calendar conversion in front.)

chart-at.ts
const chart = engine.chartAt(jdUt, 27.95, -82.46, "placidus");

It takes the same third argument as chart() (a house-system name or a full ChartOptions object) and returns an identical Chart.

For a single body at a Julian Day, engine.position() and engine.longitude() take a JD directly, so no conversion is needed:

at-jd.ts
engine.longitude("sun", jdUt);                        // degrees
engine.position("mars", jdUt, { zodiac: "tropical" }); // full Position

Options

options.ts
const chart = engine.chart(
1990, 6, 10, 14, 30, 0,
27.95, -82.46,
{
  houseSystem: "koch",
  zodiac: "sidereal:lahiri",
  bodies: ["mean_lilith"], // extra bodies beyond the core set
},
);

The chart object

shape.ts
chart.bodies.sun.lon;        // ecliptic longitude, degrees
chart.bodies.sun.speed;      // degrees per day
chart.bodies.sun.retrograde; // boolean
chart.bodies.sun.sign;       // "Gemini"
chart.bodies.sun.ra;         // right ascension (true equinox of date)

chart.angles.asc;            // ascendant
chart.angles.mc;             // midheaven
chart.cusps;                 // twelve house cusps, degrees
chart.aspects;               // [{ a, b, aspect, orb, phase, strength }, ...]
                           //   phase: applying | separating | exact
                           //   strength: 1 exact ... 0 at the orb limit
chart.houseSystem;           // the system actually used
chart.houseSystemRequested;  // what you asked for (differs on polar fallback)
123456789101112ACMCDCIC19°27'13°17'27°50'13°01'7°30'14°50'24°18'℞8°21'℞13°50'℞15°30'℞15°34'8°07'℞
sun19°27' Geminih11
moon13°17' Capricornh6
mercury27°50' Taurush10
venus13°01' Taurush10
mars 7°30' Ariesh9
jupiter14°50' Cancerh12
saturn24°18' Capricornh6
uranus 8°21' Capricornh5
neptune13°50' Capricornh6
pluto15°30' Scorpioh4
chiron15°34' Cancerh12
mean_node 9°57' Aquariush6
true_node 8°07' Aquariush6
ASC10°54' Leo
MC 6°02' Taurus
The sample chart from the code above: 10 Jun 1990, 14:30 UT, Tampa, FL (27.95°, -82.46° east-positive), placidus. Rendered server-side from the same Chart object with <ChartWheel chart={chart} /> from caelus-wheel.

Local birth time to UT

The engine works in UT. Convert a local civil time with caelus-birth, which resolves the IANA zone from the location and applies historical tzdb rules.

birth.ts
import { toUT } from "caelus-birth";

const t = toUT({
year: 1990, month: 6, day: 10,
hour: 14, minute: 30,
lat: 27.95, lon: -82.46,
});

const chart = engine.chart(
t.year, t.month, t.day, t.hour, t.minute, 0,
27.95, -82.46, "placidus",
);

Edge and REST

The same engine runs on edge runtimes. The site exposes a demo endpoint: GET /api/chart returns a full chart as JSON.

Ship a chart in your app

Quickstart →