MDMaurice Däppen.
06

mdstack.

Point it at a folder of markdown and get a rendered static site, in dev or as a deployable build for any static host. Published on npm as @exor404/mdstack.

mdstack.dev
mdstack screenshot
Lines of code
~8.2k
Runtime deps
5
Built-in themes
4
Published

mdstack is a zero-config static-site CLI: point it at a folder of markdown and it either serves the files with hot reload or builds a self-contained dist/ you can deploy to any static host. A thin Node binary scaffolds a config and a homepage on first run, then drives a bundled Astro app that turns every .md into a route, ships every other file untouched, and renders four self-designed themes with server-side math and syntax highlighting.

The CLI is a 154-line Node entry point with hand-rolled argument parsing and zero parsing dependencies. It resolves the target folder, writes a default mdstack.config.js and a starter index.md on first run, validates the theme, then sets MD_SOURCE and MD_THEME in the environment and programmatically invokes Astro's dev, build, or preview APIs against an Astro app that lives inside the package. The user's markdown never enters the package tree: an Astro content collection uses a glob loader rooted at MD_SOURCE, and a catch-all [...slug].astro maps each file to a route, with index.md becoming the homepage and frontmatter title and order driving the nav.

Markdown rendering is extended with three custom remark plugins on top of remark-math and rehype-katex. One rewrites relative image paths to absolute paths from the source root and, importantly, contains them: any target that resolves outside the source folder is rejected, the same path-traversal guard applied byte for byte in the dev asset middleware. A second parses GitHub-style callouts (NOTE, TIP, IMPORTANT, WARNING, CAUTION) into labeled, icon-prefixed blockquotes, and a third turns ==text== into <mark>. Math is rendered server-side via KaTeX, code is highlighted with Shiki using a per-theme palette, and mermaid is loaded lazily through a dynamic import that only fires on pages that actually contain a diagram.

Asset handling is a single Astro integration that does double duty. In dev it installs a Connect middleware that serves any non-markdown file straight from the source folder with correct MIME types, range-safe HEAD handling, and exclusion of dotfiles and build directories. At build time it walks the source tree, copies every non-.md file into dist for a self-contained output, then emits robots.txt always and sitemap.xml when a site URL is configured, while deferring to any user-supplied robots or sitemap. The client layer adds a localStorage theme toggle, an IntersectionObserver scroll-spy table of contents, heading anchor deep-links, and a cmd-K command palette that searches a build-time index of titles, headings, and body prose with highlighted snippet matches.

The package treats publishing as a controlled surface. A prepublishOnly guard runs npm pack in dry-run mode and refuses to publish if the tarball exceeds 500 kB or contains forbidden paths such as node_modules, build output, or the example folder, keeping the shipped CLI lean. The four themes are self-designed from scratch, roughly 3,800 lines of CSS, each paired with a matching Shiki code theme. A separate marketing site, also built with Astro, is containerized with nginx and shipped through a tag-triggered GitHub Actions workflow that builds the image and pushes it to the registry.

PrevThreeJS PortfolioNext flux
All projects