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

orihon

v2.0.1

Published

Orihon Maps — a free, open-source browser map engine. Apache 2.0. Use it anywhere.

Readme

Orihon Maps

A fast, typed browser map engine with a small path from first map to large-scale GIS.

npm downloads CI full size license TypeScript

Orihon Maps is a free, open-source browser mapping library. Start with a map-centric API for common work, move to explicit layers when you need more control, and opt into GPU rendering and large-data tools only when the application needs them.

Apache 2.0. No engine key. No paid runtime license.

The product is Orihon Maps; the package is orihon. Every install, import and global uses the short identifier — npm i orihon, from "orihon", globalThis.Orihon — and so does this document wherever it is talking about code rather than about the product.

Start here

Starting from an empty folder? One command writes a project that already draws a map:

npm create orihon-app my-map
cd my-map
npm install
npm run dev

Templates are vanilla and react, both on Vite; npm create orihon-app my-map -- --template react --yes skips the prompts. The generated project already contains the stylesheet import, a container with a height, an attribution and one working map, so the first thing you see is a map rather than a setup checklist.

Already have a Vite, React, Vue or other ESM application?

npm install orihon

Then create a map with orihon/easy:

import { createMap } from "orihon/easy";
import "orihon/orihon.css";

const map = createMap("map", {
  center: { lat: 52.52, lng: 13.405 },
  zoom: 12,
  basemap: {
    url: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
    attribution: "© OpenStreetMap contributors"
  }
});

map.addMarker({
  position: { lat: 52.52, lng: 13.405 },
  appearance: { shape: "pin", color: "#2563eb" },
  popup: "Berlin"
});

Your page needs a container with a real size:

<div id="map"></div>

<style>
  html,
  body {
    margin: 0;
    height: 100%;
  }

  #map {
    height: 100vh;
    min-height: 360px;
  }
</style>

That is enough for a pannable, zoomable OpenStreetMap basemap with a marker and popup.

A <div> has no height of its own, which is the most common reason a first map looks broken: tiles are requested, layers exist, nothing is painted. Orihon says so in the console instead of leaving you to guess — see Troubleshooting.

Add common map objects

The Easy API is map-centric and object-first. Each operation takes one options object, so the fields are visible in autocomplete and there are no positional Easy overloads to memorize.

map.addPolyline({
  points: [
    { lat: 52.51, lng: 13.37 },
    { lat: 52.53, lng: 13.41 },
    { lat: 52.50, lng: 13.44 }
  ],
  style: {
    stroke: "#2563eb",
    strokeWidth: 4
  }
});

map.addPolygon({
  rings: [
    { lat: 52.50, lng: 13.38 },
    { lat: 52.54, lng: 13.39 },
    { lat: 52.53, lng: 13.45 },
    { lat: 52.50, lng: 13.38 }
  ],
  style: {
    fill: "#2563eb",
    fillOpacity: 0.2,
    stroke: "#2563eb"
  },
  popup: "District"
});

const places = map.addGeoJSON({
  data: {
    type: "FeatureCollection",
    features: [
      {
        type: "Feature",
        properties: { name: "Alexanderplatz" },
        geometry: {
          type: "Point",
          coordinates: [13.4132, 52.5219]
        }
      }
    ]
  }
});

map.fitBounds(places.getBounds());

Easy currently covers the common first-map operations:

  • addMarker({ position, ... })
  • addPolyline({ points, ... })
  • addPolygon({ rings, ... })
  • addGeoJSON({ data, ... })
  • addTileLayer({ url, ... })
  • setBasemap(...) / getBasemap()

The objects returned by those methods are normal Orihon layers, not wrappers. You can use their events, popup APIs, setters and normal remove() lifecycle immediately.

See the Easy API guide for the complete contract.

When you need more control

You do not need to choose the whole architecture before drawing the first map.

Start with orihon/easy. Move to the Layer API only where the application needs explicit composition:

import { polygon } from "orihon/standard";

const area = polygon(
  [
    { lat: 52.50, lng: 13.38 },
    { lat: 52.54, lng: 13.39 },
    { lat: 52.53, lng: 13.45 },
    { lat: 52.50, lng: 13.38 }
  ],
  {
    fill: "#0f766e",
    fillOpacity: 0.2,
    stroke: "#0f766e"
  }
).addTo(map);

area.bindPopup("Custom layer");

The two public sentence forms are intentional:

| API | Sentence | Use it for | | --- | --- | --- | | Easy | map.addMarker({ ... }) | First maps and common application work | | Layer API | marker(position).addTo(map) | Explicit composition and the full layer surface |

There is no third generic map.add({ type, ... }) dialect.

Coordinates without guessing

Application-facing geographic coordinates use named values:

const berlin = { lat: 52.52, lng: 13.405 };

When converting from another convention, make the order explicit:

import {
  latLng,
  lngLat,
  fromGeoJSONPosition,
  toGeoJSONPosition
} from "orihon/standard";

const moscow = latLng(55.751244, 37.618423); // latitude, longitude
const berlin = lngLat(13.405, 52.52);        // longitude, latitude

const point = fromGeoJSONPosition([13.405, 52.52]);
const geojsonPosition = toGeoJSONPosition(point); // [13.405, 52.52]

A list names its order once instead of repeating lat and lng on every point:

import { latLngs, lngLats, fromGeoJSONPositions, polyline } from "orihon/standard";

polyline(latLngs([[52.51, 13.37], [52.53, 13.41], [52.50, 13.44]]));
polyline(lngLats(maplibreCoordinates));
polyline(fromGeoJSONPositions(feature.geometry.coordinates));

latLngs() and lngLats() also read a flat run of numbers — latLngs([52.51, 13.37, 52.53, 13.41]), or a Float64Array straight from a worker, which skips building one pair object per point. An odd length throws instead of shifting every later point by one place.

GeoJSON keeps the standard [longitude, latitude] order. Normal Orihon geographic APIs prefer { lat, lng } so a bare numeric tuple cannot silently swap the two.

Choose a package tier later

Package size and API difficulty are separate concerns. The Easy API is a beginner-oriented adapter over Standard; Core, Standard and Advanced describe capability and bundle size.

| Tier | Import | What it includes | | --- | --- | --- | | Core | orihon/core | Map, camera, events, geometry, DOM raster tiles and grid primitives | | Standard | orihon/standard | Core + markers, SVG/canvas vectors, GeoJSON, popups, overlays, controls and locales | | Advanced | orihon | Standard + WebGL/WebGPU, MVT, heat, ObjectManager, workers, routing, traffic and offline tooling |

A normal application can stay on Standard indefinitely. Importing the Advanced root is for cases where dataset size, rendering load or infrastructure features justify it.

GPU rendering is explicit:

import { tileLayer } from "orihon";

tileLayer("/tiles/{z}/{x}/{y}.png");
// DOM renderer — stable default.

tileLayer("/tiles/{z}/{x}/{y}.png", { renderer: "auto" });
// Prefer WebGPU, then WebGL, then DOM.

tileLayer("/tiles/{z}/{x}/{y}.png", { renderer: "webgl" });
// WebGL is required; unsupported capability throws instead of silently changing renderer.

Optional product-specific entry points stay separate from those tiers:

  • orihon/easy — map-centric first-map API
  • orihon/source — reactive FeatureSource
  • orihon/react — React bindings
  • orihon/draw — drawing and editing
  • orihon/controls — fullscreen, measure, minimap and graticule
  • orihon/geo — additional geographic helpers
  • orihon/popup-content — declarative rich popup content
  • orihon/pmtiles, orihon/mvt, orihon/mlt, orihon/mvt-wasm — packed tile formats
  • orihon/webgpu — explicit WebGPU integration

Common next steps

Reactive data

If the same data should drive several renderers, use FeatureSource instead of rebuilding application state around a particular layer:

import { featureSource } from "orihon/source";
import { geoJSON } from "orihon/standard";

const source = featureSource();
const layer = geoJSON(source).addTo(map);

source.add({
  type: "Feature",
  id: "station-1",
  properties: { name: "Central Station" },
  geometry: {
    type: "Point",
    coordinates: [13.3694, 52.5251]
  }
});

One source can feed GeoJSON, labels and high-volume rendering. See FeatureSource.

Large datasets

The Advanced entry includes ObjectManager, GPU point/path rendering, heatmaps, vector tiles, workers and performance diagnostics. ObjectManager is intended for tens of thousands to millions of application objects without one DOM marker per object.

For large cooperative imports:

import { objectManager } from "orihon";

const manager = objectManager({
  clusterize: true,
  clusterRenderer: "auto",
  layoutWorker: "auto"
}).addTo(map);

await manager.addAsync(objects, {
  chunkSize: 10_000,
  yieldMode: "task",
  signal: abortController.signal
});

The detailed data, styling, clustering, heatmap and lifecycle contracts live in the API reference instead of this README.

React

React bindings are published from orihon/react and use the same map/layer concepts. React and React DOM are optional peer dependencies, so non-React applications do not pull them in.

See the API reference and the runnable example under examples/react.

Drawing and controls

Drawing/editing is opt-in through orihon/draw. Additional UI such as fullscreen, measurement, minimap and graticule lives under orihon/controls.

Keeping these entry points separate means a normal map does not pay for product-specific UI it never uses.

TypeScript and API contracts

Orihon is written in strict TypeScript and publishes generated declarations for every public entry point.

The public API follows a small set of rules:

  • options objects are preferred when several independent values would otherwise become positional arguments;
  • geographic units are visible in names such as durationMs, radiusMeters and radiusPixels;
  • addTo(map) attaches reusable layers and controls; remove() detaches them;
  • resource-owning services use terminal, idempotent destroy();
  • cancellation uses AbortSignal / AbortError;
  • calls made after terminal destruction use DestroyedError rather than pretending the operation was cancelled;
  • live map state is read-only from the public surface and changes through explicit methods;
  • built-in events are typed by event name and payload.

The complete conventions are documented in API-DESIGN.md.

Performance

Orihon keeps rendering cost proportional to the job instead of forcing every application through the heaviest pipeline.

Core and Standard stay CPU/DOM. Advanced adds GPU backends for the workloads where they pay off: large point sets, heat, GPU raster tiles and large vector paths.

The repository includes two reproducible browser demos:

Run the benchmarks rather than relying on a headline number; browser, GPU, dataset shape and interaction pattern all matter.

Size

Nothing Orihon ships crosses 150 KiB gzip. npm run size fails the build when a published artifact exceeds its budget and checks this table against dist/release-manifest.json.

| Artifact | Budget | What it carries | | --- | ---: | --- | | orihon.geo.esm.js | ≤ 2 KiB gzip | Geometry helpers only | | orihon.popup-content.esm.js | ≤ 5 KiB gzip | Popup content blocks | | orihon.controls.esm.js | ≤ 8 KiB gzip | Optional controls | | orihon.draw.esm.js | ≤ 12 KiB gzip | Draw/edit tools | | orihon.core.esm.js | ≤ 18 KiB gzip | Map, events, geometry, DOM tiles | | orihon.standard.esm.js | ≤ 38 KiB gzip | Everyday GIS, no WebGL | | orihon.esm.js | ≤ 132 KiB gzip | Advanced: Standard + GPU, MVT, ObjectManager and WASM | | orihon.react.esm.js | ≤ 118 KiB gzip | React bindings over the Advanced surface | | orihon.global.js | ≤ 149 KiB gzip | Standalone script-tag build |

Prefer the smallest entry point that contains the capability you need. Exact raw and gzip sizes for the current build are written to dist/release-manifest.json.

Browser builds

npm run build emits modular ESM, generated TypeScript declarations, minified single-file ESM bundles, CSS and a standalone globalThis.Orihon build.

Main artifacts include:

  • dist/core.js
  • dist/standard.js
  • dist/index.js
  • dist/orihon.core.esm.js
  • dist/orihon.standard.esm.js
  • dist/orihon.esm.js
  • dist/orihon.global.js
  • dist/orihon.css

If you self-host the standalone files, a script-tag page can use:

<link rel="stylesheet" href="/vendor/orihon/orihon.css" />
<script src="/vendor/orihon/orihon.global.js"></script>
<script>
  const map = Orihon.createMap("map", {
    center: { lat: 52.52, lng: 13.405 },
    zoom: 12
  });
</script>

The global build exposes globalThis.Orihon and globalThis.OrihonReady.

Documentation

Start with the guide that matches what you are doing:

Development

Repository development and release tooling requires Node.js 22 or newer. .node-version pins the tested LTS version.

npm install
npm run build
npm run check

Useful commands:

npm run typecheck
npm test
npm run test:browser
npm run test:e2e
npm run size
npm run docs:build
npm run docs:check
npm run demo:docs
npm run demo:showcase
npm run demo:bench

npm run check runs the type checks, unit tests, size budgets and documentation consistency checks used before publishing.

Design goals

  • Make the first map require very little API knowledge.
  • Keep one predictable grammar inside each API level.
  • Make coordinates, units, ownership and lifecycle explicit.
  • Keep Core, Standard and Advanced as capability tiers with enforced size budgets.
  • Let applications move from DOM/SVG/canvas to GPU rendering without replacing their map model.
  • Keep I/O-heavy services provider-based so applications can supply local, commercial or test implementations.
  • Prefer browser primitives and small data structures over mandatory heavyweight runtime stacks.

Brand assets

Production-ready SVG/PNG logos, favicons and design tokens are published under orihon/brand/*.

License

Orihon is licensed under the Apache License 2.0. Use it in personal, educational and commercial projects without a separate paid engine license.

See LICENSE, LICENSE-NOTICE.md and the License FAQ.

Copyright 2026 whahe.