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

@stakme/mdf

v0.11.0

Published

Lightweight utility to organize Markdown files with front matter

Readme

mdf

Organize Markdown knowledge bases with confident, schema-driven front matter.

mdf helps teams and solo note-takers keep Markdown collections consistent. Define the front matter schema you expect, scaffold new notes from templates, audit and repair existing files, and even browse them with an interactive viewer — all from one CLI.

Version status: We're continuing in the 0.x series (latest: 0.10.0) while we collect more feedback before committing to a 1.0 release.

This tool does not enforce any rules on the content of your Markdown files. You can define any schema, organize your files in any way, and use any template to scaffold new files. Although this tool assumes that users will store their Markdown files in a single directory with a flat structure, it is not required.

Highlights

  • Schema-first authoring – enforce exactly the fields, defaults, and content rules you need.
  • Frictionless scaffolding – spin up ready-to-edit Markdown files in one command.
  • Smart filtering – slice notes by front matter attributes and render tailored output.
  • Confident maintenance – validate, update, or auto-fix drifted notes before they reach your repo.
  • Interactive viewer – explore documents in a local web UI with filters and virtual paths.

Installation

npm install --save-dev @stakme/mdf
# or
pnpm add -D @stakme/mdf
# or
yarn add -D @stakme/mdf

Node.js requirement: mdf targets Node 22 and newer.

Add the CLI to your package scripts or run it via npx @stakme/mdf.

Quick start

  1. Create a config: run mdf init to scaffold .config/mdf.mts (or author your own) anywhere under your workspace with a schema describing the front matter every file should include.
  2. Generate a note: run mdf new <directory> and provide overrides with --fm flags or a named template.
  3. Surface the right notes: explore your collection with mdf list filters, virtual-path scoping, and custom output formats.
  4. Browse your notes: start a local viewer with mdf viewer <directory> to navigate and read documents in your browser.

When you are ready to publish new notes, validate the collection with mdf validate or mdf fix.

CLI overview

| Command | Description | | --------------------------- | -------------------------------------------------------------------------------------------------- | | mdf init [directory] | Create a starter .config/mdf.mts in the target directory. | | mdf new <directory> | Scaffold Markdown files that match your schema and optional template defaults. | | mdf list <directory> | Inspect existing notes with virtual-path trees, filters, and custom output templates. | | mdf validate <directory> | Confirm every file conforms to your schema, exiting non-zero when issues arise. | | mdf fix <directory> | Apply schema defaults and CLI overrides in-place to repair invalid notes. | | mdf update <files...> | Update specific front matter keys on targeted files (explicit values or schema/config defaults). | | mdf viewer <directory> | Launch a local web viewer with navigation, filters, and virtual-path scoping. | | mdf export <directory> | Generate a static viewer site for your notes (use --output to choose the destination directory). | | mdf run <alias> [args...] | Execute a configured alias that expands to another mdf command. |

Run any command with --help for the full option list.

Export a static viewer

Use mdf export <directory> when you want to publish the same experience the viewer command provides, but as a static site. The command copies the built viewer assets, writes JSON responses under api/**/index.json that mirror the viewer API, and replicates document filters such as --filter and --vpath. Relative image references are rewritten to serve from documents/<id>/assets/, so the exported site can host local screenshots or diagrams alongside each note.

The output directory defaults to mdf-export, but you can provide your own path with --output. The export reuses --strict and --ignore-invalid flags to match the viewer's parsing behavior. Virtual paths are computed the same way as the live viewer, using your schema resolvers or each document's directory.

Configuration

mdf loads the closest .config/mdf.mts file in the directory tree. Define your schema with Zod and optional helpers:

import { defineConfig, defineSchema, z } from "@stakme/mdf/config";

export default defineConfig({
  schema: {
    default: defineSchema({
      schema: z.object({
        title: z.string(),
        created_at: z.iso.datetime().default(() => new Date().toISOString()),
        updated_at: z.iso.datetime().default(() => new Date().toISOString()),
        status: z.enum(["todo", "in_progress", "done"]).default("todo"),
        tags: z.array(z.string()).default(() => []),
        section: z.string().optional(),
      }),
      vpath: ({ fm }) => (fm.section ? `/${fm.section}` : "/"),
      vslug: ({ fm, relativePath }) =>
        (fm.slug ?? relativePath).replace(/\\.md$/u, ""),
    }),
  },
  defaultSchema: "default",
});
  • schema must be a Zod object describing your front matter. Use defineSchema to attach helpers such as filename, vpath, or vslug resolvers to a schema entry.
  • defaults sets automatic fallback values for fields you omit when creating new notes.
  • content (optional) can generate the Markdown body from template data.
  • fileName (optional) lets you compute the file name from front matter values.
  • aliases (optional) map friendly names to frequently used CLI command fragments for mdf run.

Templates and overrides

Define named templates in your config to reuse curated defaults and starting content. Then apply them on the CLI:

mdf new notes --template meeting --fm tags=sync --fm attendees="Ada, Lin"

Templates layer their front matter on top of schema defaults, while --fm key=value flags win last. Array fields support JSON-style values (["release","planning"]) or repeated flags.

Pass --filename <name> to override the generated file name for a specific note. Omit the extension and .md will be appended automatically.

List, filter, and automate

Use the list command to slice your knowledge base and pipe the output to other tools:

mdf list notes
mdf list notes --filter "vpath ^= backlog"
mdf list notes \
  --filter "status=todo" \
  --filter "tags~=feature" \
  --format "[{{status}}] {{title}} ({{tags:, }})"
  • mdf list renders a tree using each document's virtual path; without a schema override, that mirrors the on-disk directory layout.
  • Provide --filter expressions with = (or :), ~=, ^=, or $= operators for exact, substring, prefix, or suffix matching. Arrays match when any element satisfies the filter.
  • Filters inspect front matter fields. Define a vpath field in your schema or front matter before using --filter "vpath ^= …".
  • Target nested front matter fields with dot notation, such as project.status.
  • Supply --format to bypass the tree and render each match with {{field}} placeholders. Use helpers like {{tags:, }} to join arrays or {{paths.relativePath}} for the file location.

Aliases and shortcuts

Store your favorite command combinations in the config and run them with a short name:

import { defineConfig, defineSchema, z } from "@stakme/mdf/config";

export default defineConfig({
  schema: {
    default: defineSchema({
      schema: z.object({
        title: z.string(),
        status: z.enum(["todo", "in_progress", "done"]),
        vpath: z.string().optional(),
      }),
      vpath: ({ fm }) => fm.vpath ?? "/",
    }),
  },
  defaultSchema: "default",
  aliases: {
    todo: 'list --filter "status=todo" ./TODO',
  },
});
mdf run todo

mdf run expands the alias value into a fresh CLI invocation, so all built-in commands and flags work as if you typed them manually. Aliases can reference other aliases, and the CLI detects cycles to prevent infinite recursion.

Keep notes trustworthy

Run validation before shipping changes, or automatically fix what you can:

mdf validate notes
mdf fix notes --fm status=todo --fm tags=backlog
  • validate reports each valid file and exits with code 0 when everything passes.
  • fix rewrites front matter safely, applying schema defaults and CLI overrides before writing.
  • Both commands honor the file extension and defaults defined in your config.

Update specific files

Use mdf update when you want to change front matter on particular files without touching the rest of the collection:

# Set explicit values and let the schema/config provide defaults
mdf update --fm "status=done" --fm updated_at ./docs/roadmap.md ./docs/intro.md
  • Provide --fm key=value for explicit assignments.
  • Provide --fm key (no value) to ask mdf to fill that key from template/config defaults or the schema’s default.
  • The command validates the final front matter against your schema before writing.

Interactive viewer

Explore your notes in a local web UI:

mdf viewer ./docs --vpath blog --filter "status=done" --port 4173
  • Navigation groups documents by their computed virtual path. Customize this by defining a schema vpath resolver.
  • Supports the same filter expressions as mdf list.
  • Prints the local URL on start (defaults to http://127.0.0.1:4173).
  • Troubleshooting: add --access-log to print per-request access logs.
  • If you experience hanging navigation in certain environments, try --no-reload to disable hot reload (SSE) and file watching.

Programmatic usage

The package also exposes utilities for custom tooling. Import from @stakme/mdf or @stakme/mdf/config inside build scripts, note-taking automations, or editor integrations to reuse the same schema and helper functions as the CLI.

Legal notice

TL;DR: You can use this freely. But no open‑source license right now.

This project is not distributed under an OSI‑approved open‑source license.

  • As of 2025-09-28, you may use this package without notifying or asking the author.
  • I (stakme) am not presently exercising any copyrights in this repository. This is an expression of my current intent and should be read as me not asserting rights at this time.
  • I may change my mind later and adopt a specific license or begin exercising rights for future releases. If that happens, I will update this repository. Any change would apply going forward and is not intended to retroactively change what you already obtained under these terms.

I used AI‑assisted tooling (Codex CLI) extensively while creating this project and therefore cannot make a definitive legal declaration about copyright ownership of every line of code. This does not mean the project is illegal or a copied work: it simply reflects caution about formal legal assertions at this time.

Contributing

I am not accepting contributions at this time, but I welcome issues for feature requests and bug reports.