Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ dist-ssr

.worktrees/
graphify-out/
docs/superpowers/

src/data-compressed
177 changes: 160 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@

# PH-Address

A lightweight package that provides a comprehensive collection of Philippine geographic data, based on the official [Philippine Standard Geographic Code (PSGC)](https://psa.gov.ph/classification/psgc/) as of 30 June 2026.
A lightweight Philippine address-data package containing the official [Philippine Standard Geographic Code (PSGC)](https://psa.gov.ph/classification/psgc/) geographic hierarchy as of 30 June 2026 and separate postal-code mappings.

[Explore the Philippine address data](https://aivangogh.dev/tools/ph-address)

## Features

- **Up-to-Date Data**: Sourced from the latest PSGC publications.
- **Address Data**: PSGC regions, provinces, municipalities, cities, and barangays, plus Philippine postal-code mappings.
- **Ultra-Lightweight**: Highly optimized bundle size (~373 KB dist) using CSV + gzip compression — 40% smaller than the previous format.
- **Fast Performance**: Efficient data loading with automatic caching. Barangay data (42k rows) decompresses and parses in ~39 ms on first call; subsequent calls are nearly instant.
- **Fully Typed**: Written in TypeScript for a better developer experience with full type definitions.
Expand All @@ -29,6 +29,25 @@ A lightweight package that provides a comprehensive collection of Philippine geo

This package supports Node.js 18 or newer and browsers, with both CommonJS (`require()`) and ESM (`import`) syntax. The data is bundled directly with the code using efficient compression, so it works seamlessly without needing file system access.

## Address Data Model

### PSGC geographic codes

![PSGC Revision 1 10-digit coding structure](assets/psgc/coding-structure.png)

PSGC Revision 1 uses a 10-digit `RR-PPP-MM-BBB` structure:

| Segment | Meaning |
| ------- | --------------------------------------- |
| `RR` | Region |
| `PPP` | Province or highly urbanized city (HUC) |
| `MM` | Municipality or city |
| `BBB` | Barangay |

### Postal codes

Philippine postal codes are separate four-digit delivery-area identifiers. They complement PSGC codes but are not derived from them: a municipality can have multiple postal codes, and a postal code can cover multiple localities.

### Performance Characteristics

- **Bundle Size**: ~373 KB (dist/index.mjs) — 40% smaller than the previous format
Expand All @@ -41,11 +60,11 @@ The package uses CSV with gzip compression for optimal size and parse speed. Dat

Benchmarked on 42,010 barangay rows (20 iterations median):

| Format | Compressed size | Decompress + parse |
|---|---|---|
| JSON | 586 KB | 81 ms |
| CSV full | 477 KB | 77 ms |
| **CSV optimized** (current) | **346 KB** | **39 ms** |
| Format | Compressed size | Decompress + parse |
| --------------------------- | --------------- | ------------------ |
| JSON | 586 KB | 81 ms |
| CSV full | 477 KB | 77 ms |
| **CSV optimized** (current) | **346 KB** | **39 ms** |

CSV optimized removes columns that are derivable from the 10-digit PSGC code structure, then derives them at load time — smaller payload and less to parse.

Expand Down Expand Up @@ -79,21 +98,55 @@ You can import all functions from the package:
```ts
import {
getAllRegions,
getRegionByCode,
getAllProvinces,
getProvinceByCode,
getAllMunicipalities,
getMunicipalityByCode,
getAllBarangays,
getBarangayByCode,
getProvincesByRegion,
getMunicipalitiesByProvince,
getBarangaysByMunicipality,
getBarangayByCode,
getAddressByBarangayCode,
getAllPostalCodes,
getLocationsByPostalCode,
getPostalCodesByMunicipality,
} from "@aivangogh/ph-address";
```

### Function signatures

| Function | Return type |
| -------------------------------------------------------- | ----------------------------- |
| `getAllRegions()` | `readonly PHRegion[]` |
| `getRegionByCode(code: string)` | `PHRegion \| undefined` |
| `getAllProvinces()` | `readonly PHProvince[]` |
| `getProvinceByCode(code: string)` | `PHProvince \| undefined` |
| `getProvincesByRegion(code: string)` | `readonly PHProvince[]` |
| `getAllMunicipalities()` | `readonly PHMunicipality[]` |
| `getMunicipalityByCode(code: string)` | `PHMunicipality \| undefined` |
| `getMunicipalitiesByProvince(code: string)` | `readonly PHMunicipality[]` |
| `getAllBarangays()` | `readonly PHBarangay[]` |
| `getBarangayByCode(code: string)` | `PHBarangay \| undefined` |
| `getBarangaysByMunicipality(code: string)` | `readonly PHBarangay[]` |
| `getAddressByBarangayCode(code: string)` | `PHAddress \| undefined` |
| `getAllPostalCodes()` | `readonly PHPostalCode[]` |
| `getLocationsByPostalCode(postalCode: string)` | `readonly PHPostalCode[]` |
| `getPostalCodesByMunicipality(municipalityCode: string)` | `readonly PHPostalCode[]` |

Collection lookups return an empty readonly array when no records match;
exact-code lookups return `undefined`.

---

### Code and Address Lookup

```ts
getBarangayByCode(code: string): PHBarangay | undefined;
getAddressByBarangayCode(code: string): PHAddress | undefined;
```

```ts
const barangay = getBarangayByCode("0730600001");
const address = getAddressByBarangayCode("0730600001");
Expand All @@ -106,7 +159,7 @@ optional for NCR and independent or highly urbanized cities.

### `getAllRegions()`

Returns a sorted list of all regions.
Returns `readonly PHRegion[]`, sorted by region order.

**Example:**

Expand All @@ -128,7 +181,7 @@ console.log(regions);

### `getAllProvinces()`

Returns a sorted list of all provinces.
Returns `readonly PHProvince[]`, sorted alphabetically.

**Example:**

Expand All @@ -150,7 +203,8 @@ console.log(provinces);

### `getProvincesByRegion(regionCode)`

Returns a sorted list of provinces within a specific region.
Returns `readonly PHProvince[]`, sorted alphabetically. Returns an empty array
when the region has no matching provinces.

- `regionCode` (string): The PSGC code of the region.

Expand All @@ -160,7 +214,7 @@ Returns a sorted list of provinces within a specific region.
import { getProvincesByRegion } from "@aivangogh/ph-address";

// Get all provinces in Region VII (Central Visayas)
const provinces = getProvincesByRegion("0700000000");
const provinces = getProvincesByRegion("0700000000");
console.log(provinces);
/*
[
Expand All @@ -174,7 +228,8 @@ console.log(provinces);

### `getMunicipalitiesByProvince(provinceCode)`

Returns a sorted list of municipalities/cities within a specific province.
Returns `readonly PHMunicipality[]`, sorted alphabetically. Returns an empty
array when the province has no matching municipalities or cities.

- `provinceCode` (string): The PSGC code of the province.

Expand All @@ -199,7 +254,8 @@ console.log(municipalities);

### `getBarangaysByMunicipality(municipalityCode)`

Returns a sorted list of barangays within a specific municipality or city.
Returns `readonly PHBarangay[]`, sorted alphabetically. Returns an empty array
when the municipality or city has no matching barangays.

- `municipalityCode` (string): The PSGC code of the municipality or city.

Expand All @@ -222,6 +278,40 @@ console.log(barangays);
*/
```

## Postal Codes

Postal codes are separate from the PSGC hierarchy because one municipality can
have multiple delivery localities and codes.

```ts
getAllPostalCodes(): readonly PHPostalCode[];
getLocationsByPostalCode(postalCode: string): readonly PHPostalCode[];
getPostalCodesByMunicipality(
municipalityCode: string,
): readonly PHPostalCode[];
```

Postal-code lookups return an empty readonly array when no records match.

```ts
import {
getAllPostalCodes,
getLocationsByPostalCode,
getPostalCodesByMunicipality,
} from "@aivangogh/ph-address";

getLocationsByPostalCode("6000");
getPostalCodesByMunicipality("0730600000"); // Cebu City
getAllPostalCodes();
```

Every current PSGC municipality/city has at least one postal-code mapping.
Historical names and spelling differences are resolved through reviewed
aliases. New BARMM Special Geographic Area municipalities use the PHLPost
codes inherited from the municipalities that previously contained their
barangays. GeoNames localities that still cannot be identified safely remain
available through postal-code lookup without a `municipalityCode`.

## Types

You can import all the necessary types for use in your TypeScript projects.
Expand All @@ -231,14 +321,67 @@ import type {
PHRegion,
PHProvince,
PHMunicipality,
PHBarangay
PHBarangay,
PHPostalCode,
PHAddress,
} from "@aivangogh/ph-address";
```

```ts
type PHRegion = {
name: string;
psgcCode: string;
designation: string;
};

type PHProvince = {
name: string;
psgcCode: string;
regionCode: string;
};

type PHMunicipality = {
name: string;
psgcCode: string;
provinceCode: string;
};

type PHBarangay = {
name: string;
psgcCode: string;
municipalCityCode: string;
};

type PHPostalCode = {
postalCode: string;
placeName: string;
provinceName: string;
regionName: string;
municipalityCode?: string;
};

type PHAddress = {
region: PHRegion;
province?: PHProvince;
municipality: PHMunicipality;
barangay: PHBarangay;
};
```

`PHAddress.province` is optional for NCR and independent or highly urbanized
cities. `PHPostalCode.municipalityCode` is optional when a delivery locality
cannot be mapped safely to a current PSGC municipality or city.

## Data Source

The data is sourced directly from the quarterly publications of the **Philippine Statistics Authority (PSA)**.
Geographic data is sourced from the quarterly [Philippine Standard Geographic Code publications](https://psa.gov.ph/classification/psgc/node/1684083815) of the **Philippine Statistics Authority (PSA)**.

Postal-code data is from [GeoNames](https://www.geonames.org/), licensed under
[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). The source snapshot
and its readme are stored in `assets/ph-postal-code`. Reviewed mappings use the
[PHLPost ZIP Code Locator](https://phlpost.gov.ph/zip-code-locator/) and the
PSA PSGC correspondence data bundled with this package.

## License

[MIT](LICENSE)
[MIT](LICENCE)
Loading
Loading