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

@tw-labs/countries

v0.0.2

Published

Comprehensive country data with utilities and React hook — tree-shakeable, TypeScript-first, framework-agnostic

Readme

@tw-labs/countries

Comprehensive country data with utilities and an optional React hook.

TypeScript-first · Framework-agnostic · Tree-shakeable · Zero dependencies

npm version License: MIT TypeScript Tree Shakeable Next.js


Features

  • 195+ countries — ISO alpha-2/alpha-3 codes, name, phone dial code, capital, continent, currency, and timezones
  • Flag support — emoji flags, PNG (20px, 40px), and SVG via flagcdn.com
  • Tree-shakeable — import only the countries you need via the /data subpath
  • Framework-agnostic core — works in Node.js, Vue, Svelte, and anywhere else
  • React hookuseCountries with filtering, sorting, and conditional flag types
  • Next.js ready"use client" built into the React entry, core works in Server Components
  • TypeScript-first — full type safety and IntelliSense out of the box
  • Zero dependencies — no runtime dependencies

Installation

npm install @tw-labs/countries
yarn add @tw-labs/countries
pnpm add @tw-labs/countries
bun add @tw-labs/countries

Import Paths

| Path | Use case | |---|---| | @tw-labs/countries | Framework-agnostic utilities (Node, Vue, Svelte, Next.js server) | | @tw-labs/countries/react | React hook (useCountries) | | @tw-labs/countries/data | Named country exports — fully tree-shakeable |


Core Utilities

import {
  getAllCountries,
  getAllCountriesWithFlags,
  getCountryByCode,
  getCountryByAlpha3,
  getCountryByPhone,
  withFlags,
} from "@tw-labs/countries";

getCountryByCode(code)

const country = getCountryByCode("US");
// {
//   code: "US",
//   alpha3: "USA",
//   label: "United States",
//   phone: "1",
//   capital: "Washington, D.C.",
//   continent: "North America",
//   currency: { code: "USD", symbol: "$", name: "United States Dollar" },
//   timezones: ["America/New_York", "America/Chicago", ...]
// }

getCountryByAlpha3(alpha3)

const country = getCountryByAlpha3("GBR");
// { code: "GB", alpha3: "GBR", label: "United Kingdom", ... }

getCountryByPhone(phone)

Returns an array since multiple countries can share a dial code.

const countries = getCountryByPhone("1");
// [{ code: "US", ... }, { code: "CA", ... }, { code: "PR", ... }, ...]

getAllCountries(options?)

// All countries
const all = getAllCountries();

// Filtered
const european = getAllCountries({
  filter: (c) => c.continent === "Europe",
});

// Sorted
const sorted = getAllCountries({
  sort: { by: "label", order: "asc" },
});

// Filtered + sorted
const result = getAllCountries({
  filter: (c) => c.continent === "Asia",
  sort: { by: "label", order: "asc" },
});

getAllCountriesWithFlags(options?)

Same as getAllCountries but each country includes flag data.

const countries = getAllCountriesWithFlags();
// Each country has: flagEmoji, flagPng20, flagPng40, flagSvg, srcSet

withFlags(country)

Add flag data to a single country object.

const country = getCountryByCode("JP");
const withFlagData = withFlags(country!);
// { ...country, flagEmoji: "🇯🇵", flagPng20: "...", flagSvg: "...", ... }

Tree-Shakeable Data Imports

For the best bundle size when you know your countries at build time:

import { US, GB, DE, FR } from "@tw-labs/countries/data";
// Only these 4 country objects are included in your bundle

Note: getCountryByCode("US") is for runtime dynamic lookups and includes the full dataset. Use the /data subpath when the country codes are known at build time.


React Hook

import { useCountries } from "@tw-labs/countries/react";

The @tw-labs/countries/react entry has "use client" built in — no need to add it yourself in Next.js.

Basic usage

function CountryList() {
  const countries = useCountries({});

  return (
    <ul>
      {countries.map((c) => (
        <li key={c.code}>
          {c.label} (+{c.phone})
        </li>
      ))}
    </ul>
  );
}

With flags

function FlagList() {
  const countries = useCountries({ includeFlags: true });
  // TypeScript knows each country has flagEmoji, flagPng20, etc.

  return (
    <div>
      {countries.map((c) => (
        <div key={c.code}>
          <span>{c.flagEmoji}</span>
          <img src={c.flagPng40} alt={`${c.label} flag`} />
          <span>{c.label}</span>
        </div>
      ))}
    </div>
  );
}

With filtering and sorting

function SearchableCountryPicker() {
  const [query, setQuery] = useState("");

  const countries = useCountries({
    includeFlags: true,
    filter: query
      ? (c) =>
          c.label.toLowerCase().includes(query.toLowerCase()) ||
          c.code.toLowerCase().includes(query.toLowerCase()) ||
          c.phone.includes(query)
      : undefined,
    sort: { by: "label", order: "asc" },
  });

  return (
    <div>
      <input
        placeholder="Search countries..."
        value={query}
        onChange={(e) => setQuery(e.target.value)}
      />
      <p>{countries.length} results</p>
      {countries.map((c) => (
        <div key={c.code}>
          {c.flagEmoji} {c.label} (+{c.phone})
        </div>
      ))}
    </div>
  );
}

Sort options

useCountries({ sort: { by: "label",     order: "asc" } }); // A → Z by name
useCountries({ sort: { by: "code",      order: "asc" } }); // AD → ZW
useCountries({ sort: { by: "phone",     order: "asc" } }); // by dial code
useCountries({ sort: { by: "continent", order: "asc" } }); // grouped by continent

Next.js Usage

// app/components/PhoneInput.tsx — Client Component
// No need to add "use client" manually — it's built into @tw-labs/countries/react
import { useCountries } from "@tw-labs/countries/react";

// app/api/validate/route.ts — Server Component / Route Handler
// Works with no configuration — no "use client" in the core entry
import { getCountryByCode } from "@tw-labs/countries";

TypeScript Types

import type {
  Country,
  CountryWithFlags,
  Currency,
  FilterSortOptions,
  SortBy,
} from "@tw-labs/countries";

type Currency = {
  code: string;    // "USD"
  symbol: string;  // "$"
  name: string;    // "United States Dollar"
};

type Country = {
  code: string;        // ISO alpha-2  "US"
  alpha3: string;      // ISO alpha-3  "USA"
  label: string;       // "United States"
  phone: string;       // "1"
  capital: string;     // "Washington, D.C."
  continent: string;   // "North America"
  currency: Currency;
  timezones: string[]; // ["America/New_York", ...]
};

type CountryWithFlags = Country & {
  flagEmoji: string;   // "🇺🇸"
  flagPng20: string;   // https://flagcdn.com/w20/us.png
  flagPng40: string;   // https://flagcdn.com/w40/us.png
  flagSvg: string;     // https://flagcdn.com/us.svg
  srcSet: string;      // https://flagcdn.com/w40/us.png 2x
};

License

MIT © TechWebster