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

mahtis

v0.5.1

Published

Readme

mahtis

A small collection of things I keep rewriting: prefixed sortable IDs, a handful of React hooks and a shared Prettier config. Written in TypeScript, shipped as ESM and CJS.

Install

pnpm add mahtis

react is a peer dependency and only needed for mahtis/hooks and mahtis/react.

Entrypoints

There is no root import, pick the subpath you need.

| Import | Contents | Runtime | | ----------------- | --------------------------------- | ----------- | | mahtis/mika | Prefixed, sortable, decodable IDs | Node | | mahtis/id | Random string IDs | Anywhere | | mahtis/hooks | React hooks | Browser | | mahtis/react | React helpers | Browser | | mahtis/prettier | Shared Prettier config | Config only |

mahtis/mika

IDs like user_NjEyNzIzOTE4MDQwMzEzODU3: a readable prefix plus a snowflake, so every ID sorts by creation time and can be decoded back into its parts.

import { Mika } from 'mahtis/mika';

const mika = new Mika(['user', { prefix: 'invite', secure: true }]);

const id = mika.gen('user'); // user_NjEyNzIzOTE4MDQwMzEzODU3
mika.validate(id, 'user'); // true
mika.decode(id); // { prefix: 'user', timestamp: 1787079965920n, nodeId: 731, seq: 1, ... }

Prefixes marked secure: true get 16 extra random bytes, so they cannot be guessed from a neighbouring ID. Use that for invite codes and share links.

The registered prefixes drive the types, which you can reuse:

import type { InferIds } from 'mahtis/mika';

type Id = InferIds<typeof mika>; // `user_${string}` | `invite_${string}`

Constructor options:

| Option | Default | Purpose | | ------------------------ | -------------------- | --------------------------------------------- | | epoch | Jan 1 2022 | Point in time IDs are counted from | | nodeId | derived from the MAC | 0 to 1023, one per process writing to the set | | suppressPrefixWarnings | false | Silences warnings for unregistered prefixes |

Keep epoch stable once IDs exist, every ID is decoded against it.

mahtis/id

import { generateId } from 'mahtis/id';

generateId(); // Zkas5DRK8hM3NOSqAJkE
generateId(8); // EQCOrzY8
generateId(8, 'abcdef0123456789');

Backed by Math.random, so it is fine for keys and handles, not for secrets.

mahtis/hooks

import { useDebounce, useIsOnline, useDynamicTextSize } from 'mahtis/hooks';

const { debouncedValue } = useDebounce(query, 300);
const online = useIsOnline();
const { fontSize, isMultiline, textRef } = useDynamicTextSize(title, 320);

mahtis/react

provideReact turns an async function into React state, refetching whenever the arguments change and ignoring results of outdated calls.

import { provideReact } from 'mahtis/react';

const { data, error, isLoading, mutate } = provideReact(fetchUser, userId);

mahtis/prettier

{
	"prettier": "mahtis/prettier"
}

License

MIT