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

md-computer

v0.3.1

Published

A Markdown-native UI DSL that compiles to React + shadcn/ui

Downloads

45

Readme

md-computer

A Markdown-native UI DSL that compiles to React + shadcn/ui.

Write your UI like a product spec — describe layout, components, props, bindings, and actions in plain Markdown. Get type-safe shadcn/ui React out the other side.

Status: alpha (v0.3). APIs may still change.

Install

pnpm add -D md-computer
# or: npm i -D md-computer

Example

app/settings/page.md:

---
title: Settings
---

# Settings
@stack gap=8

## Profile
@card
@form submit="saveProfile"
Input name="displayName" label="Display name" placeholder="Vlad"
Input name="email" label="Email" type="email"
Button type="submit"
  Save changes

## Billing
@card
Badge variant="secondary"
  Pro plan
Text tone="muted"
  Your next invoice is due on {{ billing.nextInvoiceDate }}.
Button variant="outline" action="openBillingPortal"
  Manage billing

Compile it:

npx md-computer compile app/settings/page.md

You get a typed React component (page.tsx) and a sibling page.actions.ts stub you fill in with your real handlers. Any shadcn primitives the page references that aren't installed yet are added automatically via npx shadcn add.

How it reads

  • # Title / ## Section — page + section headings
  • @directive — layout/structure wrappers (@stack, @grid, @card, @form, @section)
  • Component prop=value — leaf components (capitalised names matched against the registry)
  • child text — indented continuation becomes the component's children
  • {{ binding.path }} — typed data passed in as bindings props
  • action="name" — wired to actions.name() in the sibling page.actions.ts
  • @form submit="name" — wraps in <form onSubmit> and calls actions.name(formData)

CLI

md-computer compile <input.md>                     # writes <input>.tsx + .actions.ts; auto-installs missing shadcn primitives
md-computer compile <input.md> --no-install-shadcn # skip the auto-install
md-computer compile <input.md> --out Page.tsx      # custom output path

Vite plugin

// vite.config.ts
import { defineConfig } from "vite";
import mdComputer from "md-computer/vite";

export default defineConfig({
  plugins: [mdComputer()],
});

Importing a .md file gives you the compiled React component as the default export. Missing shadcn primitives are installed on first transform; HMR works automatically.

Tailwind setup (one extra line)

Each .md is compiled to a real .tsx file under <projectRoot>/.md-computer/ so Tailwind's source scanner can discover the codegen-emitted classes (p-8, shadow-lg, text-xl, etc). You only need to point Tailwind at that dir:

@import "tailwindcss";
@source "../.md-computer/**/*.tsx";

Add .md-computer/ to your .gitignore — it's a build-time cache that's regenerated on every transform.

If you'd rather not have an on-disk cache, pass cache: false and add classes via @source inline(...) yourself:

mdComputer({ cache: false })

Built-in components

Layout: @stack, @grid, @card, @form, @section Form: Input, Textarea, Switch Action: Button Display: Badge, Text

Requires components.json in your project root (run npx shadcn@latest init once if you don't have it).

Style props

Every directive and component accepts className="..." as an escape hatch — it's merged with codegen-emitted classes via tailwind-merge, so user classes win cleanly (p-6 p-12p-12).

Curated semantic tokens:

| Where | Props | |---|---| | @card | padding=none|sm|md|lg|xl, radius=none|sm|md|lg|xl|2xl|full, shadow=none|sm|md|lg|xl, variant=destructive | | @stack / @grid | align=start|center|end|stretch|baseline, justify=start|center|end|between|around|evenly (plus existing gap / cols) | | Button | width=full|auto, variant, size | | Text | tone=default|muted, size=xs..4xl, weight=normal|medium|semibold|bold, align=left|center|right |

Anything not in the table can be expressed with className="..." directly.

License

MIT