@michaelolof/markdown-serve
v0.1.2
Published
Portable markdown server with clean pathname routing.
Downloads
46
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
/FAQand/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-serveor
npm install -g @michaelolof/markdown-serveThen run it against any directory that contains markdown files:
markdown-serve ./docsFrom this repository
If you are working from a source checkout:
pnpm install
pnpm build
pnpm start -- ./docspnpm 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; defaults to0.0.0.0so other devices on the same local network can connect--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 7000markdown-serve ./docs --port 8080 --title "Project Docs"MARKDOWN_SERVE_PORT=9000 markdown-serve ./docsLocal network access
By default, markdown-serve binds to 0.0.0.0, which makes it reachable from other devices on the same LAN.
When the server starts, it prints a local URL for the current machine and one or more Network: URLs for your active LAN interfaces. Open one of those Network: URLs from another device on the same Wi-Fi or Ethernet network.
Example:
Serving /Users/you/docs
Local: http://127.0.0.1:6450
Network: http://192.168.1.42:6450If another device cannot connect, check the computer's firewall and make sure the chosen port is allowed for incoming connections.
Port configuration
The port number is configurable in three ways.
Precedence order:
--portMARKDOWN_SERVE_PORTPORT- default
6450
Examples:
markdown-serve ./docs --port 7000PORT=7000 markdown-serve ./docsMARKDOWN_SERVE_PORT=7100 markdown-serve ./docsShutdown
Press Ctrl+C or send SIGTERM (kill <pid>) to stop the server. It exits within ~1 second even when a browser tab is open with an active live-reload connection. If the process ever appears stuck, pressing Ctrl+C a second time forces an immediate exit.
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: '0.0.0.0',
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:
createMarkdownServeServerbuildDocsIndexroutePathFromFilePathcreateRouteIndex
Routing behavior
Document routes are mapped by encoded pathname, not by query string.
Examples:
FAQ.md->/FAQguides/Getting Started.md->/guides/Getting%20Startedweird/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
.mdfiles. .git,.github, andnode_modulesare skipped during scanning.- The browser-facing document routes are clean paths; raw markdown is served from internal endpoints used by the viewer.
