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 🙏

© 2025 – Pkg Stats / Ryan Hefner

rhodochrosite

v0.0.13

Published

simple static site generator with neat tagging features including inline hashtags. written in typescript, powered by metalsmith. working on documenting!

Downloads

1,818

Readme

rhodochrosite

make a website for online. powered by metalsmith. try this template project

node package || git repo || my website

install

npm install rhodochrosite

use

npx rhodo build

build the site once

the default source folder is ./src/ and the default folder to build to is ./build/ . everything is relative to the working directory where you run the command. to override these, use the options --src or --dest. npx rhodo --src mysource --dest pathto/mybuild will look in ./mysource/ for source files and output the site in ./pathto/mybuild/

there's also an option --prod to build a "production version" site instead of the dev version - this changes the default destination folder to ./prodbuild/ and excludes pages that are designated as drafts in their frontmatter. theres another option, --clean, that will have it delete the old build before starting a new one - by default, builds are done incrementally. all of these options can also be used with all the other commands! see the options at any time with npx rhodo --help.

npx rhodo watch

keep the build folder updated with changes in the source folder and start a dev server watching it .

use npx rhodo watch --noserver to watch without starting the server. --noserver can also be used with hack

npx rhodo hack

like watch, but also spin up a typescript compiler so you can hack the generator. edit metalsmith.ts and all the files in plugs

you can also install rhodochrosite globally with npm link rhodochrosite or npm i -g rhodochrosite, then the commands become just rhodo build, rhodo watch, rhodo hack and you can use them wherever ! (note, use the option --tsdir to set the directory for the typescript watcher if you're running hack with a global install. point it to node_modules/rhodochrosite, wherever that is on your machine. use npm list -g to find where your global packages are installed if you dont know

features

like stuff the website maker does or can do. actively writing this part rn. the main fun is tags and stuff. i use it "sort of like an obsidian vault but with indeces that get compiled at build time instead of search"

basics

rhodochrosite makes a page for each markdown file in the source directory. the page will be located at a corresponding path in the build directory. ./src/mypage.md will translate to ./build/mypage/index.html. the permalink to this page will be set as mypage/, with the trailing slash. files with the name index.md are treated special: their permalink is set by the parent folder, not the filename. ./src/mypage/index.md will translate to ./build/mypage/index.html. other files just get passed through - locations are 1:1. ./src/mypage/mysong.mp3 will wind up at ./build/mypage/mysong.mp3.

by default, markdown links arent processed at all, it just chucks whatever's between the parentheses right in the href of the resulting html. there's also an option you can set in options.json to make it prepend the page permalink to relative links that dont start with a /, which lets you curve issues that can arise using those kinds of relative links due to this one property of html. like, let's say you're in your source folder, editing /blog/firstpost/index.md, and you want to embed an image thats at /blog/firstpost/image.png. if you typed ![my alt text](image.png), you'd get some html like <img src="image.png" alt="my alt text">. in the build folder (aka the static website,) this would work fine from /blog/firstpost/, since the browser would see its location as the directory /blog/firstpost/ and go looking for /blog/firstpost/image.png accordingly. but if you were at /blog/firstpost without the trailing slash, the browser would see itself at /blog/ and go looking for the image in the wrong place, at /blog/image.png. so by automatically adding the rest of the path from / back on to the beginning, we get an unambiguous location in the link, which now looks like this: <img src="/blog/firstpost/image.png" alt="my alt text">. but you still dont have to type that whole path out in your .md files !

tags/collections

rhodochrosite uses metalsmith's collections plugin in three ways. the first two are regular stuff the plugin can already do:

pattern collections

pass some options into the collections plugin from options.json to make a pattern collection. all pages matching the pattern will be added to the collection. other options can also be passed in.

frontmatter

a page can be added to a collection by specifying the collection in the pages frontmatter like so:

---
collection: [mycollection, myothercollection]
---

inline tags

the third way is a special rhodo thing. its inline tags ! type a tag in the body of the page like so - #mytag . the page will be added to the "mytag" collection automatically! the tag will also be turned into a link to that tag's tag page.

tag pages

rhodochrosite also uses collections to make tag pages, which index the collections by displaying a list of all posts in the collection on that page, with titles, links and excerpts. tag pages can be specified in the frontmatter: if a page includes the following,

---
pagetag: mytag
---

then that page will become the mytag tag page, listing all the pages in the mytag collection below the body content. also, if the file's name was mytag.md in the source folder, that would also make it the same tag page, because the file name (which becomes the permalink slug) matches a tag. frontmatter pagetags will override file names - if mypage.md had pagetag: "mytag" in the frontmatter, it would be the tag page for mytag, not mypage.

if there's no specified tag page for a given collection, rhodochrosite will generate a tag page at /tags/mytag/ . this way, all you have to do at minimum is write #mytag somewhere, and all the rest gets taken care of - but on the other hand if you want more control, you can just add stuff manually and the automatic parts will gracefully avoid it. don't give two different pages the same pagetag, it messes everything up as of now, and they should be unique anyway because when you write an inline tag the link needs a specific place to go. if you want to list out a collection that already has a tag page somewhere else, write some nunjucks in the markdown file. ill put an example of this in the template project later.

subtags

subtags are like tags, but they apply to list items within a page instead of whole pages, and the index just appears at the bottom of that one page. to add a subtag, include it in a child item in a markdown list, like this:

---
- my lovely item
    - ##subtag ##anothersubtag
---

image mini

rhodochrosite uses sharp to resize pngs and jpgs, by default to just a comfy width for browsing. use a gallery span as defined below to wrap an image in a link to its full-res original, or link to the original yourself - for myimage.png , rhodochrosite will resize it in place and put the full-res copy at myimage_orig.png alongside it in the same folder. this way the links all shake out intuitively

gallery pages

rhodochrosite can make nice image galleries on a static page, using lazy loading and anchor links. set up the page like this:

---
type: gallery 
---

<span class="gal">

- ![](image.png)
    - ##subtag ##more
- ![alt text](anotherimage.png)
    - description ##subtag ##another

</span>

(note the markdown parser needs blank lines around the html.) subtags will render the images as fun little thumbnails in the index ! also, images will be wrapped in a link to their full-resolution originals.

feeds

the site will have an rss feed and an atom feed located at /feed.xml and /atom.xml respectively. the feed is generated from the #update collection, which also has the first 3 entries appear on the homepage. this way you can make a feed of the latest updates that pulls in from all different areas of the site.

now page

the now page is a special page in terms of the rss feed, because it changes its GUID every time it's updated. this should make it appear as unread each time it's updated in many readers, at the expense of possibly also leaving the old version in the reader's backlog. i think of each now page update like a "semi-disappearing post."

last modified dates

rhodochrosite sets the last-modified date of each page automatically based on the last-modified date of the markdown file on your computer. these are used to order some collections and the feeds, and are displayed on the pages. if you want to override it, set "mod" to a date in the frontmatter:

---
mod: 2024-01-30
---

and the last-modified date of the page will be set to that date instead of the automatic one. if your website is a git repo and git keeps messing with the mtimes: try git-restore-mtime. thats how i do it !

passthru copies

set "ignores" to some patterns in options.json and files that match the patterns won't enter the metalsmith build. instead, rhodochrosite will pass them through to the build folder separately. this can speed things up for large files and by working incrementally - if the file is already there in the build folder, rhodochrosite won't overwrite it unless it's newer. it could also be used to keep some html files from being indexed or altered, or to not process some images, for example.

buckets

activate by setting the type "bucket" in the frontmatter of a markdown file

---
type: bucket
---

buckets are a type of page where it automatically embeds media files (right now just pngs, mp3s and mp4s) that are in the same folder in the source directory one after the other on the page, unless you already embedded them in there yourself in the page content in which case it doesnt. i frankly dont use this anymore cause i tend to maintian a list of markdown embeds for each of my media galleries. maybe ill depricate it or do something neat with it eventually

options

include a file called options.json in the working directory to set some options as follows:

  • "sitename": "my lovely website",
    • the name of your site !
  • "url": "https://example.url/",
    • the base url of your site, which all permalinks are appended to
  • "author": "me",
    • for the feeds
  • "width": 960,
    • rhodochrosite uses a one-column layout - this sets the width of the column in pixels
  • "version": 0.1,
    • this is for css versioning. increment this when you want peoples' browsers to reload your css the next time they visit.
  • "fontpath": "/assets/fonts/myfont.woof/",
    • you can set one font to preload so the page load looks better. totally optional, fonts linked in css will still work without using this
  • "bannerimg": "/assets/img/mybanner.png"
    • put a banner image at the top of every page
  • "stylepath": "/assets/css/userstyles.css",
    • relative to the source folder, the path to a file where you can put your own css to override or augment the site styling. link other css files, fonts etc from this one with @import. this default will work if you don't set one.
  • "ignores": ["**/*.zip", "**/*.mp3", "**/*.mp4"],
    • glob patterns that will be ignored by metalsmith, instead being passed through to the build folder unaltered.
"navs": [
    {"title": "map", "link": "/map/"},
    {"title": "tags", "link": "/tags/"},
    {"title": "updates", "link": "/tags/update/"},
    {"title": "now", "link": "/now/"},
    {"title": "home", "link": "/"},
    {"title": "rss", "link": "/rss/"}
],
  • navs (as above)
    • set the bottom nav bar items
  • "footertext": "try some <a href='/'>html</a>",
    • add custom text to the footer
"collections": {
    "update": {
        "sortBy": "stats.mtimeMs", "reverse": true
    },
    "tags": { "pattern": ["tags/**/*.html", "!tags/index.html"] },
    "all": { "pattern": ["**/*.html"], "sortBy": "stats.mtimeMs", "reverse": true }
},
  • collections (as above)

  • "tagline": "check it out!",

    • optional tagline which appears below the title/banner image
  • "absolute": false

    • set this to true to prepend the page permalink to relative urls that dont start with /

styling

as mentioned above, you can include a stylesheet to add your own css, either by putting a file at "/assets/css/userstyles.css" (relative to the source directory) or specifying your own location and putting one there. building on that, you can easily create your own color scheme for the site by setting a handful of variables. to do so, include this somewhere in your css:

/*main color scheme light mode colors*/
:root {
    --color-main: #303030;
    --color-second: #696969;
    --color-bold: #a05656;
    --color-em: #519676;
    --color-header: #336779;
    --link-main: #5378ce;
    --link-second: #276821;
    --bg-main: #f3f2f7;
    --bg-second: #c8c8e0;
    --bg-third: #e4e7ec;
    --bg-glass: #f2f3f799;
    --second-glass: #cac8e055;
  }
  
  /*main color scheme dark mode colors*/
  @media (prefers-color-scheme: dark) {
    :root{
    --color-main: #ebebeb;
    --color-second: #b3b3b3;
    --color-bold: #9bc248;
    --color-em: #ecaeae;
    --color-header: #b49090;
    --link-main: #9aadf8;
    --link-second: #f9c8ff;
    --tagline-color: #e8c7ee;
    --bg-main: #03040c;
    --bg-second: #282c4d;
    --bg-third: #12151f;
    --bg-glass: #03040c99;
    --second-glass:#12121f77;
    }
  }

and then set the colors to whatever you like! the first block defines the light-mode color scheme and the second defines the dark-mode :)