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

@michaelolof/markdown-serve

v0.1.0

Published

Portable markdown server with clean pathname routing.

Readme

@michaelolof/markdown-serve

@michaelolof/markdown-serve is a portable markdown viewer for serving a directory of .md files as a standalone local website with clean pathname routing.

It keeps the current markdown viewer behavior intact while removing the old make, manifest.json, and Python HTTP server requirements.

Features

  • Clean document routes such as /FAQ and /guides/Getting%20Started
  • Filename-safe routing for spaces, Unicode, #, %, and other URL-sensitive characters
  • Automatic refresh when the currently open markdown file changes on disk
  • Sidebar document tree, heading legend, in-document search, code highlighting, and Mermaid rendering
  • CLI binary for local or global installation
  • Programmatic server API for embedding in other tools

Installation

Global install

If the package is published, install it globally with your package manager of choice:

pnpm add -g @michaelolof/markdown-serve

or

npm install -g @michaelolof/markdown-serve

Then run it against any directory that contains markdown files:

markdown-serve ./docs

From this repository

If you are working from a source checkout:

pnpm install
pnpm build
pnpm start -- ./docs

pnpm build is required in a source checkout because the viewer assets are emitted into dist/viewer.

CLI usage

markdown-serve [directory] [options]

Options:

  • --port <number>: bind the server to a specific port
  • --host <address>: bind to a specific host interface
  • --title <text>: override the viewer title shown in the UI
  • --open: open the viewer in the default browser after startup
  • --help: print usage help

Examples:

markdown-serve ./docs --port 7000
markdown-serve ./docs --host 0.0.0.0 --port 8080 --title "Project Docs"
MARKDOWN_SERVE_PORT=9000 markdown-serve ./docs

Port configuration

The port number is configurable in three ways.

Precedence order:

  1. --port
  2. MARKDOWN_SERVE_PORT
  3. PORT
  4. default 6450

Examples:

markdown-serve ./docs --port 7000
PORT=7000 markdown-serve ./docs
MARKDOWN_SERVE_PORT=7100 markdown-serve ./docs

Programmatic usage

markdown-serve also exposes a small Node API.

import { startMarkdownServeServer } from '@michaelolof/markdown-serve';

const { url, server } = await startMarkdownServeServer({
	rootDir: '/absolute/path/to/docs',
	port: 7000,
	host: '127.0.0.1',
	title: 'Project Docs',
});

console.log(url);

process.on('SIGINT', () => {
	server.close(() => process.exit(0));
});

You can also use the lower-level exports for route generation and document indexing:

  • createMarkdownServeServer
  • buildDocsIndex
  • routePathFromFilePath
  • createRouteIndex

Routing behavior

Document routes are mapped by encoded pathname, not by query string.

Examples:

  • FAQ.md -> /FAQ
  • guides/Getting Started.md -> /guides/Getting%20Started
  • weird/naïve #topic%.md -> /weird/na%C3%AFve%20%23topic%25

This preserves the real filename and avoids collisions caused by lossy slug generation.

Live refresh behavior

markdown-serve automatically watches the markdown file that is currently open in the browser.

When that file changes on disk, the viewer fetches the latest content and rerenders the open document without a full page reload.

Current scope:

  • The open document refreshes automatically when it changes.
  • Files that are not currently open are not watched.
  • The sidebar tree does not live-refresh for newly added, renamed, or deleted files until the page reloads.

Notes

  • The server recursively scans for .md files.
  • .git, .github, and node_modules are skipped during scanning.
  • The browser-facing document routes are clean paths; raw markdown is served from internal endpoints used by the viewer.