npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mysticapi

v0.1.0

Published

Official isomorphic TypeScript/JavaScript client for MysticAPI — deterministic Human Design–compatible bodygraphs, personal sky charts, and ephemeris. Zero dependencies; runs on Node, Bun, browsers, and Cloudflare Workers.

Readme

mysticapi

Official isomorphic client for MysticAPI — a metered engine API for deterministic, Human Design–compatible bodygraphs, personal sky charts, and ephemeris. Same input always returns the same output (JPL-validated pure-JS ephemeris; no generative output).

  • Zero dependencies. Uses the runtime's global fetch.
  • Runs everywhere: Node 18+, Bun, browsers, and Cloudflare Workers.
  • Fully typed, including a typed error that surfaces the JSON error body, HTTP status, and the 429 Retry-After.
npm install mysticapi

Get a key (30 seconds, no card)

Free tier is 50 calls/month, no card. The key is emailed to you.

import { MysticApi } from 'mysticapi';

await MysticApi.getFreeKey('[email protected]'); // → check your inbox for mk_live_...

Paid tiers (Maker $19 / Pro $49 / Scale $149 per month, flat — never credits) are self-serve Stripe links listed at https://mysticapi.com/llms.txt; your key is emailed within a minute of checkout.

Quick start

import { MysticApi } from 'mysticapi';

const mystic = new MysticApi({ apiKey: process.env.MYSTIC_API_KEY! });
// baseUrl defaults to https://mysticapi.com; pass { baseUrl } to override.

1. Today's sky — skyToday()

GET /v1/sky/today — active retrogrades, moon phase, geocentric positions for 13 bodies (zodiac + Energy Blueprint gate/line), and a 30-day forward scan of stations and new/full moons.

const sky = await mystic.skyToday();

console.log(sky.date);                 // "2026-07-07"
console.log(sky.moon.phaseName);       // "Waxing Gibbous"
console.log(sky.moon.illumination);    // 0.82
console.log(sky.retrogrades.active);   // [{ planet: "mercury", label: "Mercury Retrograde" }]
console.log(sky.positions.sun.zodiac); // { sign: "Cancer", degree: 15.2 }
console.log(sky.positions.sun.gate);   // { gate: 4, line: 3 }

Response shape:

{
  "date": "2026-07-07",
  "moon": { "phaseName": "Waxing Gibbous", "illumination": 0.82, "nextFullMoon": { "date": "2026-07-10", "type": "full_moon", "daysAway": 3 } },
  "retrogrades": { "active": [{ "planet": "mercury", "label": "Mercury Retrograde" }], "upcomingStations": [ /* SkyEvent[] */ ] },
  "positions": { "sun": { "longitude": 105.2, "zodiac": { "sign": "Cancer", "degree": 15.2 }, "gate": { "gate": 4, "line": 3 }, "retrograde": false } /* …13 bodies */ },
  "upcoming": [ /* SkyEvent[] — next 30 days */ ]
}

2. Bodygraph — bodygraph(birth)

POST /v1/bodygraph — a birth instant in UTC → the full Energy Blueprint (Human Design) chart JSON plus a rendered body-graph SVG. No latitude/longitude needed; the body-graph is location-independent.

const { chart, svg } = await mystic.bodygraph({
  year: 1979, month: 8, day: 5, hour: 22, minute: 51, // UTC — convert local time first
});

console.log(chart.chart?.type);      // "Manifesting Generator"
console.log(chart.chart?.authority); // "Sacral"
console.log(chart.chart?.profile);   // "3/5"
// `svg` is a complete <svg>…</svg> string — write it to a file or inline it.

Response shape:

{
  "chart": {
    "birth": { "year": 1979, "month": 8, "day": 5, "jdn": 2444091.45 },
    "design": { /* the 88°-solar-arc design moment */ },
    "personalityGates": { "sun": { "gate": 4, "line": 3 } /* … */ },
    "designGates": { "sun": { "gate": 49, "line": 1 } /* … */ },
    "chart": { "type": "Manifesting Generator", "authority": "Sacral", "strategy": "…", "profile": "3/5", "definition": "…", "cross": "…", "channels": [ /* … */ ], "centers": { /* … */ } }
  },
  "svg": "<svg …>…</svg>"
}

3. Personal sky — skyPersonal(birth)

POST /v1/sky/personal — a birth instant → the natal sky rendered as an SVG string (image/svg+xml). Deterministic per birth. Retrogrades render ; fixed stars conjunct natal points light up.

const svg = await mystic.skyPersonal(
  { year: 1990, month: 1, day: 2, hour: 3, minute: 4 },
  { animate: false }, // optional — request a static render
);
// svg === "<svg xmlns=\"http://www.w3.org/2000/svg\" …>…</svg>"

There is also skyPersonalGet(birth, opts?) if you want the GET query-param form (handy for shareable URLs).

Error handling

Every non-2xx response throws a typed MysticApiError. Network/transport failures throw with status: 0, code: 'network_error'.

import { MysticApi, MysticApiError } from 'mysticapi';

try {
  await mystic.skyToday();
} catch (err) {
  if (err instanceof MysticApiError) {
    err.status;           // 401 | 402 | 429 | 400 | 0 | …
    err.code;             // "missing_api_key" | "quota_exceeded" | "http_402" | …
    err.message;          // human-readable message from the API
    err.docs;             // documentation URL, when provided
    err.retryAfter;       // number of seconds (set on 429 when Retry-After is present)

    if (err.isRateLimited) await sleep(err.retryAfter! * 1000); // back off, then retry
    if (err.isUnauthorized) { /* bad or missing key */ }
    if (err.isPaymentRequired) { /* 402 — supply a key or an x402 payment */ }
  }
}

Cloudflare Workers

Works out of the box — the client uses global fetch. Read the key from a secret binding:

export default {
  async fetch(_req: Request, env: { MYSTIC_API_KEY: string }): Promise<Response> {
    const mystic = new MysticApi({ apiKey: env.MYSTIC_API_KEY });
    const sky = await mystic.skyToday();
    return Response.json(sky);
  },
};

You can also inject a custom fetch via new MysticApi({ apiKey, fetch }).

API

| Method | HTTP | Returns | | --- | --- | --- | | new MysticApi({ apiKey, baseUrl?, fetch? }) | — | client | | skyToday() | GET /v1/sky/today | Promise<SkyToday> | | bodygraph(birth) | POST /v1/bodygraph | Promise<BodygraphResult> ({ chart, svg }) | | skyPersonal(birth, opts?) | POST /v1/sky/personal | Promise<string> (SVG) | | skyPersonalGet(birth, opts?) | GET /v1/sky/personal | Promise<string> (SVG) | | MysticApi.getFreeKey(email, opts?) | POST /v1/keys/free | Promise<FreeKeyResponse> |

birth is { year, month, day, hour, minute, second? } in UTC. All types are exported. The machine-readable contract lives at https://mysticapi.com/.well-known/openapi.json.

License

MIT © Latimer Woods Tech