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

@contentmap/mdx

v1.2.0

Published

MDX compiler for contentmap, built on @mdx-js/mdx.

Readme

@contentmap/mdx

MDX for contentmap, built on @mdx-js/mdx.

Write JSX in your content, import components into it, export values from it — and keep contentmap's typed schema, per-document output and incremental cache.

Install

npm i @contentmap/mdx

Use

import { defineCollection, defineConfig } from 'contentmap'
import { mdx } from '@contentmap/mdx'
import { z } from 'zod'

const posts = defineCollection({
  directory: 'content/posts',
  include: '**/*.mdx',
  schema: z.object({ title: z.string(), content: z.string() }),
  transform: async (doc, ctx) => ({ ...doc, code: await ctx.mdx() })
})

export default defineConfig({ mdx: mdx(), collections: { posts } })

Then render it with your framework's JSX runtime:

import { run } from '@mdx-js/mdx'
import * as runtime from 'react/jsx-runtime'
import { posts } from 'contentmap/generated'

const post = await posts.load('hello-world')
const { default: Content } = await run(post.code, { ...runtime, baseUrl: import.meta.url })

// Anything the document exported is on the same object.
// Map your own components with <Content components={{ Callout }} />

What ctx.mdx() returns

A JavaScript function body, not a component — because a build can only write data, and a component does not exist until a JSX runtime has evaluated it. The string goes into your document like any other field, and run() turns it into a component.

This is what every tool in this space does: contentlayer's body.code, velite's s.mdx() and @content-collections/mdx all produce the same function-body string. run() evaluates JavaScript, so it will not work under a CSP that forbids eval.

contentmap's own runtime is unaffected — it still contains no eval, no Function and no Proxy.

What it costs

Measured from a packed tarball:

| | packages | install size | | ------------------ | -------- | ------------ | | contentmap + zod | 10 | 7.0 MB | | @contentmap/mdx | 114 | 12 MB |

The MDX toolchain is most of a unified pipeline, and there is no version of it that is small. That is exactly why it is a separate package: a project rendering .md never installs any of it, and contentmap's own figures do not move.

None of that reaches your users. The compiler runs at build time. import { run } from '@mdx-js/mdx' in client code tree-shakes to 0.2 KB minified and gzipped — measured by bundling exactly that import — because run is a few lines around AsyncFunction and pulls none of the compiler with it.

Options

mdx({
  remarkPlugins: [remarkGfm],
  rehypePlugins: [rehypeSlug],
  recmaPlugins: [],
  development: process.env.NODE_ENV !== 'production',
  minify: true
})

development: true adds source positions, so a runtime error points at the .mdx file rather than at generated code.

minify: true runs the compiled output through esbuild. Nothing reads that JavaScript — it is written to disk and handed to a bundler — and unminified it is roughly 2.5× the size: migrating a 54-document site, one page came out 52,316 characters unminified against 20,693 from Velite, which has always minified. Turning it on brought the whole corpus from 7.69 MB to 3.30 MB with every rendered page identical.

esbuild is an optional peer. Install it alongside this package to use the option; leave the option off and nothing changes, including the figures above.

Options can also be passed per call — ctx.mdx({ remarkPlugins: [...] }) — which overrides the configured ones for that document.

Errors

A document that will not parse fails the build and names the file:

✖ contentmap — 1 error in 1 document

  Transform (1)
  └─ broken.mdx
     Expected a closing tag for `<Unclosed>` (1:1-1:11)

Just markdown?

Use @contentmap/markdown instead. It is far smaller, and .md files do not need a JSX pipeline.

Links

MIT