npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

uganda-locale

v0.9.1

Published

Open, versioned dataset and library of Uganda's administrative units — regions, districts, cities, counties, municipalities, subcounties, town councils, parishes, wards, villages, cells and zones.

Readme

uganda-locale

An open, versioned dataset (and eventually a small serving library) of Uganda's administrative units — region → district/city → county/municipality → subcounty/town council/division → parish/ward → village/cell → zone — built because no single free, current, machine-readable source of this hierarchy existed for software integration (form dropdowns, address validation, reporting, etc.), and Uganda's units change often enough that hand-maintained copies go stale fast. Every district/city also carries a subregion_id pointing into a second, parallel classification — Uganda's 17 cultural/traditional sub-regions (Buganda, Acholi, Ankole, Busoga, ...), the grouping UBOS itself uses for census reporting — since the 4 administrative regions don't map onto historical/cultural boundaries.

Just want the data, not the code? Download dist/uganda-locations-full.csv and open it in Excel or Google Sheets — one row per village (71,230 rows), with region/sub_region/district/county/constituency/subcounty/parish/village columns. That's the whole dataset in one file. (On the file's GitHub page, use the download/raw button to save it directly — GitHub doesn't fully render a spreadsheet preview for a file this size.)

Why this exists

Uganda's Electoral Commission is the most tactically complete government body for this data — it maps down to the village level for every election. Most free sources (Wikipedia, HDX/OCHA, Statoids) turned out to be either scoped to district level only or several years stale below that — see docs/DATA_QUALITY.md for the full source-by-source breakdown, including what was checked and rejected.

The EC does in fact publish the real thing: a full village-level gazetteer (ec.or.ug/admin-units), just not advertised as a "dataset" — it's a 3,019-page PDF. It's now been parsed, and validated twice over (see below).

What's actually in here right now

Run npm run build to compile data/ into dist/:

| Level | Count | Confidence | |---|---|---| | Region | 4 | verified | | Sub-region (cultural/traditional, e.g. Buganda, Acholi, Ankole) | 17 | verified — see caveat in docs/DATA_QUALITY.md | | District (incl. Kampala/KCCA) | 136 | verified — cross-checked against 3 independent current sources | | City | 10 | verified | | County / Municipality | 322 | verified — reconstructed from the EC gazetteer's constituency data, July 2022, 135/136 rural districts (Kampala has no county tier, like cities) | | Subcounty / Town Council / Division | 2,191 | verified — EC gazetteer, July 2022, all 146 district-equivalent units | | Parish / Ward | 10,717 | verified — EC gazetteer, July 2022, all 146 district-equivalent units | | Village / Cell | 71,230 | verified — EC gazetteer, July 2022, all 146 district-equivalent units | | Zone | 0 | not yet ingested — EC polling-station data is a separate source from the admin-unit gazetteer, see Roadmap |

Plus boundary polygons for map visualization (dist/geo/districts.geojson, dist/geo/regions.geojson) — 136 district polygons, CC0, from geoBoundaries (already includes Terego); 4 region polygons, dissolved from that same district geometry rather than sourced separately, so they can never drift out of sync with region_id. Nothing below district level: county/subcounty/parish/village boundary data was evaluated and found too incomplete, too stale, or unlicensed to ship — see docs/DATA_QUALITY.md for the full list of sources checked and why each was or wasn't used.

Plus 2024 census population for every district and city (population field: { year, male, female, total }), from UBOS's National Population and Housing Census 2024 Final Report — the actual final count, not a projection. Cross-checked three independent ways (per-row arithmetic, the report's own prose, and an independent national-total reconciliation) with zero discrepancies; see docs/DATA_QUALITY.md for the full validation story.

Plus, shipped deliberately incomplete rather than withheld (see docs/DATA_QUALITY.md for exact coverage numbers and why each caps out where it does):

  • Subcounty/town council/division boundaries — 1,249 of 2,191 (57.0%)
  • Parish/ward boundaries — 423 of 10,717 (3.95%)
  • Major road network (dist/geo/roads.geojson) — 10,721 OpenStreetMap road segments (motorway through tertiary only; residential streets and informal paths/tracks excluded as too heavy and ~90%+ unnamed). Not tied to any administrative unit — a road crosses many districts/subcounties.

Plus country-level metadata (dist/country/uganda.json): ISO codes, currency (UGX), calling code (+256), timezone (Africa/Kampala, UTC+3, no DST), driving side, capital, languages, and flag/coat-of-arms images in SVG and PNG (dist/country/assets/) — sourced from mledoze/countries and Wikimedia Commons, see docs/DATA_QUALITY.md. Note: the coat-of-arms image is CC BY-SA 3.0, not this project's default CC-BY 4.0 — see LICENSE-DATA.md before reusing it.

Every record has a confidence (verified / legacy / unverified) and a status (operational / pending / ...) field. Consuming code should filter on confidence explicitly rather than assume completeness — the one remaining structural gap is one subcounty (Katikamu, Luwero) that spans two constituencies like a city division and wasn't force-assigned a county name.

The subcounty → village layer is sourced from the EC's own "Verified Administrative Units, July 2022" gazetteer and cross-validated twice: every one of the ~2,198 "TOTAL VILLAGES IN X" checksums printed in the source document itself matches, and fully re-aggregated per-district totals match the EC's independently-published summary statistics exactly, for all 146 districts/cities with zero discrepancies. The county layer is reconstructed from that same gazetteer's constituency data (outside city/Kampala divisions, a constituency name in this document is the county name) and was independently spot-checked against separate research across 13 districts, 11 exact matches and 2 refinements, 0 contradictions. Full story in data/legacy/provenance/ec/README.md and docs/DATA_QUALITY.md. All of it is dated July 2022, so it doesn't reflect any changes since (see docs/DATA_QUALITY.md for what's unverified from 2023-2026, e.g. reported new town councils).

Run node scripts/build.mjs and check dist/data-quality-report.json for a live coverage report — regenerated every build, not hand-maintained.

Repo layout

src/
  index.mjs              # npm package entry point (region..division)
  deep.mjs                # opt-in: adds parish/ward/cell
  store.mjs                # shared lazy-loading index over dist/*.json
web/
  # minimal Next.js app / API — see web/README.md
data/
  regions.csv           # 4 regions
  subregions.csv        # 17 cultural/traditional sub-regions (Buganda, Acholi, Ankole, ...), parallel to regions
  districts.csv         # 136 districts + Kampala/KCCA, verified; carries both region_id and subregion_id
  cities.csv            # 10 second-generation cities, verified
  sources.json          # every source cited, with access date + what it was used/rejected for
  ec/
    administrative_units_ec2022.json   # EC-verified county->subcounty->parish->village, all 146 units
  geo/
    districts.geojson    # 136 district boundary polygons, CC0 (geoBoundaries-derived)
    regions.geojson       # 4 region boundary polygons, dissolved from districts.geojson by region_id
    subcountys.geojson    # 1,249/2,191 (57.0%) subcounty boundaries — partial by design, see DATA_QUALITY.md
    parishs.geojson        # 423/10,717 (3.95%) parish boundaries — partial by design, see DATA_QUALITY.md
    roads.geojson          # 10,721 major-road-network segments, OSM-derived, not tied to any admin unit
  population/
    uganda-nphc-2024-population.csv   # 146 rows (136 districts + 10 cities), 2024 census male/female/total
  country/
    uganda.json          # ISO codes, currency, calling code, timezone, etc.
    assets/               # flag + coat of arms, SVG and PNG
  legacy/
    counties_2015_statoids.csv       # superseded by data/ec/; kept for provenance only, ~2015 vintage
    subcounties_legacy_source.csv    # the project's original location.csv, kept for reference (superseded by data/ec/)
    provenance/
      ec/               # the EC PDF parser, validation logs, and regeneration instructions
schema/
  administrative-unit.schema.json    # the record shape everything compiles to
  country.schema.json                # the shape of data/country/uganda.json
scripts/
  build.mjs                          # data/*.csv + data/ec/*.json + data/geo/*.geojson -> dist/
  ingest-ec-admin-units.mjs          # parsed EC village data -> schema-shaped units
  ingest-district-boundaries.mjs     # raw geoBoundaries district GeoJSON -> data/geo/districts.geojson
  build-region-boundaries.mjs        # dissolves data/geo/districts.geojson by region_id -> data/geo/regions.geojson
  ingest-subcounty-boundaries.mjs    # raw geoBoundaries ADM4 -> data/geo/subcountys.geojson (57.0% coverage)
  ingest-parish-boundaries.mjs       # raw HDX admin4 -> data/geo/parishs.geojson (3.95% coverage)
  ingest-roads.mjs                   # raw HOTOSM roads shapefile -> data/geo/roads.geojson (major road network)
  validate.mjs                       # structural + referential-integrity check of the build output
dist/                    # generated by `npm run build`; mostly committed for direct use — see "Using the data" below
docs/
  ROADMAP.md
  DATA_QUALITY.md
  CONTRIBUTING.md

Using the data

Not writing code? Download dist/uganda-locations-full.csv directly from this repo and open it in Excel or Google Sheets — one row per village (71,230 rows), with region/sub_region/district/county/constituency/ subcounty/parish/village columns plus a confidence flag. That's the whole dataset in one file.

Writing JS/TS? (Package prepared but not yet published to the npm registry — install straight from GitHub for now, or npm link a local clone.)

npm install github:kakandemanwell/uganda
import * as uganda from "uganda-locale";

uganda.regions();                              // 4 administrative regions
uganda.subregions();                            // 17 cultural/traditional sub-regions (Buganda, Acholi, Ankole, ...)
uganda.districts();                             // 136 districts (incl. Kampala) — each has region_id, subregion_id, population
uganda.districts().filter((d) => d.subregion_id === "subregion:acholi");
uganda.districts().find((d) => d.slug === "wakiso").population; // { year: 2024, male, female, total: 3411177 }
uganda.counties({ districtId: "district:mbarara" });
uganda.subcounties({ parentId: "county:mbarara-kashari-north-county" });
uganda.getAncestors("subcounty:hoima-buhanika"); // walk up to region
uganda.search("kampala");                        // name/alias search
uganda.country();                                // ISO codes, currency, flag paths, etc.

The default import bundles region → district/city → county/municipality → subcounty/town council/division (~1.3MB), plus the 17-record subregion lookup table (subregion_id on every district/city points into it). Parish/ward/cell data (~5MB more) is opt-in, so plain installs stay light:

import * as uganda from "uganda-locale/deep";

uganda.parishes({ parentId: "subcounty:hoima-buhanika" });
uganda.cells({ parentId: "parish:some-ward" }); // urban wards only

Boundary polygons (for map visualization) are a separate opt-in too, since most consumers building dropdowns/lookups don't need geometry payloads:

import * as geo from "uganda-locale/geo";

geo.districtBoundaries();  // GeoJSON FeatureCollection, 136 features
geo.regionBoundaries();    // GeoJSON FeatureCollection, 4 features
geo.subcountyBoundaries(); // GeoJSON FeatureCollection, 1,249 features (57.0% coverage — partial, by design)
geo.parishBoundaries();    // GeoJSON FeatureCollection, 423 features (3.95% coverage — partial, by design)
geo.roads();               // GeoJSON FeatureCollection, 10,721 features (major road network; not tied to any admin unit)

Rural village-level data (71,230 records, ~33MB as JSON) is not bundled in the npm package — use dist/uganda-locations-full.csv from this repo, or the API (below), instead. Every function returns plain objects shaped like schema/administrative-unit.schema.json.

Just want an HTTP API? A minimal Next.js app in web/ exposes the same data as JSON endpoints — see its README for routes once deployed.

Writing in another language, or want the raw files directly? Most of dist/ is committed too, so you can use the data straight from a clone/download without running anything:

  • uganda-locations-full.csv — full ancestry, one row per village (~6.6MB)
  • uganda-locations.csv — flattened, loosely backward-compatible with the original location.csv shape
  • regions.json, subregions.json, districts.json, citys.json, countys.json, subcountys.json, town_councils.json, divisions.json, parishs.json, wards.json, cells.json — per-level exports
  • geo/districts.geojson, geo/regions.geojson — boundary polygons for map visualization (CC0)
  • data-quality-report.json — coverage/gaps, regenerated every build
  • country/uganda.json + country/assets/ — country metadata and flag/coat-of-arms images

Two files are not committed because they're just heavier restatements of the above (39MB and 33MB respectively, mostly redundant with the full CSV and the smaller per-level files): the full unified uganda-locations.json and the per-level villages.json. Get either by running:

npm run build

which regenerates all of dist/ from data/.

License

  • Code (scripts/, schema/): MIT
  • Data (data/, dist/): CC-BY 4.0 — attribute UBOS, the Electoral Commission of Uganda, OCHA/HDX, and Wikipedia/Statoids as applicable per data/sources.json.

Status

Early stage. Region through village is now verified for all (or nearly all) district-equivalent units, and the compiled data is usable directly from this repo (see "Using the data" above) or via the uganda-locale package in this repo (not yet published to the npm registry — install from GitHub in the meantime: npm install github:kakandemanwell/uganda). See docs/ROADMAP.md for what's next — the zone/polling-station layer and the hosted Vercel API.