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

belgica

v0.6.2

Published

Belgian legal reference data: courts, judicial cantons and arrondissements, municipalities and postal codes, legal and commercial interest rates, and the public and judicial holidays.

Readme

belgica

Belgian legal reference data for developers of legal software: every court with its registries' contacts, prisons, houses of justice, judicial cantons and arrondissements, municipalities and their postal codes, the legal and commercial interest rates, and the public holidays. As JSON and CSV, with typed lookups for TypeScript and Python. Every record says where it comes from, and the scraped data is rebuilt from the official sources twice a week.

It answers questions such as: which justice of the peace has jurisdiction over this address, what is this court's registry e-mail, which interest rate applied on that day, and on which day does a deadline that ends on Easter Monday end instead.

Documentation: https://pieterjanscheir.github.io/belgica/

The explorer is a site built on the package, in 13 languages: a page for every court, canton, municipality and postal code, the canton map and an interest calculator. Its Next.js source is in site/.

It's reference data, not legal advice: check the official sources before relying on it.

What's in it

| File | Contents | Source | | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------- | | data/judicial-areas.json | The 5 judicial areas (courts of appeal) | Judicial Code, annex art. 5 | | data/arrondissements.json | The 12 judicial arrondissements and their judicial area | Judicial Code, annex art. 4 | | data/cantons.json | All 162 judicial cantons: name, seat, municipalities, the legal description of their area, and its ELI | Judicial Code, annex art. 1 (generated) | | data/canton-boundaries.json | The boundary of every canton as GeoJSON geometry (WGS 84), to find the canton of a point in a split city | NGI, geo.be (fetched weekly) | | data/arrondissement-boundaries.json | The boundary of every arrondissement as GeoJSON geometry (WGS 84) | NGI, geo.be (fetched weekly) | | data/municipalities.json | The 565 municipalities with REFNIS code, province and region | Statbel (generated) | | data/regions.json | The 3 regions, named in Dutch, French and German | Statbel REFNIS code list (generated weekly) | | data/provinces.json | The 10 provinces, with their region | Statbel REFNIS code list (generated weekly) | | data/courts.json | Every court, division and seat: every justice of the peace, police court, court of first instance, enterprise and labour court, court of appeal, labour court of appeal and court of assize, with names as published, addresses, registries' contacts, opening hours, ECLI codes and the cantons each covers | tribunaux-rechtbanken.be (scraped weekly) | | data/court-locations.json | A GeoJSON point for each justice of the peace, where the NGI's address matches the court's | NGI, geo.be (fetched weekly) | | data/prisons.json | Every prison and detention house, names in three languages | justitie.belgium.be (scraped weekly) | | data/houses-of-justice.json | The houses of justice of the Flemish (with OVO number) and French Communities | vlaanderen.be, maisonsdejustice.be (scraped weekly) | | data/postal-codes.json | Every postal code with the municipality it belongs to, by REFNIS code (three codes belong to two) | Statbel conversion table (fetched weekly) | | data/interest-rates.json | Legal interest rate (per year, since 1970) and commercial-transaction rate (per semester, since 2002) | FOD Financiën / Belgisch Staatsblad | | data/public-holidays.json | The rules for the ten legal public holidays, three of them from Easter, for moving a deadline to the next working day | Wet 4 januari 1974, KB 18 april 1974 |

The official sources are the truth; the files in data/ are built from them. Every file has a JSON Schema, and datapackage.json lists each dataset's sources, licence, coverage and when it was last checked. Each release has the data as JSON and CSV in one zip.

Planned: the highest courts, history before 2025, bailiffs, police zones and the cadastre offices. See the roadmap.

Using it

TypeScript / JavaScript

pnpm add belgica

ESM with TypeScript types inferred from zod schemas, which belgica/schemas exports for validation; the datasets don't load zod at run time. Node 22.12 or later (where require() loads it too) and browsers. Start with getting started; every function is in the API reference.

import {
    getCourt,
    getContact,
    findCourts,
    getJusticeOfThePeace,
    getCantonsForMunicipality,
    findCourtsWithJurisdiction,
    findCourtsForPostalCode,
    getInterestRate,
    nextWorkingDay,
} from 'belgica'
import { findCantonsAt } from 'belgica/canton-boundaries'

getCourt('court-of-appeal-brussel').name // { nl: 'Hof van Beroep Brussel', fr: "Cour d'appel de Bruxelles" }
getContact(getCourt('court-of-appeal-liege'), 'email', 'Greffe pénal') // '[email protected]'
findCourts({ type: 'enterprise-court', arrondissement: 'west-vlaanderen' })

const [canton] = getCantonsForMunicipality('44088') // merelbeke-melle
getJusticeOfThePeace(canton.id).address // where to file
getCantonsForMunicipality('44021', { on: '2025-09-15' }) // Gent 1–5 on that day: a split city
findCantonsAt(3.7268, 51.053) // [gent-1]: the canton of a point
findCourtsWithJurisdiction('23088', 'police-court') // [police-court-vilvoorde]: which court, by REFNIS code
findCourtsForPostalCode('1040', 'police-court') // per municipality: Brussel and Etterbeek share the code

getInterestRate('2024-06-15', 'legal') // { rate: 5.75, period: { from: '2024-01-01', to: '2024-12-31' } }
getInterestRate(new Date(2014, 5, 15), 'commercial', { contractAfter20130316: true }) // { rate: 8.5, … }
nextWorkingDay('2026-04-04') // '2026-04-07': a deadline ending on a Saturday moves past Easter Monday

Lookups return undefined, [] or null when the data has no answer, so callers can warn instead of silently using 0 %. Malformed days throw a RangeError, and so do lookups for a day before a dataset's coverage.

Import a single dataset to keep bundles small: belgica/interest-rates, belgica/calendar, belgica/courts, belgica/prisons, belgica/houses-of-justice, belgica/territory, belgica/postal-codes. The canton boundaries (a million positions of GeoJSON) are only in belgica/canton-boundaries, the arrondissement boundaries in belgica/arrondissement-boundaries and the court locations in belgica/court-locations; the root never loads them.

The raw files are also exported: import courts from 'belgica/data/courts.json' with { type: 'json' }.

Only the courts you need

JSON can't be tree-shaken, so a browser app ships whichever data files it imports. data/courts.json stays the complete file; the build splits it into smaller ones, published with the package:

| You need | Use | | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | Everything, with lookups and filters | belgica/courts (or the root) | | One court type, all of Belgium | belgica/data/courts/<type>.json, or loadCourts({ type }) | | One type in one arrondissement | belgica/data/courts/<type>/<arrondissement>.json, or loadCourts({ type, arrondissement }) | | One court by a stored id | loadCourt(id): reads data/courts/index.json, then the court's file | | One court's contacts, opening hours, website | belgica/data/courts/details/<id>.json, or loadCourtDetails(id) | | Names and contacts of a court you already hold | belgica/courts/format (formatCourtName, getContact, formatPhoneNumber, formatIban): no data | | Cantons without the legal text of their area | belgica/cantons; the text in belgica/cantons/territory (getCantonTerritory) |

The list files hold summaries (id, type, name, canton label, canton, arrondissement, address, …); the details files the rest. Courts without an arrondissement (a court of appeal, for one) are in data/courts/<type>/judicial-area/<area>.json. The loaders are in belgica/courts/load and use one import() per file, so a bundler makes a chunk of each.

import east from 'belgica/data/courts/justice-of-the-peace/oost-vlaanderen.json' with { type: 'json' }
import west from 'belgica/data/courts/justice-of-the-peace/west-vlaanderen.json' with { type: 'json' }
import { formatCourtName, type CourtSummary } from 'belgica/courts/format'

// A JSON import types `type` and `kind` as string: cast to the summary type
const courts = [...east, ...west] as CourtSummary[]
courts.map((court) => formatCourtName(court, 'nl', { style: 'canton' })) // 'Vredegerecht 1e kanton Gent', …

Bundled for the browser (esbuild, minified, measured on 0.4.0):

| App | Minified | gzip | | -------------------------------------------------------------------- | -------- | ------ | | findCourts + formatCourtName from belgica/courts | 410 KB | 46 KB | | getCanton from belgica/territory | 180 KB | 30 KB | | The two files above + formatCourtName from belgica/courts/format | 15 KB | 2.2 KB |

Python

pip install belgica

The same data and lookups, in snake case, with the same version number: get_cantons_for_municipality('44021', on='2025-09-15'), find_courts_with_jurisdiction('23088', 'police-court'), find_cantons_at(3.7268, 51.053). Python 3.11 or later, no dependencies; the tests check both packages give the same answers. The calendar functions aren't in Python yet. See Python and python/.

Spreadsheets and anything else

Read the JSON files in data/ directly: from the npm package, a git submodule, or a raw URL pinned to a tag (https://raw.githubusercontent.com/pieterjanscheir/belgica/v0.6.2/data/cantons.json). For spreadsheets, take the CSV tables from a release.

How the data is kept up to date

Every Monday the sources workflow fetches every page of the official sources, keeps them as snapshots on the sources branch, rebuilds every scraped dataset from them, tests the result, and opens a pull request when anything changed. A freshness check opens an issue when a new interest rate is missing, a dataset is overdue for review or a source is gone.

pnpm fetch:sources   # the official sources into .sources/
pnpm build:data      # rebuild every scraped dataset from them
pnpm build:cantons   # rebuild cantons and municipalities from the law and Statbel
pnpm check           # everything CI runs

See CONTRIBUTING.md and the data quality page.

Releasing

Ids are public API, so versions follow these rules: adding data is a minor version, fixing a value is a patch, and removing or renaming an id is a major version. A release is prepared by the Prepare release workflow and published to npm and PyPI when its pull request is merged; see releasing.

Known gaps

See known gaps. The main ones: the highest courts aren't on the courts' portal yet, history before 1 January 2025 isn't in the data (lookups for earlier days throw), and split cities need the address's coordinates to pick a canton.

Licence

The code is MIT. The data in data/ is CC BY 4.0: reuse it freely, including commercially, with credit to this project and to the sources listed in datapackage.json. Municipality, province, region and postal-code data © Statbel; canton and arrondissement boundaries and court locations © National Geographic Institute (NGI), both CC BY 4.0.