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

twtxt-lib

v0.10.0

Published

An isomorphic TypeScript library of utility functions for parsing and interacting with twtxt.txt files.

Readme

twtxt-lib

An isomorphic TypeScript library of utility functions for parsing and interacting with twtxt.txt files.

These functions include:

  • hashTwt: takes the constituent parts of a "twt" and generates an extension-compatible hash for it.
  • parseTwtxt: parses a twtxt file string, returning an object with information about the file and its owner (including hashes for each twt and any metadata in the file).
  • loadAndParseTwtxt: fetches a twtxt file from the internet and parses it into an object (as above).

Features

Installation

This library can be installed several different ways:

For the Browser

  1. Grab the latest copy of the twtxt-lib.js file, either by downloading it from the git repo, the website, or by doing a git clone https://git.itsericwoodward.com/eric/twtxt-lib.git and pulling it out of the dist-browser folder.
    • Alternatively, you can grab the minified version from the same sources.
  2. Add the newly acquired file to your static site / progressive web app / over-engineered blog.
  3. Import the desired function(s) via ESM: import { hashTwt, loadAndParseTwtxtFile } from "./twtxt-lib.js";

For Node

  1. Add the package to your project.
    • Via NPM: yarn add twtxt-lib
    • Via JSR: yarn add jsr:@itsericwoodward/twtxt-lib
  2. Import the desired function(s) via ESM: import { hashTwt, loadAndParseTwtxtFile, parseTwtxt } from "twtxt-lib";

Usage

See the included tests and demo file for more information on how to use it.

hashTwt

A function that takes the constituent parts of a "twt" and generates an extension-compatible hash for it, which is then returned.

Version 0.10.0 and above includes support for V2 of the Hashing Spec:

  • A specific hashing version can be provided as an optional argument.
  • When no version argument is provided, it defaults to using version 1 for all twts with a created date before the epoch date (2026-07-01T00:00:00Z), and version 2 for all twts created on or after the epoch.
import { hashTwt } from "/web/dist/twtxt-lib.js";

const hash = hashTwt({
    content: "Prow scuttle parley provost Sail ho shrouds spirits boom mizzenmast yardarm.",
    created: "2026-02-01T01:23:45Z",
    url: "https://example.org/~pirate/twtxt.txt",
});

console.log(`Hash: ${hash}`);

Result

Hash: 7uftieq

parseTwtxt

A function that parses a twtxt file string, returning an object with information about the file and its owner (including generating hashes for each twt and any metadata in the file).

import { base32Encode, hashTwt, loadAndParseTwtxt, parseTwtxt } from "twtxt-lib";

const fileText = `
# nick = demo_sagan
# url = https://example.net/~saganos/twtxt.txt
# avatar = https://i.pravatar.cc/150?img=69
# description = Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit?
# finger = [email protected]
# link = Web https://example.net/~saganos/
#
# follow = demo_sagan https://example.net/~saganos/twtxt.txt
# follow = demo_pirate https://example.org/~pirate/twtxt.txt
# follow = demo_hipster https://example.com/demo-hipster-twtxt.txt
#
# following = 3
#

2026-02-05T23:17:47Z	The ash of stellar alchemy permanence of the stars extraordinary claims require extraordinary evidence rings of Uranus vanquish the impossible encyclopaedia galactica?
2026-01-22T12:09:44Z	Something incredible is waiting to be known another world hearts of the stars tendrils of gossamer clouds a still more glorious dawn awaits venture.
2026-01-10T13:44:37Z	Dream of the mind's eye citizens of distant epochs a still more glorious dawn awaits preserve and cherish that pale blue dot hearts of the stars preserve and cherish that pale blue dot and billions upon billions upon billions upon billions upon billions upon billions upon billions.
2026-01-01T02:05:04Z	With pretty stories for which there's little good evidence muse about a billion trillion globular star cluster inconspicuous motes of rock and gas dream of the mind's eye.
`.trim();

console.log(parseTwtxt(fileText));

Result:

{
  "following": [
    {
      "nick": "demo_sagan",
      "url": "https://example.net/~saganos/twtxt.txt"
    },
    {
      "nick": "demo_pirate",
      "url": "https://example.org/~pirate/twtxt.txt"
    },
    {
      "nick": "demo_hipster",
      "url": "https://example.com/demo-hipster-twtxt.txt"
    }
  ],
  "metadata": {
    "nick": "demo_sagan",
    "url": "https://example.net/~saganos/twtxt.txt",
    "avatar": "https://i.pravatar.cc/150?img=69",
    "description": "Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit?",
    "finger": "[email protected]",
    "link": "Web https://example.net/~saganos/",
    "following": "3"
  },
  "twts": [
    {
      "content": "With pretty stories for which there's little good evidence muse about a billion trillion globular star cluster inconspicuous motes of rock and gas dream of the mind's eye.",
      "created": "2026-01-01T02:05:04Z",
      "createdUTC": "2026-01-01T02:05:04.000Z",
      "hash": "64wq3va"
    },
    {
      "content": "Dream of the mind's eye citizens of distant epochs a still more glorious dawn awaits preserve and cherish that pale blue dot hearts of the stars preserve and cherish that pale blue dot and billions upon billions upon billions upon billions upon billions upon billions upon billions.",
      "created": "2026-01-10T13:44:37Z",
      "createdUTC": "2026-01-10T13:44:37.000Z",
      "hash": "72vgpyq"
    },
    {
      "content": "Something incredible is waiting to be known another world hearts of the stars tendrils of gossamer clouds a still more glorious dawn awaits venture.",
      "created": "2026-01-22T12:09:44Z",
      "createdUTC": "2026-01-22T12:09:44.000Z",
      "hash": "bgg5rqq"
    },
    {
      "content": "The ash of stellar alchemy permanence of the stars extraordinary claims require extraordinary evidence rings of Uranus vanquish the impossible encyclopaedia galactica?",
      "created": "2026-02-05T23:17:47Z",
      "createdUTC": "2026-02-05T23:17:47.000Z",
      "hash": "qa4xrla"
    }
  ]
}

loadAndParseText

Aan async function that fetches a twtxt.txt-compatible file from a URL and parses it, returning the extracted data as an object.

import { loadAndParseTwtxtFile } from "/web/dist/twtxt-lib.js";

// run in an IIFE (or event listener) to avoid issues with top-level await
(async () => {
    try {
        const parsedFile = await loadAndParseTwtxtFile(
            "/twtxt-demos/demo-hipster-twtxt.txt",
        );

        console.log(parsedFile);

    } catch (err) {
        console.error(err);
    }
})();

Result:

{
  "following": [
    {
      "nick": "demo_hipster",
      "url": "https://example.com/demo-hipster-twtxt.txt"
    },
    {
      "nick": "demo_pirate",
      "url": "https://example.org/~pirate/twtxt.txt"
    },
    {
      "nick": "demo_sagan",
      "url": "https://example.net/~saganos/twtxt.txt"
    }
  ],
  "metadata": {
    "nick": "demo_hipster",
    "url": "https://example.com/demo-hipster-twtxt.txt",
    "avatar": "https://i.pravatar.cc/150?img=67",
    "description": "Kitsch ut post-ironic, bruh tilde non shabby chic iceland fixie consequat?"
  },
  "twts": [
    {
      "content": "Normcore tilde ad selfies, culpa cupping nostrud gatekeep aesthetic PBR&B 3 wolf moon mustache twee.",
      "created": "2025-06-02T18:47:01+01:00",
      "createdUTC": "2025-06-02T17:47:01.000Z",
      "hash": "ymiydvq"
    },
    {
      "content": "Cardigan jean shorts eu 90's. Kitsch knausgaard culpa, marfa mumblecore portland raclette banjo retro exercitation pariatur snackwave williamsburg.",
      "created": "2025-07-05T00:17:46+02:00",
      "createdUTC": "2025-07-04T22:17:46.000Z",
      "hash": "c6bm4sq"
    },
    ...
  ],
  "lastModified": "2026-02-22T20:56:59.000Z"
}

When using in a web browser, be aware of the potential for issues with Cross-Origin Resource Sharing (CORS).

License

Copyright (c) 2026 Eric Woodward, released under the MIT License.