Developer examples

Start with a working result.

One small JavaScript project contains a local natal calculator, a personalized transit snapshot, and a publisher sky iframe. No framework, account, API key, wallet, or private environment is required.

Starter 0.1.0-rc.4 includes @zodiacs/engine@0.1.1-rc.3. Unpublished npm release candidate; review and publication gates remain open. This standalone project's engine pin is separate from the site's application; the hosted iframe uses its own deployment.

Check supported inputs, runtimes, and numerical limits before adapting the examples.

Set up once

Use Node.js 22 and npm, plus a POSIX shell with curl and tar (macOS, Linux, or WSL). Start in a directory where zodiacs-starter does not exist. The block runs in a subshell and stops if any step fails.

Download starter 0.1.0-rc.4 (.tgz) or use the commands below. They fetch the exact public archive and verify SHA-256 before extraction. Installation downloads pinned public dependencies; calculation stays local.

( set -eu
mkdir zodiacs-starter
cd zodiacs-starter
curl --disable --fail --silent --show-error --proto '=https' --max-time 30 \
  'https://raw.githubusercontent.com/ZodiacsOfficial/site/fd1f1332ee3abeb88f6159bcb5654ffe64390be4/public/examples/zodiacs-platform-starter-0.1.0-rc.4.tgz' -o 'zodiacs-platform-starter-0.1.0-rc.4.tgz'
node --input-type=module <<'JS'
import { readFileSync } from 'node:fs';
import { createHash } from 'node:crypto';
const bytes = readFileSync('zodiacs-platform-starter-0.1.0-rc.4.tgz');
const expected = '1b413959aff1263b6ab0c12c6426b1a8edd50eb2618591f989a5e5b29f79e19b';
if (createHash('sha256').update(bytes).digest('hex') !== expected) {
  throw new Error('Archive checksum mismatch. Do not extract or install.');
}
console.log('Archive verified');
JS
tar -xzf 'zodiacs-platform-starter-0.1.0-rc.4.tgz'
cd package
npm ci --ignore-scripts --no-audit --no-fund
npm test
npm run build
npm start
)

Open http://127.0.0.1:4178/. The test step must finish with no failing tests. Stop the local server with Ctrl+C. If port 4178 is occupied, run cd zodiacs-starter/package, then node scripts/server.mjs 4179 and use its printed address. This server is a local demo, with no request logging or chart endpoint.

The archive includes its full README, source, and failure cases, locked dependencies, candidate identity, and dependency notices. It uses the public engine entry point and no workspace-only imports.

1. Calculate a natal chart locally

Open /natal.html on the local server and select Calculate locally. The synthetic default describes nobody: June 15, 1990 at 13:30 UTC, latitude 51.5074°, longitude −0.1278°, requesting Placidus houses.

Success: 12 bodies, an ascendant near 191.239748° Libra, and Placidus houses. Requested and actual house systems both read placidus, and the receipt carries no flags — the system you asked for is the one you got.

Advanced: change the latitude to 78.2232°, the longitude to 15.6267° and the instant to 2001-12-21T09:00:00Z. Above 66° absolute latitude Placidus cannot be computed, so the engine falls back to whole sign and records polar-fallback with the requested and actual systems still distinct.

Try a failure: enter 2001-02-29T09:00:00Z. The impossible date must show an error and clear the previous result.

Unknown time uses 12:00 UTC on the entered date, carries no-time, and omits angles and houses. It does not infer local noon. Resolve actual birthplace timezone rules before supplying a known instant: for a local wall time and an IANA zone, use resolveBirth from @zodiacs/engine/geo (see local-time resolution) rather than converting by hand; the example’s Z instants are already resolved.

The natal example also exports and imports one draft natal receipt locally. A full export includes birth details. Imported records display their stored result as unverified claims; they do not refill the form, recalculate, upload data, or change a supplied reference time. Re-export retains the requested and actual house systems and the original receipt assumptions.

Use the redacted diagnostic for a smaller report that omits dates, coordinates, positions, imported metadata, and stable hashes. Redaction does not guarantee anonymity. Unsupported versions, required features, duplicate JSON keys, and oversized files produce a safe error.

2. Inspect a personalized transit snapshot

Open /transits.html and calculate the synthetic default at 2026-09-07T12:00:00Z. This is an explicitly dated example, not a live “today” result.

Success: 12 moving positions and major moving-to-natal body aspects, with the entered offsets, normalized instants, engine version, artifact hash, conventions, and requested/actual natal houses. Change the transit date to see different positions.

Try a failure: remove the transit instant’s Z without adding an offset. An unresolved local time must be rejected. These are snapshot aspects, not exact-pass times or natal ASC/MC contacts.

3. Embed a publisher sky widget

Open /widget.html, choose Dark or Light and a six-digit accent such as #7B6DA8, then select Load widget. No Zodiacs.org request occurs before that click.

Success: the hosted sky card fits the page, its displayed date is visible, and its Powered by Zodiacs.org credit remains reachable. Check the date before presenting it as current. The frame may adjust the accent for readable contrast.

Try a failure: enter red as the accent; it must fail validation. Block the external frame to check that Open the sky on Zodiacs.org remains usable. A frame load event alone does not prove current content.

The hosted request exposes ordinary connection information and the referring origin. This page collects no birth details. Keep the title, official sandbox, referrer policy, responsive sizing, fallback, and attribution when adapting src/widget.mjs. Use the existing widget builder for Moon and mini-chart variants.

Return to developer tools for shared-sky JSON, or use the support matrix and discrepancy-reporting guidance. Automated internal checks are recorded in the repository; unfamiliar-developer walkthroughs and external adoption remain unmeasured.