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

@scalar/asyncapi-to-markdown

v0.2.2

Published

Create plain Markdown from AsyncAPI documents (for LLMs)

Readme

Scalar AsyncAPI to Markdown

Generate LLM-friendly Markdown from AsyncAPI descriptions without rendering HTML or Vue.

npm install @scalar/asyncapi-to-markdown
import {
  createAsyncApiMarkdownRenderer,
  createMarkdownFromAsyncApi,
} from '@scalar/asyncapi-to-markdown'

const markdown = await createMarkdownFromAsyncApi('./asyncapi.yaml')

// Load, upgrade and bundle references once for a documentation build.
const renderer = await createAsyncApiMarkdownRenderer('./asyncapi.yaml')
await renderer.render() // Complete description
await renderer.render({ introduction: true })
await renderer.render({ channel: 'orders' })
await renderer.render({ operation: 'receiveOrder' })
await renderer.render({ message: 'OrderCreated' })
await renderer.render({ model: 'Order' })
await renderer.render({ tag: 'Orders' })
await renderer.render({
  message: { pointer: '#/channels/orders/messages/created' },
})

The Node.js entry point accepts objects, JSON/YAML strings, file paths, and HTTP(S) URLs. Relative external references resolve against the source file or URL. Object and inline string inputs need absolute external references. AsyncAPI 1.0–1.2, 2.0–2.6, 3.0 and 3.1 inputs use Scalar's upgrader to produce a 3.1 document. The original version stays visible in the introduction. Input objects are not modified. Create a new renderer to pick up source changes; rendering pages does not fetch the source again.

Choose at most one selector per call. Strings identify exact, case-sensitive map keys: channels, operations, component messages, or component schemas. Channel addresses and human-readable titles are not selectors. Every map selector also accepts an exact JSON pointer, with optional # and standard ~0 / ~1 escaping. Message pointers can select channel messages as well as component messages. Invalid or missing selections reject that call; the renderer remains usable afterward.

Operation pages include the channel address, parameters, relevant servers, security, selected messages, and reply details. Unknown channel addresses are labelled explicitly. Reply messages are rendered only when declared; request messages are not inferred as replies. Channel pages include their operations and all channel messages. Selected pages expand each shared schema once and include transitive schema dependencies. Introduction pages contain API metadata, the application identifier, default content type, and servers. Complete exports include channels, operations, component messages and schemas. Send/receive direction is from the described application's perspective; legacy publish/subscribe operations are migrated accordingly.

Message and operation traits are merged before rendering. Authored examples are preserved. Missing examples are generated from JSON schemas and labelled by context (Generated headers example or Generated payload example). XML payloads use XML examples, including examples authored on their schemas, while headers use JSON. Repeated generated examples link to their first occurrence within the same media type and context. JSON Schema and AsyncAPI schemas include properties, required markers, constraints, composition, discriminator fields and mappings, and recursive-reference notices. Property types and annotations share one line, followed by their Markdown descriptions and external documentation links. Content encoding and media-type annotations are preserved. Other schema formats, such as Avro and Protobuf, appear as labelled source blocks. Protocol bindings are preserved as JSON. Descriptions preserve Markdown, tables and code blocks using the same sanitization as the OpenAPI converter; images are excluded.

Navigation and shared models

Complete exports include a contents index with explicit anchors. Shared structured models render once and their usages link to that definition. Declared tags retain descriptions and external documentation links in complete exports. Repeated servers and security schemes also link to their first occurrence. Security alternatives are labelled explicitly; operation security applies in addition to applicable server security. Primitive schemas remain inline. Schema display normalization and description parsing are cached per prepared renderer.

Tag pages match exact tag names on channels, operations (including traits), and messages. A channel tag includes the channel's operations and messages. An operation tag includes that operation's context. Tags declared in info.tags retain descriptions and external links, even when unused. Tag pages retain the API introduction, display only the selected tag, and link to messages already rendered on the page. Unknown or duplicate tag declarations reject the render.

For documentation sites that publish model pages separately:

await renderer.render({
  operation: 'receiveOrder',
  schemaReferences: {
    mode: 'linked',
    resolveUrl: ({ name }) => `/models/${encodeURIComponent(name)}`,
    inlinePrimitives: true,
  },
})

Linked pages expand root schemas and replace nested structured references with published links. Returning undefined or omitting the callback keeps the model name as plain text. Set inlinePrimitives: false to link primitive, enum and const references too. Linked pages omit the transitive appendix and generated message examples. Selected model pages still generate a local example with linked structured dependencies left as stubs. Authored examples remain available in linked mode. URL callbacks receive the original reference and its model name, preserving aliases. Empty or unsafe URLs render an unlinked name. Composition branches retain their model links. Linked schema usages retain their descriptions, and primitive aliases remain available when generating model examples.

Browser

Use a document already upgraded and resolved by @scalar/workspace-store:

import { createMarkdownFromAsyncApi } from '@scalar/asyncapi-to-markdown/browser'

const markdown = await createMarkdownFromAsyncApi(document, {
  operation: 'receiveOrder',
})

The browser entry point does not read files, fetch references, or upgrade raw documents.

Limitations

This is a documentation converter, not a validator. Unsupported versions, failed loads, and unresolved references needed for rendering reject with an error. Recursive schema expansion stops at a repeated ancestor, ten levels, or 5,000 schema nodes per expansion, with a visible notice. Generated examples exceeding 10,000 estimated values are omitted with a visible notice. Custom schema vocabularies are not interpreted, and output is not a replacement for the original schema. Publishing Markdown routes and adding copy buttons to Scalar Docs are separate integrations.

Playground and benchmarks

Run pnpm --filter @scalar/asyncapi-to-markdown dev --port 3002 --strictPort. The playground includes local order events and a shared-schema stress fixture, page selection and search, linked/full export modes, sanitized previews, Markdown source, copy/download controls, output size and render timing. Click a published model link to open that model page. It runs conversion in a worker to keep the UI responsive.

Run pnpm --filter @scalar/asyncapi-to-markdown benchmark for repeatable preparation, cold/warm rendering, output size, and RSS measurements. See the benchmark method.

Specification coverage

Rendering follows the AsyncAPI 3.1 specification. The converter covers application metadata, servers and variables, channel parameters, operation and message traits, request/reply details, security schemes and OAuth flows, tags, external documentation, and JSON Schema Draft 7 constraints. All mandatory JSON/YAML schema-format identifiers work for both headers and payloads. Protocol bindings and other schema languages remain available as source blocks. Referenced reusable objects render at their usage sites; unused component schemas and messages are also included in complete exports. Custom extension semantics and validation remain outside the converter's scope.