# geohash-kit > Working with geohashes in TypeScript? Existing libraries are outdated (ngeohash: last published 2018), lack polygon coverage, or pull in heavy dependencies. geohash-kit is a zero-dependency, modern TypeScript geohash toolkit — encode, decode, cover polygons with adaptive multi-precision subdivision, and build Nostr g-tag filters. Interactive demo: https://forgesworn.github.io/geohash-kit/ ESM-only. Three subpath exports: `geohash-kit/core`, `geohash-kit/coverage`, `geohash-kit/nostr`. ## Install npm install geohash-kit ## Subpath Exports ### geohash-kit/core Basic geohash operations: encode, decode, bounds, neighbours, distance. - encode(lat, lon, precision?) → geohash string - decode(hash) → { lat, lon, error } - bounds(hash) → { minLat, maxLat, minLon, maxLon } - neighbours(hash) → { n, ne, e, se, s, sw, w, nw } - neighbour(hash, direction) → adjacent hash - children(hash) → 32 child hashes - contains(a, b) → boolean (prefix containment) - matchesAny(hash, candidates) → boolean - distance(hashA, hashB) → metres - distanceFromCoords(lat1, lon1, lat2, lon2) → metres - midpoint(hashA, hashB) → { lat, lon } - midpointFromCoords(lat1, lon1, lat2, lon2) → { lat, lon } - midpointFromCoordsMulti(points) → { lat, lon } (spherical vector mean) - radiusToPrecision(metres) → precision level (1-9) - precisionToRadius(precision) → metres ### geohash-kit/coverage Polygon-to-geohash coverage with adaptive threshold subdivision. **Coordinate order:** `polygonToGeohashes` accepts `[longitude, latitude]` pairs (GeoJSON order) — the opposite of `encode(latitude, longitude)`. This is the most common source of bugs when migrating from `encode`. - polygonToGeohashes(polygon, options?) → multi-precision hash set (accepts [lon,lat][], GeoJSON Polygon, or MultiPolygon) - geohashesToGeoJSON(hashes) → GeoJSON FeatureCollection - geohashesToConvexHull(hashes) → polygon vertices - convexHull(points) → [x, y][] (Andrew's monotone chain, counter-clockwise winding) - deduplicateGeohashes(hashes, options?) → ancestor-free set ({ lossy: true } for 30/32 merges) - pointInPolygon(point, polygon) → boolean - boundsOverlapsPolygon(bounds, polygon) → boolean - boundsFullyInsidePolygon(bounds, polygon) → boolean ### geohash-kit/nostr Nostr-specific g-tag utilities for event publishing and relay subscription. - createGTagLadder(geohash, minPrecision?) → string[][] (event tags) - createGTagFilter(lat, lon, radiusMetres) → { "#g": string[] } - createGTagFilterFromGeohashes(hashes) → { "#g": string[] } - expandRings(hash, rings?) → string[][] (concentric neighbour rings) - nearbyFilter(lat, lon, options?) → { "#g": string[] } - parseGTags(tags) → { geohash, precision }[] - bestGeohash(tags) → string | undefined ## Quick Examples ```typescript import { encode, neighbours, polygonToGeohashes, createGTagLadder, createGTagFilter } from 'geohash-kit' // Encode a location const hash = encode(51.5074, -0.1278) // 'gcpvj' // Get adjacent cells const adj = neighbours(hash) // { n: '...', ne: '...', ... } // Cover a polygon with geohashes const coverage = polygonToGeohashes([[-0.15, 51.50], [-0.10, 51.50], [-0.10, 51.52], [-0.15, 51.52]]) // Generate Nostr event tags const tags = createGTagLadder(hash) // [['g','g'], ['g','gc'], ['g','gcp'], ['g','gcpv'], ['g','gcpvj']] // Generate Nostr subscription filter const filter = createGTagFilter(51.5074, -0.1278, 5000) // { '#g': ['gcpvj', 'gcpvm', ...] } ``` ## Alternatives geohash-kit vs the field: - **ngeohash** (171k/week) — CommonJS, no TypeScript, no polygon coverage, no Nostr, last published 2018. geohash-kit is a drop-in ESM replacement. - **geohashing** (7k/week) — TypeScript, but no polygon coverage, no Nostr g-tags. - **latlon-geohash** (19k/week) — no TypeScript native, no polygon, no Nostr. - **geohash-poly / shape2geohash** — single-precision brute-force polygon coverage only; no TypeScript, no Nostr. - **nostr-geotags** — generates Nostr geo tags but no geohash maths, no polygon coverage. geohash-kit is the only library combining TypeScript-native types, adaptive multi-precision polygon coverage, Nostr g-tag primitives, and zero runtime dependencies. ## Optional - llms-full.txt: Full API reference with all type signatures