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

prefont

v0.3.0

Published

Pre-measure font character widths in real browsers, then compute text widths anywhere — including Node, SSR, edge runtimes, and workers where no DOM is available.

Readme

prefont

Pre-measure font character widths in real browsers, then compute text widths anywhere — including Node, SSR, edge runtimes, and workers where no DOM is available.

prefont ships a CLI that loads your fonts in Chromium, Firefox, and/or WebKit, measures the advance width of every character you care about, and writes the result to a JSON file. A tiny client library then turns that data into pixel-accurate text widths at any font size — without touching the DOM.

Install

npm install prefont
# or
pnpm add prefont

Requires Node.js >= 20.

You will also need browser binaries for the engines you measure in:

npx playwright install chromium firefox webkit

Quick start

  1. Create .prefontrc.json at the root of your project:

    {
      "$schema": "./node_modules/prefont/schema.json",
      "browsers": ["chromium", "firefox", "webkit"],
      "symbolSets": [{ "name": "default", "chars": "0123456789. " }],
      "fonts": [
        {
          "font": "https://fonts.googleapis.com/css2?family=Inter:wght@400&display=block",
          "family": "Inter",
          "weights": [400]
        }
      ]
    }
  2. Run the CLI to measure and write the data file:

    npx prefont

    By default this writes prefont.json.

  3. Use the data at runtime:

    import data from "./prefont.json" with { type: "json" };
    import { measureTextFromData } from "prefont";
    
    const width = measureTextFromData(data, {
      family: "Inter",
      browser: "chromium",
      weight: 400,
      text: "1.234",
      fontSize: 16,
    });
    // → pixel width matching what Chromium would render

CLI

prefont [--config <path>]

| Flag | Default | Description | | ---------------- | ----------------- | ------------------------------------------------------------ | | -c, --config | .prefontrc.json | Path to the config file (relative to the working directory). |

The CLI resolves font paths relative to the config file, launches the requested browsers in parallel, measures each font/weight/symbol-set combination, and writes a single JSON file to the configured out path.

Configuration

.prefontrc.json is validated against schema.json, so editors with JSON Schema support get autocomplete and inline docs.

| Field | Type | Description | | ------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------- | | out | string | Output path for the generated data, relative to the config file. Defaults to prefont.json. | | browsers | ("chromium" \| "firefox" \| "webkit")[] | Default browsers used to measure every font. | | symbolSets | { name, chars }[] | Reusable groups of characters to measure. Each font measures every set unless overridden. | | fonts | FontItem[] | Fonts to measure (see below). |

FontItem

| Field | Type | Description | | ------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | font | string | Local file path (.woff2, .woff, .ttf, .otf) or a URL. URLs to font files are inlined as @font-face; URLs to stylesheets (e.g. Google Fonts CSS) are loaded via <link>. Local paths are resolved relative to the config file and embedded as data URLs. | | family | string | CSS font-family name to register and measure. | | weights | number[] | Weights to measure (1–1000, e.g. 400, 700). | | browsers | BrowserName[]? | Override the top-level browsers for this font. | | symbolSets | string[]? | Names of top-level symbolSets to use for this font. Defaults to all of them. |

Example

{
  "$schema": "./node_modules/prefont/schema.json",
  "out": "prefont.json",
  "browsers": ["chromium", "firefox", "webkit"],
  "symbolSets": [
    { "name": "digits", "chars": "0123456789. " },
    {
      "name": "ascii",
      "chars": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    }
  ],
  "fonts": [
    {
      "font": "fonts/Inter-Variable.woff2",
      "family": "Inter",
      "weights": [400, 600, 700]
    },
    {
      "font": "https://fonts.googleapis.com/css2?family=Roboto:wght@400&display=block",
      "family": "Roboto",
      "weights": [400],
      "symbolSets": ["digits"]
    }
  ]
}

API

All exports are available from the package root:

import {
  measureText,
  measureTextFromData,
  measureTextFromCanvas,
  measureTextAllWeights,
} from "prefont";

measureText(opts)

Isomorphic helper. In a browser (when document is defined) it measures live via <canvas>. In Node/SSR it falls back to the prebuilt data.

measureText({
  family: "Inter",
  weight: 400,
  text: "1.234",
  fontSize: 16,
  // required outside the browser:
  data,
  browser: "chromium",
  // optional: width to use for any character missing from the measured set
  fallback: " ",
}); // → number

measureTextFromData(data, opts)

Pure function. Computes the width of text at fontSize using widths captured for family / browser / weight. Accepts an optional fallback character whose width substitutes for any character not present in the data.

measureTextFromCanvas(opts)

Browser-only. Measures text using a hidden <canvas> for the currently loaded font. Also accepts fallback.

measureTextAllWeights(data, opts)

Returns { [weight]: pixelWidth } for every weight measured for the given family on the given browser. Accepts fallback.

License

Apache-2.0. See LICENSE.