Writing the Perfect Readme for Your Node Library

Add a little of Markdown, sprinkle a little of MDX and you have the perfect recipe

Fernando Doglio
Bits and Pieces
Published in
9 min readMay 3, 2021

--

Image by Szilárd Szabó from Pixabay

There is no substitute for good documentation. The more you document the happier your users will be. There is a point, however, where you start getting diminishing returns. In other words, once you pass a threshold the more you keep documenting the less happy your users will be.

What?

Yeah, you have to find a sweet spot, just enough to explain your project but not too much to overwhelm your user. And when it comes to documenting Node.js modules, then the easiest way to do it is to create a comprehensible Readme file.

The structure of a good ReadMe file

The Readme file is normally the first thing anybody sees in regards to documentation because people would find our modules through NPM’s page, Yarn’s or even looking at our components on Bit’s component marketplace.

With that in mind, there are certain things you need to take into consideration to optimize the reading experience of your potential users (i.e other developers).

What’s the name of your library?

That’s the first thing you need to show. The title of your Readme file has to be the name of your project. That’ll give the user a clear indication that they’ve found what they’re looking for.

You do that using a single # at the start of the line:

# This is the title

Do you have a website with extended documentation?

The second thing you should be showing, if you having it, is the URL for your website. There is no point for your user to keep going through a simplified, and sometimes — even though it shouldn’t — outdated, documentation. If there is a place where they can browse and get all the details they need, make sure you add the link right at the start (some people even add it as part of the title itself):

# My library [www.myurl.com](http://www.myurl.com)

The above line gets rendered into:

What is your project all about?

The first thing your readers need to read, right after the name and URL (if there is one), is a brief description of your project. Keyword there being “brief”. Don’t go all in and explain the motivation behind it, the struggles you went through and the journey you took to get here. Just write a single paragraph explaining what the library is meant to be doing. That’s it, if you want more, you can add a link to an external file where you cover all of that. This is not the place for it.

Installation / requirements

Most Node modules will simply require a quick npm install call. However, some might have other requirements, such as a particular OS, or other utilities to be installed (such as a module depending on ImageMagick for example). Here is where you quickly list all of that.

Using the library

Now it’s time to cover use cases. Start from the easiest one, chances are your users will just copy & paste your example into their code, so don’t over-complicate it.

And use code blocks, most Markdown templates for places where your library will be published will accept language suggestions, so add them and your code will be highlighted:

```js
//A comment
function dummyFunction() {
}
```

That code can be rendered like this thanks to the language suggestion:

Start with the most basic example, and keep increasing the complexity if there are edge cases. Just remember to keep the explanation around them simple, concise and if you need to explain some concepts in-depth, link to other pages.

Contributing to the project

This section is optional, because you might not be interested in other people making contributions, but if you are you have to explain the process here.

Normally you’d want to have some form of process in place because otherwise developers will jump in and send their PR’s in very different ways with very different standards. That in turn means you’ll spend countless hours reviewing them and fixing them to match your coding standards.

So to avoid all that pain, make sure this section is crystal clear and explain:

  • The coding standards you’re using.
  • The content the PR should have (i.e other than the code changes, you probably want unit tests around that, updated documentation, etc).
  • How often you check and review PRs. This is especially useful for people using and needing a certain PR to be approved. Setting the expectations from the get-go will avoid problems with developers thinking they own your time and you should be working full time on your open source pet project.

Make sure to add any other peculiarities you feel like adding here regarding interaction with developers. Maybe for a PR to be valid, you require an issue to be open, then explain that here as well.

By being clear and concise you’re making sure everyone knows how you work and how they need to work if they have any hopes for their contributions to make it to the next release.

Licensing terms

We often forget about this section, but it should be there every, single, time. Learning about Open Source licenses is not that hard, this website for instance makes it very easy for you to pick the right one based on your expectations and needs.

But if you don’t have one, you’re leaving the door open for anyone to do whatever they want with your code. And that can be dangerous, or heck, it can work against you. Maybe you have the library to be used for the next 5 years by all Node developers and you’re giving it away without even knowing.

Take the 5 minutes you need to pick a license and add it at the end of your Readme. You’d normally also add an extra file covering the entire license inside the repo and you can link to that file from this section.

Making your Readme with MDX and Bit

What is Bit?

Bit is a tool for developing, versioning and collaborating on independent components. These are components or modules that are developed in a monorepo-like environment but are each independently versioned and shared. You can read more about it here:

What is MDX?

The MDX format joins together the ease-of-use and readability of the Markdown syntax with the endless possibilities that are offered by JSX. The modularity that’s offered by both technologies (MDX and Bit) enables MDX files to be exported to a remote scope and imported to other web projects, just like any other independent component.

MDX is especially useful for front-end components because MDX allows you to have a live version of your code working directly on the file, but it can also drastically improve the way we document backend component.

For example, Bit’s MDX compiler uses MDX to integrate into its docs, a component that displays the complier’s output (live).

Using meta description

Bit flavored MDX files allow you to add a header with metadata about your article. These pieces of information will then be used as part of the template pre-set for you.

You can define the header like this:

---
displayName: Jwhisper
description: A simple client
labels: ['node.js', 'json', 'communication', 'wsp']
---

That header gets rendered on my component’s documentation like this:

https://bit.dev/deleteman/jwhisper/jwhisper

Anything written after the header of the MDX file is treated as the body of the document.

Writing in multiple files

A big enough component, such as a framework you might want to release could have a lot of information to cover. And if you’re working as part of a team to document every feature it might be a good idea to write everything in different, specific files and then render them all together.

You can do that thanks to MDX through the import statement. Here I show you how I’m writing the documentation for my component and importing two different files containing very specific sections:

---
displayName: Jwhisper
description: A simple client
labels: ['node.js', 'json', 'communication', 'wsp']
---
import Loggerdoc from './logger/logger.docs.mdx'
import UsingExamples from './usingit.docs.mdx'
# What is JWhisper?
JWhisper is the JSON-WSP library built for Node.js.
# Using it
<UsingExamples />
# The internal logger
<Loggerdoc/>

If you’re familiar with React the syntax might sound familiar. I’m importing the two MDX files into two different JSX tags, which are then used below. The imported files don’t have to have any particular syntax, all they need is their actual content (no header required or anything).

Live code examples

I know I mentioned this one before as a benefit for front-end developers, since all their code can be shown as a live playground using MDX, however, we can also create some interesting interactions if we have non-backend-specific code. For instance, I have the following dummy function meant to validate input:

You can have anything else really, as long as it’s not using Node-specific modules, you’re good.

If I wanted to show a little playground for users to understand how to use my input validator, I could add the following to my MDX file:

# Live code example 
import validateInput from './lib/inputValidator.js'
```js live=true
function LiveValidator() {
return <p>{validateInput(23, "number") ? "Is valid" : "Not valid"}</p>
}
```

Notice I’m importing the function before the code block, this is because MDX allows me to import it and then use it anywhere I want. The other key part of the example is the live=true next to the language suggestion, which will turn my example function into an editable block and add an output screen next to it.

Notice the output window on the right. Whatever the live function LiveValidator returns will be rendered on the right.

This is a very useful tool if you have common code that can run on the front-end as well as on the back-end, because you’re literally adding a playground inside your own documentation.

You can check out the full component and its live documentation here on Bit’s site. If you’re new to Bit and would like to know how to use it with Node, I’ve written a great intro tutorial here:

And if you want to dig deeper, Bit allows you to extract sections of your code into individual components. They’re not called modules, because a component is so much more than just the source code. So you could even extract the logger under lib/logger in my example into its own component and ‘export’ (push) it separately as well, keeping the same code repository.

Are you a fan of ReadMes? Or do you prefer a different way of documenting your Node libraries? Leave a comment below with your suggestions and impressions about MDX!

--

--

I write about technology, freelancing and more. Check out my FREE newsletter if you’re into Software Development: https://fernandodoglio.substack.com/