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.2.41

Published

simple static site generator with neat mind-mapping features including inline hashtags and automatic tag pages. also utility features like image minification, gallery pages and pre-configured rss/atom feeds. written in typescript, powered by metalsmith. w

Downloads

522

Readme

rhodochrosite

node package || git repo || discord || my website

rhodochrosite is a batteries-included, mind-mappy, multimedia-forward static site generator for node.js, built on metalsmith, with a tiny command-line interface to control it. it transforms a folder-tree of markdown files and attachments into a static, no-javascript html website, featuring blog and art gallery layouts, inline and property-based tags, rss and atom feeds, automatic image processing with sharp, and customizable layouts and styling using njk, html and css. it also includes a pre-configured dev server using five server, for testing and live-previewing the site. builds are highly incremental, and changes update quickly!

install

to install rhodochrosite, first install node.js and npm. next, create or choose a project folder. this will be the root directory of your website project; throughout this guide, this folder will be assumed to be the current working directory, and paths will be written relative to it. if you're starting a new project, this can just be a new blank folder; or, you can download a copy of this template project, and use the outermost folder rhodo-template . in any case, navigate to the folder in a terminal and use the command:

npm install rhodochrosite

to install. (if you'd rather install globally, use npm install rhodochrosite -g ; but you'll need to pass some extra options to some of the commands.)

usage

rhodochrosite is controlled via a little cli made in commander.js. to use it, navigate to your project folder and use the command:

npx rhodo

to show a list of all commands and options. commands follow the syntax npx rhodo command --option value . some basic commands:

npx rhodo build: build the site once and stop, using default folder names

npx rhodo watch: watch the source folder for changes and continually update the build folder; also start a dev server for live-previewing the site in a web browser.

npx rhodo build -p: build a "production version" of the site, omitting drafts, to a different default location

source files

rhodochrosite looks for markdown files to transform into web pages. a markdown file is a text file with the extension .md . markdown files for rhodochrosite have two parts, frontmatter and a body.

frontmatter

frontmatter appears at the beginning of a markdown file, between two special lines made of three hyphens. frontmatter is used in markdown files in the source to set properties of the corresponding page in the build. here is a complete example frontmatter section:

---
title: my first blog post
tags: [recipe, soup]
---

this sets one property, the page's title, to "my first blog post," and adds a couple of tags (another property) - "recipe" and "soup".

body

this is the rest of the markdown file; it can contain paragraphs of text, code blocks, markdown links and embedded-image links, bits of inline html or njk, etc. for an overview of markdown syntax, start here

building the site

when building the site, rhodochrosite looks in the project folder for a source folder (called src by default) and uses it to create a build folder (called build by default) containing the finished website. each markdown file in the source folder becomes a web page on the resulting site, consisting of a folder and an index.html file.

each page has two main sections, a body and an index. the page body is where the transformed body of the markdown file is displayed; this can be paragraphs of text, links, embedded media, etc, as written in by the user.

following the body is the page index, which shows a list of titles and excerpts of other pages. which pages are listed is determined in two ways: using the folder tree, and using tags. this part is generated automatically by rhodochrosite.

the folder tree

the structure of subfolders in the source folder determines the corresponding web page's location on the site: the file src/blog/mypost.md would wind up at mywebsite.com/blog/mypost/ . since web pages in rhodochrosite consist of a folder and an index.html file, in the build folder this page would actually look like this: build/blog/mypost/index.html . but because of how web browsers look at things, the index.html part doesn't appear in the web address - just the folder name. this folder name, created from the name of the markdown file in the source folder, is a property of the page called its slug.

to recap this transformation: a folder has been created with the same name as the markdown file, and the contents of the markdown file have been transformed into an html webpage and moved to a file called index.html inside the folder. (links are also updated as necessary to work with the folder change.)

if a markdown file is named index.md, it gets special treatment. it's still transformed to index.html, but instead of being placed in a new folder, this file simply stays in place and becomes the index.html of its existing parent folder. so for example, src/blog/index.md becomes a page at mywebsite.com/blog/, with the slug blog . in the build folder, it looks like build/blog/index.html .

the structure of the surrounding folder tree of pages is the first of two criteria for building a page's index section. since each page consists of a folder (with the name being that page's slug) and an index.html file, pages can contain other pages. for example, and combining our earlier examples, the page mywebsite.com/blog/ (build/blog/index.html) contains the page mywebsite.com/blog/mypost/ (build/blog/mypost/index.html) in the folder part of its page structure. when a page contains another page like this, that inner page will be included in the outer page's index section.

  • src/
    • blog/
      • index.md
      • mypost.md
  • build/
    • blog/
      • index.html
      • mypost/
        • index.html

this shows a basic blog setup. each blog post starts as a markdown file like src/blog/mypost.md and becomes a page like mysite.com/blog/mypost/, nested within the outer page mysite.com/blog/; and that outer page, that started as src/blog/index.md, indexes all the posts because they're one level down in the folder tree of pages. actually, it's not even necessary to include that src/blog/index.md file in the source folder - if rhodochrosite sees a folder which contains pages, but has no index.md to transform, it will automatically create an index page there instead. pagination is also added to the footer of each post, for navigating to next/previous entries.

of course, the inner pages could be folders, too - in our example, src/blog/mypost.md could be replaced with src/blog/mypost/index.md and get the same results. this makes for a nice way to bundle attachments; say our blog post includes an image, we might structure the source folder so that src/blog/mypost/ includes both src/blog/mypost/index.md and src/blog/mypost/mypic.png . then we can link to the image like so in the markdown file:

![my alt text](mypic.png)

and, since the inner page is now a folder itself, it can contain and index yet more pages nested one level deeper; and those could contain further pages and so on, as deep as you like. indexing goes exactly one level deeper starting at the current page; mysite.com/media/ indexes mysite.com/media/books/ but not mysite.com/media/books/fiction/, mysite.com/media/books/ indexes mysite.com/media/books/fiction/ but not mysite.com/media/books/fiction/romance/, and so on. here's one valid example of how all that could look:

  • src/

    • media/
      • index.md
      • books/
        • fiction/
          • index.md
          • romance.md
  • build/

    • media/
      • index.html
      • books/
        • index.html
        • fiction/
          • index.html
          • romance/
            • index.html

and since every page in the finished site has an index.html file, we can just assume they're all there, and omit them in our digram to simplify its appearance; leaving only the nested structure of pages on the site.

  • mysite.com/
    • media/
      • books/
        • fiction/
          • romance/

tags

the second criteria for building a page's index section is tags. tags are a way of identifying a page for inclusion in another page's index, based on a property of that other page called its tagslug. they can be used in two ways, inline and in frontmatter.

tagslugs

tagslugs are the receiving counterpart to tags; if page A's tagslug matches any tags on any other page B, page B will be included in page A's index section. tags mark a page to be listed by another page, and tagslugs tell a page which other pages to list. by default, a page's tagslug is just its slug, but something else can be specified in frontmatter. if src/cookbook.md had this frontmatter:

---
title: my cookbook
tagslug: recipe
---

then the page mysite.com/cookbook/ would have the slug "cookbook" and the tagslug "recipe". if it had no frontmatter, both the slug and the tagslug would be "cookbook".

tagslugs should be unique for everything to work right. slugs, on the other hand, don't need to be unique; two pages with the same slug can coexist, so long as they're in different folders. if two pages have the same slug, and neither one has a different tagslug set in the frontmatter, rhodochrosite will add the rest of the path to the beginning of one page's tagslug, separated by hyphens. if the pages are nested at different depths, it will default to altering the tagslug of the more-deeply-nested page. take this website, for example:

  • mysite.com/
    • books/
      • sff/
        • scifi/
        • fantasy/
    • movies/
      • horror/
      • scifi/

in this site, two pages have the slug scifi. since books/sff/scifi/ is more deeply nested, its tagslug will be updated to books-sff-scifi. (if two pages with duplicate slugs are nested at the same depth in different places, one is picked to alter more or less arbitrarily. when using tags in conjunction with duplicate page slugs, specify your own tagslugs in frontmatter to avoid confusion.)

inline tags

to use a tag inline, simply include it in the body of a markdown file following the # character, so that it appears in the body of a page. say src/blog/goodsoup.md includes the text

here's the #recipe for my great soup

somewhere in its body. then the page mysite.com/blog/goodsoup/ will have the tag "recipe" as one of its properties. if that tag matches any page's tagslug, for example, our mysite.com/cookbook/ from earlier, then mysite.com/blog/goodsoup/ will appear listed in mysite.com/cookbook/'s index section. also, the inline tag itself in the body of mysite.com/blog/goodsoup/ will be made into a link to mysite.com/cookbook/ .

frontmatter tags

tags can also be included in frontmatter, by setting the "tag" or "tags" property. multiple tags must be enclosed by brackets. examples:

---
tag: soup
---
---
tag: [soup, carrot, broccoli]
---

automatic tag pages

let's say mysite.com/blog/goodsoup/ has the tag "recipe," and "recipe" does not match any page's tagslug. then, a new page will be made at mysite.com/tags/recipe/ . this page will list mysite.com/blog/goodsoup/ in its index section, as well as any other pages with the tag "recipe". so, inline tags can be used even when no page would exist to index them; again, necessary index pages are created automatically. all that's needed to initialize a new tag is to include it in a page for the first time !

lists

markdown in rhodochrosite (and most implementations) includes a syntax for ordered and unordered lists; rhodochrosite also includes task lists. in addition to normal usage, rhodochrosite uses list syntax for two special purposes: gallery pages and subtags. a basic unordered list somewhere in the body of a markdown file, using hyphens for delimiters and tabs for indentation, could appear like this:

- milk
- eggs
- fruit
    - bananas
    - apples
        - red delicious
- bread

gallery pages

rhodochrosite can apply some special formatting to a page for making a media gallery. to set up a gallery page, first set the page type (another property of the page) to "gallery" in the markdown file's frontmatter like so:

---
type: gallery
---

then, enclose parts of the markdown file's body in an html span with the class gal, like so:

---
title: my picture gallery
type: gallery
---

<span class="gal">

- ![my alt text](mypics/myimage.png)
    - this is my favorite picture :)
- ![more alt text](mypics/secondimage.png)
    - this is another picture i like 

</span>

---

(note that, in our markdown files, inline html must be surrounded with a blank line on either side.) within the span, a gallery is written as a markdown list. each top-level list item is a media item in the gallery; in the above example, they're embedded images. list items nested beneath these can be used to provide titles or other text below the image. other media types can be included with html embeds like so:


<span class="gal">

- <video controls src="video.mp4">title of my video</video>

    - this is a video i took 
- [title of my audio](mysounds/myaudio.mp3)

    - <audio controls src="mysounds/myaudio.mp3">my audio alt text</audio>

    - this is a sound i recorded! 

</span>

in the second item here, the top-level item is a text link to the file, and the embed appears below it. this accomplishes basically the same thing, it just puts a little more visual emphasis on the title.

subtags

subtags are like tags, except instead of applying to a whole page, they apply to just one list item within the page; and instead of being indexed somewhere else, they're indexed right there in the same page's footer. subtags allow us to make little bundles of list items within a single page, just as tags allow us to make bundles of pages within the website.

to use a subtag, include it in an indented list item following a double hash mark, ## . the subtag will be applied to the outer list item within which that indented item is nested. for example, take a markdown file in the source folder which contains this list:

- milk
    - ##dairy
- eggs
- butter
    - ##dairy 
    - ##yellow
- produce
    - apples 
        - this is a ##red ##fruit
    - tomatoes
        - ##red 
    - bananas
        - this is a ##fruit
        - this is ##yellow

in this example, the list item milk has the subtag dairy, the list item apples has the subtags red and fruit, and so on. here's the subtag index that would be generated for the above list, and appear in the footer of the page that contains the list:

subtag index

##dairy

milk, butter

##yellow

butter

##red

apples, tomatoes

##fruit

apples

the subtags system uses URI fragments to make links for jumping around the page. every entry in the subtag index (milk, butter and so on) is a link to its corresponding list item, and every subtag in the list is made into a link to its corresponding header in the subtag index.

subtag index entries are usually rendered as the full text of the list item. if the item is a piece of media embedded with html like the examples shown in the gallery section, rhodochrosite will use the text between the html tags to render the entry. for example, this list:

- <video controls src="myvideo.mp4">my favorite skating video</video>

    - ##skateboarding

would generate this subtag index:

subtag index

##skateboarding

my favorite skating video

thumbnails

if subtags are used on a gallery of images, something fun happens: instead of the usual text links, the entries in the subtag index are rendered as thumbnails of the images. for this to work, the page type should be set to gallery, and images should be embedded using markdown syntax. here's our previous example gallery updated to include some subtags:

---
title: my picture gallery
type: gallery
---

<span class="gal">

- ![my alt text](mypics/myimage.png)
    - this is my favorite picture :)
    - ##sunset ##ocean
- ![more alt text](mypics/secondimage.png)
    - this is another ##sunset picture i like
    - ##mountain ##winter

</span>

---

this arrangement will generate a subtag index with image thumbnails instead of text links!

further reading

this guide aims to get one up and running, explain the main features and define some terms; but it doesn't cover everything. the old readme had some more information, but this guide is formatted better; still, it's available until i put together some more extensive documentation

CLI commands and options

Options:
-V, --version             output the version number
-s, --src <source>        custom source directory
-d, --dest <destination>  custom build directory
-n, --noserver            do not start dev server
-p, --prod                build the production version
-c --clean                delete the previous build before building
-t --tsdir <ts-dir>        set root dir for typescript watcher
-o --noopen               server does not open new browser tab when starting
-h, --help                display help for command

Commands:
build                     build the site once
watch                     watch the source folder for changes and keep the build folder updated correspondingly - also start a dev server
hack                      watch the typescript for changes, use this for hacking the generator
help [command]            display help for command