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

horizon-sky

v0.2.0

Published

Physics-based sky gradient renderer. Given a date/time and coordinates, returns a CSS gradient representing the current sky.

Readme

horizon-sky

Part of horizon — physics-based sky gradient renderer for the web.

Physics-based sky gradient renderer. Given a date/time and geographic coordinates, returns a CSS linear-gradient that accurately represents the current sky — including sunrise, daytime, sunset, and night.

Powered by suncalc for sun position calculations. Works in any environment that supports the Fetch API (browsers, Node.js 18+, Deno, Bun, Cloudflare Workers, etc.) for optional sunrise/sunset correction.

Installation

npm install horizon-sky

Quick Start

import { computeSky } from "horizon-sky";

const sky = await computeSky({
  date: new Date(),
  latitude: 35.6895,
  longitude: 139.6917,
});

document.body.style.background = sky.gradient;

API

computeSky(options) — static mode

Compute the sky for a specific date and location. Returns a Promise<SkyResult>.

import { computeSky } from "horizon-sky";

const sky = await computeSky({
  date: new Date("2026-06-21T06:00:00+09:00"),
  latitude: 35.6895,
  longitude: 139.6917,
});

Options:

| Field | Type | Required | Description | |---|---|---|---| | date | Date | ✅ | The date and time to render the sky for | | latitude | number | ✅ | Latitude in degrees (-90 to 90) | | longitude | number | ✅ | Longitude in degrees (-180 to 180) | | sunTimes | SunTimesOption | — | Enable sunrise/sunset altitude correction (see below) | | bortle | number | — | Bortle scale (1-9) for light pollution correction |

SunTimesOption:

// Disabled (default) — no correction applied
sunTimes: false

// Enabled with a custom provider
sunTimes: { provider: myCustomProvider }

Returns: SkyResult

interface SkyResult {
  gradient: string;
  topColor: string;
  bottomColor: string;
  altitude: number;
  azimuth: number;
  correctedAltitude?: number;
  sunrise?: Date;
  sunset?: Date;
}

realtimeSky(options) — realtime mode

An AsyncGenerator that yields a fresh SkyResult at a regular interval using the current system time. Stops when the provided AbortSignal is aborted.

import { realtimeSky } from "horizon-sky";

const controller = new AbortController();

for await (const sky of realtimeSky({
  latitude: 35.6895,
  longitude: 139.6917,
  interval: 60_000,
  signal: controller.signal,
  sunTimes: { provider: myCustomProvider },
})) {
  document.body.style.background = sky.gradient;
}

To stop the loop:

controller.abort();

Options: All fields from ComputeSkyOptions except date (always uses new Date()), plus:

| Field | Type | Default | Description | |---|---|---|---| | interval | number | 60000 | Milliseconds between updates | | signal | AbortSignal | — | Cancellation signal |


Sunrise/Sunset Correction

By default, computeSky uses the raw solar altitude from orbital mechanics. This is accurate but may produce slightly off colors at exactly sunrise/sunset since the horizon reference differs from the physical model.

When a custom provider is provided via sunTimes: { provider }, the library fetches the actual sunrise/sunset times for the given location and date, then corrects the altitude so the gradient transitions precisely at those moments.

Custom Provider

You must provide a provider function to enable sunrise/sunset correction. This gives you full control over the data source.

import { computeSky } from "horizon-sky";
import type { SunTimesProvider } from "horizon-sky";

const myProvider: SunTimesProvider = async ({ latitude, longitude, date }) => {
  const res = await fetch(`https://my-api.example.com/sun?lat=${latitude}&lng=${longitude}&date=${date}`);
  const data = await res.json();
  return {
    sunrise: data.sunrise_utc,
    sunset: data.sunset_utc,
  };
};

const sky = await computeSky({
  date: new Date(),
  latitude: 35.6895,
  longitude: 139.6917,
  sunTimes: { provider: myProvider },
});

Provider Interface

type SunTimesProvider = (params: SunTimesRequest) => Promise<SunTimesResponse>;

interface SunTimesRequest {
  latitude: number;
  longitude: number;
  date: string;
}

interface SunTimesResponse {
  sunrise: Date | string;
  sunset: Date | string;
}

Important: sunrise and sunset must represent times in UTC. If your API returns local times, convert them before returning.

Example: Using a self-hosted API

const selfHostedProvider: SunTimesProvider = async ({ latitude, longitude, date }) => {
  const res = await fetch(`/api/sun-times?lat=${latitude}&lng=${longitude}&date=${date}`);
  if (!res.ok) throw new Error(`API error: ${res.status}`);
  const { sunrise_utc, sunset_utc } = await res.json();
  return { sunrise: sunrise_utc, sunset: sunset_utc };
};

Your API endpoint should return a JSON response in this shape:

{
  "sunrise_utc": "2026-06-21T20:14:00+00:00",
  "sunset_utc": "2026-06-22T10:01:00+00:00"
}

The field names are flexible — only the SunTimesResponse shape returned by your provider function matters.


Low-level API

The internal rendering and calculation functions are also exported for advanced use.

import { renderGradient, getSunPosition } from "horizon-sky";

const pos = getSunPosition(new Date(), 35.6895, 139.6917);
console.log(pos.altitude, pos.azimuth);

const { gradient, topColor, bottomColor } = renderGradient(pos.altitude);
document.body.style.background = gradient;

License

MIT. Physical model and parameters derived from: