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

mffontship

v1.1.2

Published

CLI tool to download and manage Google Fonts locally — zero build step, pure ESM.

Readme

mffontship

Download and self-host Google Fonts in one command. Zero build step, pure ESM, Node 18+.

mffontship fetches .woff2 files directly from the Google Fonts API, writes them to disk, and generates a _font-faces.css file alongside a fonts-manifest.json you can commit. It ships a WordPress preset that also injects the @import into your theme's style.css.


Installation

# Use without installing — fonts/ folder created in the current directory
npx mffontship add "Inter" 400,700

# WordPress preset
npx mffontship add "Inter" 400,700 --wordpress

# Or install globally
npm install -g mffontship
mffontship add "Inter" 400,700 --wordpress

Commands

add <family> <weights>

Download a Google Font family and register it locally. <weights> is a comma-separated list of numeric weights.

# No flags needed — creates fonts/ in the current working directory
mffontship add "Inter" 400,700

# WordPress preset — resolves dest automatically from cwd
mffontship add "Inter" 400,500,700 --wordpress

# WordPress with a non-default theme slug
mffontship add "Playfair Display" 400,700 --wordpress --theme="my-theme-child"

# WordPress + italic variants
mffontship add "Inter" 400,700 --wordpress --italic

# Explicit destination folder (no preset)
mffontship add "Inter" 400,700 --dest="path/to/fonts"

# Custom CSS fallback
mffontship add "Playfair Display" 400,700 --dest="fonts" --fallback=serif

# Skip the "MF " prefix — font is stored and referenced as plain "Inter"
mffontship add "Inter" 400,700 --no-prefix

# Preview what would be downloaded — no files written
mffontship add "Inter" 400,700 --wordpress --dry-run

| Flag | Argument | Default | Description | |---|---|---|---| | --wordpress | — | off | Activate the WordPress preset. Resolves the destination to <cwd>/wp-content/themes/<theme>/. Also injects @import "fonts/_font-faces.css"; into style.css after the theme header block (idempotent). | | --theme | <slug> | bb-theme-child | WordPress theme folder name. Only used with --wordpress. | | --dest | <path> | — | Explicit destination folder. Relative to cwd or absolute. Cannot be used together with --wordpress. | | --italic | — | off | Also download italic variants for all specified weights. | | --fallback | <generic> | sans-serif | CSS generic font family written into _font-faces.css (e.g. serif, monospace). | | --no-prefix | — | off | Store the font family name without the MF prefix. By default every family is prefixed — e.g. MF Inter. Pass --no-prefix to register it as plain Inter instead. | | --dry-run | — | off | Print the filenames that would be downloaded without writing anything to disk. |

Writes (relative to dest):

fonts/
  inter/              ← one sub-folder per family slug
    inter-400.woff2
    inter-400-italic.woff2
    inter-700.woff2
  fonts-manifest.json ← tracks all registered fonts; safe to commit
  _font-faces.css     ← auto-generated @font-face rules; do not edit manually

remove <family>

Remove a single font family: deletes its .woff2 directory and regenerates _font-faces.css.

mffontship remove "Inter"
mffontship remove "Inter" --wordpress
mffontship remove "Inter" --dest="path/to/fonts"
mffontship remove "Playfair Display" --wordpress --theme="my-theme-child"

| Flag | Argument | Default | Description | |---|---|---|---| | --wordpress | — | off | Use the WordPress preset to resolve the destination. | | --theme | <slug> | bb-theme-child | WordPress theme folder name. | | --dest | <path> | — | Explicit destination folder. |


list

Print a table of all fonts currently tracked in fonts-manifest.json.

mffontship list
mffontship list --wordpress
mffontship list --dest="path/to/fonts"

| Flag | Argument | Default | Description | |---|---|---|---| | --wordpress | — | off | Use the WordPress preset to resolve the destination. | | --theme | <slug> | bb-theme-child | WordPress theme folder name. | | --dest | <path> | — | Explicit destination folder. |

Example output:

FONT NAME                      WEIGHTS              STYLES
--------------------------------------------------------------------
MF Inter                       400, 500, 700        normal
MF Playfair Display            400, 700             normal, italic

sync

Regenerate _font-faces.css from fonts-manifest.json without re-downloading any files. Use this after manually editing the manifest.

mffontship sync
mffontship sync --wordpress
mffontship sync --dest="path/to/fonts"

| Flag | Argument | Default | Description | |---|---|---|---| | --wordpress | — | off | Use the WordPress preset to resolve the destination. | | --theme | <slug> | bb-theme-child | WordPress theme folder name. | | --dest | <path> | — | Explicit destination folder. |


reset

Remove all registered fonts, delete every .woff2 directory, wipe fonts-manifest.json, and clear _font-faces.css.

mffontship reset
mffontship reset --wordpress
mffontship reset --dest="path/to/fonts"

| Flag | Argument | Default | Description | |---|---|---|---| | --wordpress | — | off | Use the WordPress preset to resolve the destination. | | --theme | <slug> | bb-theme-child | WordPress theme folder name. | | --dest | <path> | — | Explicit destination folder. |


Adding a new preset (Laravel, Next.js, …)

  1. Create src/presets/your-stack.js exporting a plain object:
// src/presets/your-stack.js
import path from 'node:path';

export default {
  resolveDest(cwd, flags) {
    return path.join(cwd, 'resources/fonts');
  },
  afterAdd(dest, flags) {
    // optional — runs after a successful `add`
  },
};
  1. Register it in src/presets/index.js:
import yourStack from './your-stack.js';

const presets = { wordpress, 'your-stack': yourStack };
  1. Call it with --your-stack … or just wire up the flag in bin/mffontship.js. No other code changes required.

Security model

mffontship is a local CLI tool. It does not run install scripts and does not execute shell commands.

Network access is only used when the user explicitly runs mffontship add. The tool fetches CSS from https://fonts.googleapis.com and downloads font files exclusively from https://fonts.gstatic.com. All download URLs are validated at runtime to enforce HTTPS and the exact fonts.gstatic.com hostname — no other host is ever contacted.

Filesystem access is limited to the destination chosen by the user. By default this is a fonts/ folder inside the current working directory. The WordPress preset writes under wp-content/themes/<theme>/fonts/. The --dest flag lets the user point to any path they control — it is intentional user-directed output, not automatic or hidden writes.

No install hooks — the package has no postinstall, preinstall, prepare, or other lifecycle scripts that run automatically when consumers install it.

Code-level safeguards:

  • Path traversal guard — all font directories are validated against the fonts root with realpathSync before any write or delete.
  • CSS sanitisation — family names, file entries, weights, and styles are all validated before being written into _font-faces.css.
  • Atomic writes — manifest and CSS files are written to a .tmp file and renamed atomically.
  • Idempotent WP injection — the @import is never inserted twice.
  • WordPress --theme sanitisation — only letters, numbers, _, and - are accepted; path separators are rejected.

Requirements

  • Node.js ≥ 18 (uses native fetch)

License

MIT