zipcode-neighbors
v2.2.2
Published
Find neighboring postal code areas using GeoJSON boundary data and spatial analysis. Prepacked with Berlin, Germany. Configurable to other localities.
Maintainers
Readme
Berlin ZIP Code Neighbor Finder
A Node.js module to find neighboring postal code areas in Berlin using GeoJSON boundary data and spatial analysis.
Overview
This module provides a way to identify which Berlin postal codes share geographic boundaries with each other. It includes pre-computed mappings for fast lookups with automatic fallback to geometric computation.
It utilizes geodata from yetzt's wonderful postleitzahlen project. Check it out!
Features
- Fast cached lookups: Pre-computed mappings for instant neighbor queries (O(1) lookup)
- Geographic neighbor detection: Find all postal codes that share a boundary with a given ZIP code
- Berlin-default: Pre-filtered dataset containing only Berlin postal codes but pipeline to add custom localities
- Fallback computation: Automatically computes neighbors if cache is unavailable
- Efficient spatial analysis: Uses Turf.js for geometric operations
- CLI tool: Includes command-line interface for quick lookups
- NPM installable: Install as a dependency in your projects
Installation
From GitHub (using npm)
npm install github:machinaeXphilip/zipcode-neighborsOr via git URL:
npm install git+https://github.com/machinaeXphilip/zipcode-neighbors.gitFrom NPM Registry
install via:
npm install zipcode-neighborsUsage
As a Module
Import and use the module in your JavaScript code:
//import { findNeighbors } from './lib/index.js'; // if you downloaded the source
import { findNeighbors } from 'zipcode-neighbors'; // if you installed via package manager
// Find neighboring postal codes for 13156 (uses Berlin by default)
const neighbors1 = findNeighbors('13156');
console.log(neighbors1); // ['12627', '13155', '14165', ...]
// Force recomputation from features (slower, but always works)
const neighbors2 = findNeighbors('13156', false, true);
// Show progress during computation
const neighbors3 = findNeighbors('13156', true, false);
console.log(neighbors1, neighbors2, neighbors3)Using Different Localities
To use a different locality, set the LOCALITY environment variable before importing (only possible if you've prepared data for other localities as described below):
process.env.ZIPCODE_DATA_DIR = './my-zipcode-data';
process.env.LOCALITY = 'dusseldorf';
const { findNeighbors } = import('zipcode-neighbors');
const neighbors = findNeighbors('40210');API
findNeighbors(targetZip, showProgress, forceCompute)
Find neighboring postal codes for a given Berlin ZIP code.
Parameters:
targetZip(string): The postal code to find neighbors forshowProgress(boolean, optional): Whether to show progress logs during computation (default: false)forceCompute(boolean, optional): Force computation from features instead of using cache (default: false)
Returns:
- Array of neighboring postal codes, sorted alphabetically
findNeighborsFromFeatures(targetZip, showProgress)
Find neighbors by computing from GeoJSON features (slower method, always works).
Parameters:
targetZip(string): The postal code to find neighbors forshowProgress(boolean, optional): Whether to show progress logs (default: false)
Returns:
- Array of neighboring postal codes, sorted alphabetically
loadNeighborMappings()
Manually load pre-computed neighbor mappings from disk. This is typically called automatically.
Command Line Interface
Use the included CLI tool to query neighbors directly:
# Download and install globally
npm install -g zipcode-neighbors
# Query for neighbors
zipcode-neighbors 13156
# Force computation instead of using cache
zipcode-neighbors 13156 trueOr use it with npx:
npx zipcode-neighbors 13156Project Structure
.
├── lib/
│ └── index.js # Main module entry point
├── bin/
│ └── zipcode-neighbors.js # CLI tool
├── data/
│ ├── postleitzahlen.geojson # Decompressed source data
│ ├── postleitzahlen.geojson.br # Brotli-compressed source data
│ └── localities/
│ ├── berlin/
│ │ ├── zipcodeList.json # List of Berlin postal codes
│ │ ├── zipcodes.geojson # GeoJSON data for Berlin postal codes
│ │ └── neighborMappings.json # Pre-computed neighbor mappings (optional)
│ └── [other-localities]/ # Support for other localities
├── scripts/
│ ├── decompressFromBrotli.js
│ ├── filterPostcodesByList.js
│ └── generateNeighborMappings.js
├── test/
│ └── data-preparation-pipeline.test.js # Integration tests for data pipeline
├── examples.js # Usage examples
├── package.json
├── LICENSE # MIT License
├── DATA_LICENSE # ODbL data license
└── README.mdPrerequisites
- Node.js (v18 or higher)
- npm
Local Development
Install dependencies:
npm installThis will install:
@turf/turf- For spatial analysis operationsbrotli- For decompressing source data
Cache Management
Each locality has its own cache file at <data-dir>/localities/<locality>/neighborMappings.json. By default, this is data/localities/<locality>/neighborMappings.json in the package directory, but when using custom data paths via ZIPCODE_DATA_DIR, it follows your custom location.
The module automatically uses this cache for instant lookups, with automatic fallback to geometric computation if the cache is unavailable.
Performance
- Cached query: ~instant (JSON object lookup)
- Without cache: ~slower per query depending on the size of the areas covered (geometric computation)
Data Preparation
The Berlin ZIP code data is already prepared and ready to use. However, you can update or add new localities using the data preparation pipeline.
Environment Variables
The scripts support two environment variables for configuration:
LOCALITY- Which locality to use (default:berlin). Set this when working with other localitiesZIPCODE_DATA_DIR- Base directory for all data files (default:<package>/data)
All file paths follow a predictable structure:
- Source data:
${ZIPCODE_DATA_DIR}/postleitzahlen.geojson.brandpostleitzahlen.geojson - Postcode lists:
${ZIPCODE_DATA_DIR}/localities/${LOCALITY}/zipcodeList.json - Locality output:
${ZIPCODE_DATA_DIR}/localities/${LOCALITY}/
Working from Source Repository
If you cloned this repository:
Step 1: Download Source Data
curl -L https://github.com/yetzt/postleitzahlen/releases/download/2026.02/postleitzahlen.geojson.br -o ./data/postleitzahlen.geojson.brStep 2: Decompress the Data
node scripts/decompressFromBrotli.jsThis reads data/postleitzahlen.geojson.br and creates data/postleitzahlen.geojson.
Step 3: Filter Postal Codes by Locality
For Berlin (default):
node scripts/filterPostcodesByList.jsFor a different locality, set the LOCALITY environment variable (or pass it as a CLI argument):
LOCALITY=dusseldorf node scripts/filterPostcodesByList.js
# alternative w/o env
# node scripts/filterPostcodesByList.js ./data/localities/dusseldorf/zipcodeList.jsonNote: You must first create the postcode list file (e.g., ./data/localities/dusseldorf/zipcodeList.json) with your desired postal codes before running this script.
Step 4 (Optional): Generate Neighbor Mappings Cache
For Berlin (default):
node scripts/generateNeighborMappings.jsFor a different locality, set the LOCALITY environment variable (or pass it as a CLI argument fallback):
LOCALITY=dusseldorf node scripts/generateNeighborMappings.jsNote: This step is computationally intensive and may take several minutes.
Working with NPM-Installed Package
If you installed via npm and want to work with custom localities outside of node_modules:
Step 1: Set Up Custom Data Directory
mkdir -p my-zipcode-data/localitiesStep 2: Download Source Data
curl -L https://github.com/yetzt/postleitzahlen/releases/download/2026.02/postleitzahlen.geojson.br -o my-zipcode-data/postleitzahlen.geojson.brStep 3: Decompress the Data
ZIPCODE_DATA_DIR=./my-zipcode-data node node_modules/zipcode-neighbors/scripts/decompressFromBrotli.jsStep 4: Create Postcode List
Create your custom postcode list (array of strings or object with name and postcodes):
[
"40210", "40211", "40212", "40213", "40215", "40217", "40219", "40221", "40223", "40225", "40227", "40229", "40231", "40233", "40235", "40237", "40239",
"40468", "40470", "40472", "40474", "40476", "40477", "40479", "40489",
"40545", "40547", "40549", "40589", "40591", "40593", "40595", "40597", "40599",
"40625", "40627", "40629"
]Step 5: Filter for Your Locality
ZIPCODE_DATA_DIR=./my-zipcode-data LOCALITY=dusseldorf node node_modules/zipcode-neighbors/scripts/filterPostcodesByList.jsStep 6 (Optional): Generate Neighbor Mappings
ZIPCODE_DATA_DIR=./my-zipcode-data LOCALITY=dusseldorf node node_modules/zipcode-neighbors/scripts/generateNeighborMappings.jsSee the "Using Different Localities" section above for instructions on using your custom locality in code.
Example CLI Output
Finding neighbors for zip code 13127...
Neighboring zip codes: 13125, 13129, 13156, 13159
Total neighbors: 4
Time taken: 0.0023 secondsHow It Works
The neighbor detection uses the Turf.js library for spatial analysis:
- Loads the GeoJSON file containing Berlin postal code area boundaries
- For each comparison:
- Uses
turf.booleanTouches()to check if two polygons share a boundary - Two ZIP codes are considered neighbors if their boundaries touch
- Uses
- Returns a sorted list of all neighboring postal codes
Data Source
The source data comes from the yetzt/postleitzahlen repository, which provides German postal code boundaries as GeoJSON.
Berlin Postal Codes
The dataset includes all Berlin postal codes ranging from:
- 10115 - 10999 (Central Berlin)
- 12043 - 12689 (South Berlin)
- 13051 - 13629 (East Berlin)
- 14050 - 14199 (West Berlin)
Total: ~190 postal code areas
License
Code License
This project code is licensed under the MIT License. See LICENSE.
Data License and Attribution
The GeoJSON data is derived from yetzt/postleitzahlen and is licensed under the ODC Open Database License (ODbL) v1.0. See DATA_LICENSE for full attribution and license requirements.
Mixed License Distribution (Important)
This package distributes mixed-licensed contents:
- Code files (for example
lib/,bin/,scripts/,examples.js) are under MIT. - Included dataset files under
data/localities/are under ODbL v1.0.
When redistributing this package, included data, or adapted database outputs derived from the included data, ensure you follow ODbL attribution and share-alike requirements in addition to the MIT terms for code.
