How to implement geohashes correctly in TypeScript and Rust, how to query and index them at scale, and how to apply them to the "codebase as a navigable 2D map" pattern — projecting code into a plane so geohash prefixes become domain regions you can fly through like Google Maps. Contains 42 rules across 8 categories, prioritised by impact.
When to Apply
Reference these guidelines when:
- Implementing or reviewing a geohash encoder/decoder in TypeScript or Rust (bit interleaving, base32, precision, neighbours)
- Building proximity / radius / bounding-box search on lat/lon data, or storing geohashes as index keys (SQL B-tree, Redis sorted sets)
- Debugging the classic geohash bugs — swapped axes, wrong alphabet, border false negatives, off-by-one cells at high precision
- Projecting a codebase (or any abstract graph) into a 2D plane and geohashing it so prefixes name business domains or features
- Navigating a geohashed dataset like a slippy map: zoom-to-precision, viewport tile loading, level-of-detail aggregation, prefix clustering, deep links
A note on scope
Categories 1–4, 6, and 7 are textbook geohashing, drawn from authoritative sources (the geohash spec, the davetroy/geohash-js neighbour tables, Redis, Elasticsearch). Categories 5 (map-) and 8 (nav-) are a novel synthesis — there is no canonical "geohash your codebase" library, so those rules derive design principles from established techniques (deterministic graph layout, Morton/Z-order keys, slippy-map tiling, software cartography). They are honest about when the pattern is overkill.
Rule Categories by Priority
| Priority | Category | Impact | Prefix | Rules |
|---|---|---|---|---|
| 1 | Encoding & Bit Interleaving | CRITICAL | enc- |
6 |
| 2 | Precision & Cell Geometry | CRITICAL | prec- |
5 |
| 3 | Neighbours & Adjacency | HIGH | nbr- |
5 |
| 4 | Proximity & Range Queries | HIGH | qry- |
5 |
| 5 | Codebase-as-Map Spatial Layout | HIGH | map- |
7 |
| 6 | Decoding & Bounding Boxes | MEDIUM-HIGH | dec- |
4 |
| 7 | Spatial Indexing & Storage | MEDIUM-HIGH | idx- |
5 |
| 8 | Navigation & Rendering | MEDIUM | nav- |
5 |
Quick Reference
1. Encoding & Bit Interleaving (CRITICAL)
enc-interleave-longitude-first— Interleave longitude on even bits, latitude on oddenc-base32-alphabet— Use the geohash base32 alphabet, not RFC 4648enc-integer-morton-encode— Encode to an interleaved 64-bit integer for speed and sortable keysenc-binary-chop-no-float-drift— Recompute interval midpoints; never accumulate a float stepenc-normalize-input-domain— Clamp latitude, wrap longitude, reject non-finite inputenc-five-bit-char-boundary— Accumulate exactly five bits per character
2. Precision & Cell Geometry (CRITICAL)
prec-choose-from-error-radius— Choose geohash length from the required error radiusprec-cells-are-not-square— Treat cells as rectangles whose aspect flips with lengthprec-error-is-half-cell— Report decoded accuracy as half the cell, not the full cellprec-cells-shrink-toward-poles— Scale longitude metres by cos(latitude)prec-avoid-mixed-precision— Normalise to one precision before comparing or storing
3. Neighbours & Adjacency (HIGH)
nbr-canonical-lookup-tables— Compute neighbours with the canonical border/neighbour tablesnbr-antimeridian-wrap— Wrap east/west neighbours across the antimeridiannbr-pole-handling— Return no neighbour past the polesnbr-integer-level-neighbors— Compute neighbours on the de-interleaved integernbr-eight-neighbor-set— Build the full eight-neighbour set for proximity
4. Proximity & Range Queries (HIGH)
qry-search-cell-plus-neighbors— Query the cell plus its eight neighbours, never the prefix aloneqry-precision-from-radius— Match query precision to the search radiusqry-bbox-range-decomposition— Decompose a bounding box into covering geohash rangesqry-refine-with-haversine— Refine geohash candidates with true distanceqry-expand-precision-when-sparse— Widen the search by dropping a prefix character on sparse cells
5. Codebase-as-Map Spatial Layout (HIGH)
map-deterministic-projection— Project code into 2D from a structural signal, not arbitrary layoutmap-stable-coordinates— Make coordinates reproducible and incremental-stablemap-normalize-to-geohash-domain— Normalise the code plane into the geohash lat/lon domainmap-coupling-implies-proximity— Validate that coupled code lands in the same regionmap-prefix-as-domain-region— Treat a geohash prefix as a named domain regionmap-precision-as-architectural-level— Map prefix length to architectural levelmap-persist-coordinate-sidecar— Persist the file-to-geohash assignment as a committed sidecar
6. Decoding & Bounding Boxes (MEDIUM-HIGH)
dec-decode-to-bbox— Decode to a bounding box, then derive the centredec-symmetric-interval-reconstruction— Decode by mirroring the encoder's interval halvingdec-avoid-roundtrip-reencode— Keep the original hash; don't decode-then-re-encodedec-precompute-reverse-alphabet— Decode with a precomputed reverse-alphabet table
7. Spatial Indexing & Storage (MEDIUM-HIGH)
idx-sorted-string-range-scan— Store geohashes as sorted strings for prefix range scansidx-integer-sortable-key— Use the interleaved integer as a compact sortable keyidx-db-prefix-index— Make prefix queries sargable in Postgres and Redisidx-range-query-from-covering-set— Execute a box query as range scans over the covering setidx-trie-hierarchical-bucketing— Aggregate by region with a geohash trie
8. Navigation & Rendering (MEDIUM)
nav-precision-to-zoom-levels— Map geohash precision to zoom levelsnav-level-of-detail-aggregation— Render aggregated prefix buckets when zoomed outnav-tile-lazy-loading— Load only the geohash cells in the viewportnav-cluster-by-prefix— Cluster overlapping markers by shared prefixnav-breadcrumb-prefix-path— Use the geohash prefix as navigation state and deep link
How to Use
Read individual reference files for detailed explanations, code examples, and "when NOT to apply" guidance:
- Section definitions — Category structure and impact levels
- Rule template — Template for adding new rules
Rules cross-link via [[other-rule-slug]]; follow them when a related pattern is referenced. To build a code map end to end, the spine is: map-deterministic-projection → map-normalize-to-geohash-domain → encode (category 1) → map-prefix-as-domain-region → navigate (category 8).
Reference Files
| File | Description |
|---|---|
| references/_sections.md | Category definitions and ordering |
| assets/templates/_template.md | Template for new rules |
| metadata.json | Version and reference information |