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

nihonpost

v0.3.0

Published

🗾 Japanese postal code → address lookup for Vue 3. TypeScript-first, zero-config via CDN or fully self-hosted/offline, self-updating data.

Downloads

487

Readme

🗾 nihonpost

Japanese postal code → address lookup for Vue 3. TypeScript-first · works out of the box · fully self-hostable (offline, zero third-party calls) · self-updating data · handles 〒 and full-width input

〒150-0002  →  { prefecture: "東京都", city: "渋谷区", town: "渋谷" }

Why nihonpost?

Every Japanese web form needs 郵便番号 → 住所 autofill. Your options today:

| | API-based (zipcloud etc.) | yubinbango-core2 | nihonpost | |---|---|---|---| | Works offline / no third-party dependency | ❌ | ✅ | ✅ when self-hosted | | Zero-config first run (CDN fallback) | — | ❌ | ✅ | | TypeScript types | ❌ | ❌ | ✅ | | Vue 3 composable | ❌ | ❌ | ✅ | | Promise-based | ❌ | ❌ (callbacks) | ✅ | | Full-width & 〒 input normalization | ❌ | partial | ✅ | | Full-width kana output (シブヤ not シブヤ) | ❌ | ❌ | ✅ | | Data auto-updated monthly via CI | — | ❌ | ✅ |

Install

npm i nihonpost

Quick start (Vue 3)

<script setup lang="ts">
import { usePostalCode } from 'nihonpost/vue'

const { code, address, loading, notFound } = usePostalCode()
</script>

<template>
  <label>郵便番号</label>
  <input v-model="code" placeholder="150-0002" />

  <span v-if="loading">検索中…</span>
  <span v-if="notFound">該当する住所が見つかりません</span>

  <template v-if="address">
    <input :value="address.prefecture" readonly />
    <input :value="address.city" readonly />
    <input :value="address.town" readonly />
  </template>
</template>

That's it. The composable watches code, normalizes whatever the user types (〒150ー0002 works), and fills address the moment 7 digits exist.

Composable API

const {
  code,        // Ref<string>            — bind to your input
  normalized,  // ComputedRef<string|null> — "1500002" when valid
  address,     // ComputedRef<JpAddress|null> — first match
  addresses,   // ShallowRef<JpAddress[]> — all matches (some codes span 2 cities!)
  loading,     // Ref<boolean>
  notFound,    // Ref<boolean>           — valid code, no match
  error,       // Ref<Error|null>
  search,      // (value?) => Promise<JpAddress|null> — manual trigger
  reset,       // () => void
} = usePostalCode({
  auto: true,      // lookup automatically at 7 digits (default)
  debounce: 0,     // ms; rarely needed since length is fixed
})

Framework-agnostic core

No Vue? Use the core directly:

import { lookup, lookupAll, formatPostalCode } from 'nihonpost'

const addr = await lookup('150-0002')
// { prefecture: '東京都', city: '渋谷区', town: '渋谷',
//   prefectureKana: 'トウキョウト', cityKana: 'シブヤク', townKana: 'シブヤ',
//   prefectureCode: 13 }

await lookupAll('4980000')
// → 2 results: 愛知県弥富市 AND 三重県桑名郡木曽岬町 (shared codes are real!)

formatPostalCode('1500002') // "150-0002"

Data loading

The dataset (~124k codes) is chunked by the first 3 digits into ~900 small JSON files — your app loads only the chunks it touches, a few KB each.

Zero config: it works out of the box. With no setup, lookups fetch chunks from the jsDelivr CDN, pinned to your installed nihonpost version (a one-time console.info reminds you this is happening). Upgrading the package automatically moves the pin — nothing goes stale.

// Equivalent explicit form, if you prefer no console notice:
import { configureLoader, cdnLoader } from 'nihonpost'
configureLoader(cdnLoader())

Self-hosting (offline, intranet, CSP, privacy policies): copy node_modules/nihonpost/data into your static assets and point the loader at it once, at app startup:

import { configureLoader, fetchLoader } from 'nihonpost'

configureLoader(fetchLoader('/nihonpost-data'))
// lookups now GET /nihonpost-data/150.json etc., cached after first hit

Vite example — add to vite.config.ts:

import { viteStaticCopy } from 'vite-plugin-static-copy'

plugins: [
  viteStaticCopy({
    targets: [{ src: 'node_modules/nihonpost/data/*', dest: 'nihonpost-data' }],
  }),
]

Any static host works too (GitHub Pages, Cloudflare Pages, S3). It's static files — there is no API server anywhere.

Bundle size note: none of this data ever enters your JS bundle. The browser fetches only the chunks a lookup touches — a few KB each, cached after the first hit. The full ~11 MB exists only in node_modules (and travels as a 1.9 MB tarball).

Custom sources implement one function:

configureLoader(async (prefix) => {
  const res = await fetch(`https://cdn.example.com/jp-postal/${prefix}.json`)
  return res.ok ? res.json() : null
})

Rebuilding the data yourself

npm run build:data              # downloads latest utf_ken_all from Japan Post
npm run build:data -- ./my.csv  # or use a local copy

The pipeline handles KEN_ALL's sharp edges: multi-row 町域 continuation merging, parenthetical annotation stripping, 「以下に掲載がない場合」 placeholders, half-width → full-width kana, and deduplication.

A GitHub Action rebuilds the data on the 1st of every month and publishes a patch release automatically — installs stay current without a server.

Notes & limits

  • Postal codes resolve to town (町域) level — that's how Japan's postal system works. Users still type the block/building portion themselves.
  • Some codes map to multiple municipalities; address gives the first, addresses gives all. Offer a picker if you need precision.
  • Data source: Japan Post 郵便番号データ (public data).

License

MIT © Thiyagu Arunachalam