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

@webpieces/docs-site

v0.4.977

Published

Render a static, three-pane API reference site from any OpenAPI 3.0-or-3.1 document plus a directory of markdown prose. Node builtins only. Ships the wp-docs-site bin.

Readme

@webpieces/docs-site

A static, three-pane API reference site from any OpenAPI 3.0-or-3.1 document.

wp-docs-site --spec path/to/public-openapi.json --prose path/to/docs --out path/to/site
wp-docs-site --spec path/to/public-openapi.json --out path/to/site --serve

Node builtins only — no framework, no markdown library, no bundler. Adding an API reference to your project does not grow your dependency surface, and this package's own build is tsc.

What you get

site/
  index.html                          the overview: info.title, info.summary under it, info.description, plus every tag and its operations
  styles.css  site.js                 one stylesheet, one script
  prose/<kebab-title>/index.html      one per page docs.manifest.json names, in ITS order
  reference/<kebab-operationId>/index.html
  schemas/<kebab-name>/index.html     one per named OBJECT dto

An operation's request or response body written INLINE — as @webpieces/openapi-generator writes a single-use …Request / …Response wrapper (#1303) — has no schema page: the operation page heads the body with its title (the name a generated client gives the model) and description, then its fields.

Each operation page is HEADED, and its sidebar link LABELLED, with the operation's summary — its short human title (#1296) — and shows the operationId beside the method and path as the code identifier a generated client names the method by. The page's URL is kebabed from the operationId, so rewording a title never moves a bookmarked link. A document that states no summary falls back to the operationId, then the path or event name.

One PRE-RENDERED file per URL. A deep link resolves without JavaScript, the folder works on any static host (and under a path prefix, and over file://), and a JSDoc edit shows up as a diff on the one page it affects. The client script does three things only: disclosure state, the language tabs, and the theme.

The prose directory

{
    "title": "Example Orders API",
    "pages": [
        { "file": "getting-started.md", "title": "Getting started" },
        { "file": "authentication.md", "title": "Authentication" }
    ]
}

The order of pages is the published order. So is the document's tags[] for the reference. Neither is sorted — alphabetising either reorders what a partner reads first.

A page the manifest names but the directory does not hold fails the run. A markdown file the manifest does NOT name is simply not published: the manifest is the published list.

The markdown is a documented SUBSET of CommonMark — headings, fenced code, tables, lists, blockquotes, rules, paragraphs, and inline code / **bold** / *italic* / [links](url) — over trusted, PR-reviewed input. Everything is HTML-escaped before any mark is applied.

A code span that exactly names an operationId, or a schema that has its own page (or a member of one, `Menu.items`), renders as a LINK to that page (#1284) — which is how a JSDoc {@link}, published by wp-openapi as a code span of its target's published name, becomes a hyperlink. A name that is both an operationId and a schema, an inlined request/response wrapper (it has no page), and every other code span stays plain code.

Reading the reference

  • Every tag is its own nav section. A tag missing from the sidebar is an operation a partner cannot find, which reads exactly like an operation that does not exist.
  • A webhook files into the section of the tag it shares, appended after that tag's operations and badged, with no method, no path and no code samples. The url is yours, not ours.
  • A oneOf request body renders every branch expanded and labelled by its discriminator value — never tabbed, because a tab is invisible to Ctrl-F and to print.
  • A named object DTO gets its own page, and every reference to it is a LINK. The generated example body resolves the same reference fully, because a hyperlink cannot live in a JSON sample.
  • An enum shows the COMPLETE Possible values: chip line, inline, with no page of its own.
  • A nullable field shows the NON-null type; a format renders as string<date-time>.

Code samples

Built FROM THE SPEC — the server url, the path, the header names your securitySchemes declare, and an example body generated from the request schema — in HTTP, JavaScript, Go and Java. Nothing is authored per operation, so a rename cannot leave a partner pasting a header the server stopped reading.

The languages are labelled in words. The gopher and the Java cup are other companies' trademarks.

--serve is a preview, not a host

It binds 127.0.0.1 and nothing else. It is not hardened and not authenticated: no logging, no rate limiting, no TLS, no access control. Put the generated FOLDER on a real static host.

It does not depend on the generator

This package does not import @webpieces/openapi-generator, even though the two model the same document. A compile-time dependency would make "generated by us" a precondition for "renderable by us". The document is read structurally, and the suite renders a 3.0 document written in 3.0's dialect to keep that honest. See responsibilities.md.