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

@amritk/generate-markdown

v0.4.1

Published

Generate markdown documentation from JSON Schemas.

Readme

@amritk/generate-markdown

Generate markdown documentation from JSON Schemas.

status  version  license  JSON Schema  node  vibe coded


Overview

@amritk/generate-markdown renders a configuration reference table from a config.schema.json file and writes the result to README.md. It exists so the documentation for a CLI's flags can be regenerated from the schema itself, keeping the two in sync.

For every property it reads the standard JSON Schema keywords:

  • type — shown in the Type column
  • description — the first paragraph fills the full-width detail row
  • default — shown (quoted/JSON-encoded) in the Default column
  • enum — listed as Allowed: values in the detail row
  • examples — listed as Examples: values in the detail row
  • required — the parent's required array drives the Required column

Schemas built from references work too. $ref pointers are resolved against the document's $defs (any #/… JSON pointer, in fact) before rendering, recursive definitions are detected and collapsed so generation always terminates, and sibling keywords on a $ref node — typically description — override the referenced definition. When a property describes its type through enum, const, or anyOf/oneOf/allOf rather than a plain type, the Type column shows an inferred label (e.g. string or number | string).

…plus two non-standard keywords for richer output:

  • x-cli-flag — the matching CLI flag (e.g. --schema <path>), shown in the CLI Flag column
  • x-icon — an emoji shown next to the property name

Columns and icons are only rendered when the schema actually uses them. The CLI Flag, Required, and Default columns are each dropped entirely when no property anywhere in the schema fills them, and a property with no x-icon simply shows no icon. There are no placeholders: a cell with nothing to say is left empty. The check spans the whole schema (including nested objects), so every table keeps the same set of columns.

Object properties with their own properties are linked to a nested detail table rendered below the main one.


Installation

npm install @amritk/generate-markdown
# or
pnpm add @amritk/generate-markdown
# or
yarn add @amritk/generate-markdown
# or
bun add @amritk/generate-markdown

Usage

import { generateMarkdown } from '@amritk/generate-markdown'

await generateMarkdown()
// Reads ./config.schema.json from process.cwd()
// Writes ./README.md

If README.md already exists and contains the marker comments below, only the content between them is replaced — everything else in the file is preserved:

<!-- config-table-start -->
<!-- config-table-end -->

Without markers (or without an existing README) the file is overwritten with just the table.


Examples

Each example below shows an input config.schema.json and the markdown generateMarkdown() produces from it.

Defaults of every type

Defaults are rendered in the Default column. Strings are quoted; numbers and booleans are printed bare; objects and arrays are JSON-encoded. None of these properties use a CLI flag or are required, so those columns are dropped — only Property, Type, and Default remain.

{
  "title": "Defaults",
  "properties": {
    "outDir":  { "type": "string",  "default": "./generated", "x-icon": "📁", "description": "Output directory." },
    "port":    { "type": "number",  "default": 8080, "x-icon": "🔌", "description": "Port to listen on." },
    "minify":  { "type": "boolean", "default": false, "x-icon": "🗜️", "description": "Minify the output." },
    "include": { "type": "array",   "default": ["**/*.ts"], "x-icon": "📥", "description": "Glob patterns to include." },
    "env":     { "type": "object",  "default": { "NODE_ENV": "production" }, "x-icon": "🌱", "description": "Environment variables." }
  }
}

Generated markdown:

Enums and examples

enum becomes an Allowed: line and examples becomes an Examples: line, both appended to the property's detail row beneath the description.

{
  "title": "Input",
  "required": ["input"],
  "properties": {
    "input": {
      "type": "string",
      "enum": ["json", "zod", "typebox"],
      "default": "json",
      "x-cli-flag": "--input <format>",
      "x-icon": "🔌",
      "description": "Source format of the schema.",
      "examples": ["json", "zod"]
    }
  }
}

Generated markdown:

Required properties and CLI flags

A property name appears in the Required column (✅) when it is listed in the object's required array. x-cli-flag fills the CLI Flag column, and x-icon sits next to the name. Neither property sets a default, so the Default column is dropped; the outFile row, which isn't required, leaves the Required cell empty rather than printing a placeholder.

{
  "title": "RequiredFlags",
  "required": ["schema"],
  "properties": {
    "schema":  { "type": "string", "x-cli-flag": "--schema <path>", "x-icon": "📄", "description": "Path to the schema to process.", "examples": ["./schema.json"] },
    "outFile": { "type": "string", "x-cli-flag": "--out-file <file>", "x-icon": "📄", "description": "Write everything to a single file." }
  }
}

Generated markdown:

Nested objects

An object property that declares its own properties is linked to a detail table rendered below the main one. The nested table uses the object's own required array, so required markers are scoped to each level.

{
  "title": "Nested",
  "properties": {
    "server": {
      "type": "object",
      "x-icon": "🖥️",
      "description": "HTTP server settings.",
      "required": ["host"],
      "properties": {
        "host": { "type": "string", "x-icon": "🌐", "description": "Hostname to bind." },
        "port": { "type": "number", "x-icon": "🔌", "default": 3000, "description": "Port to listen on." }
      }
    }
  }
}

Generated markdown:

server

References and definitions

$ref pointers are inlined from $defs before rendering, so a schema assembled from reusable definitions produces the same tables as an inline one. Sibling keywords on a $ref (here x-icon and description) override the definition, and a property whose type comes from enum (logLevel) gets an inferred Type.

{
  "title": "Refs",
  "required": ["server"],
  "properties": {
    "server": { "$ref": "#/$defs/server", "x-icon": "🖥️", "description": "HTTP server settings." },
    "logLevel": { "$ref": "#/$defs/logLevel", "x-icon": "🔊" }
  },
  "$defs": {
    "server": {
      "type": "object",
      "required": ["host"],
      "properties": {
        "host": { "type": "string", "x-icon": "🌐", "description": "Hostname to bind." },
        "port": { "type": "number", "x-icon": "🔌", "default": 3000, "description": "Port to listen on." }
      }
    },
    "logLevel": {
      "enum": ["debug", "info", "warn", "error"],
      "default": "info",
      "description": "Minimum log level to emit."
    }
  }
}

Generated markdown:

server


API

generateMarkdown(): Promise<void>

No arguments. Reads from ${cwd}/config.schema.json and writes to ${cwd}/README.md.


Related packages


License

MIT