h3-js

Uber's H3 hexagonal geospatial indexing system, compiled to pure JavaScript for Node and the browser.

Library
npm
v4.5.0
1,079stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
80/100Excellent
Development Activity72
Maintenance72
Community76
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
84/100Excellent
Architecture85
Code Quality88
Innovation84
Learning Curve78

h3-js is the official JavaScript port of Uber’s H3 library, a hierarchical hexagon-based geospatial indexing system originally built for ride-sharing analytics and now used broadly for spatial aggregation, visualization, and geofencing. The core C library is transpiled via Emscripten, so h3-js exposes the exact same operations as the native H3 API — converting coordinates to hexagon cells, walking hexagon grids, computing cell hierarchies, and generating hexagon coverage for polygons — with full parity and no native bindings to compile.

Because every H3 index is just a 64-bit hex string, the library slots cleanly into existing JSON pipelines, GeoJSON tooling, and databases without custom types. It ships as ES modules, CommonJS, and a UMD bundle for direct browser use, with first-class TypeScript definitions generated straight from the source.

What You Get

  • Pure-JavaScript build of the H3 core library (via Emscripten) with full API parity — no native module compilation required
  • Coordinate conversion functions (latLngToCell, cellToLatLng, cellToBoundary) for mapping lat/lng points to hexagon cells and back
  • Grid traversal and hierarchy operations (gridDisk, gridRing, cellToParent, cellToChildren, compactCells) for spatial aggregation and multi-resolution analysis
  • Polygon coverage utilities (polygonToCells, cellsToMultiPolygon) that convert GeoJSON-style polygons into hexagon sets and back into outlines
  • TypeScript declaration files generated directly from the source, plus ES module, CommonJS, and UMD browser bundles
  • A documented legacy compatibility layer for codebases migrating from the H3 v3 API to v4

Common Use Cases

  • Aggregating ride, delivery, or event data into uniform hexagon cells for heatmaps and demand analysis
  • Building geofences by converting service-area polygons into sets of H3 cells for fast point-in-region checks
  • Powering hexbin map visualizations (e.g. deck.gl H3HexagonLayer) with consistent, multi-resolution spatial bins
  • Deduplicating or clustering nearby geographic points by snapping them to a shared-resolution H3 cell

Under The Hood

Architecture - h3-js is a thin JavaScript binding layer over a C library compiled to WebAssembly/asm.js via Emscripten. lib/bindings.js declares the full table of native H3 functions and their C signatures, which lib/h3core.js wires up at load time using C.cwrap(...) against the compiled module imported from ../out/libh3. Each exported JS function (latLngToCell, gridDisk, polygonToCells, etc.) marshals JS values into the C module’s linear memory — allocating buffers sized via sizeOfH3Index(), sizeOfLatLng(), sizeOfCellBoundary() and friends — calls the corresponding bound C function, reads the result back out, and frees the buffer, with lib/errors.js translating native H3 error codes into thrown H3LibraryError/JSBindingError instances. A separate legacy.js/legacy-mapping.js layer re-exports the v3 function names as thin wrappers around the v4 API for projects migrating between major versions.

Tech Stack - The runtime surface has zero dependencies; everything needed to run ships in the compiled dist bundles (ES module, CommonJS, and UMD/browser builds via microbundle and rollup). The build toolchain is heavier: the H3 core is rebuilt from the upstream C library inside a pinned trzeci/emscripten Docker image (scripts/update-emscripten.sh), then bundled and type-checked with TypeScript (tsc --noEmit, strict mode) and linted with a legacy ESLint 4 + Prettier setup. Type declarations (dist/types.d.ts) are generated directly from the JSDoc-annotated source via tsc ... --emitDeclarationOnly, keeping the public API and its types mechanically in sync.

Code Quality - The project has an extensive test suite: test/h3core.spec.js and test/legacy.spec.js together exceed 1,700 lines, covering every exported function including edge cases (invalid indexes, pentagon cells, resolution domain errors) using tape, run through nyc for coverage and faucet for output formatting. Error handling is centralized and explicit — every native call path is wrapped so C-level error codes surface as typed JS errors with human-readable messages rather than silent failures or raw exit codes. Naming is consistent and mirrors the upstream H3 C API 1:1, which keeps the JS bindings predictable for anyone already familiar with H3’s C or Python bindings.

API Design - The public API favors plain data over custom classes: H3 indexes are always hex strings (or an optional [lower, upper] int-pair form for performance-sensitive code), coordinates are plain [lat, lng] tuples, and boundaries/polygons follow GeoJSON-adjacent conventions with an explicit formatAsGeoJson flag where ordering matters. Function names read as verbs on that data (cellToParent, gridDisk, polygonToCells), so the learning curve is mostly about learning H3’s own hexagon-grid vocabulary rather than the JS wrapper. The auto-generated README doubles as full API reference documentation with runnable examples for every function, which meaningfully lowers onboarding friction despite the conceptual depth of a hierarchical hexagonal grid system.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search