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

@darronz/designmd-gen

v0.2.0

Published

Export DESIGN.md from existing design token sources

Downloads

329

Readme

designmd-gen

npm version

Reads design tokens from your existing CSS, Tailwind, or JSON files and writes a standard DESIGN.md file.

Every project names its tokens differently. --bg-primary, --color-brand, --accent — they're all colors, but no parser can know that from the name alone. So instead of trying to handle every convention, designmd-gen lets you generate a custom mapper for your project using an LLM. The LLM reads your code once, produces a plain TypeScript file, and from there everything runs without it.

Why?

Design tokens live in CSS files, Tailwind configs, JSON files — whatever the team picked when the project started. DESIGN.md is a specification that gives these tokens a shared format: a YAML frontmatter block with sections for colors, typography, spacing, and more.

The problem is getting from one to the other. A CSS file with --bg-primary: #08060d and --space-md: 1rem doesn't tell you which variables are colors and which are spacing — at least not in a way a deterministic parser can reliably figure out. Naming conventions vary wildly between projects, and writing a custom parser by hand for each one is tedious.

designmd-gen solves this in two layers:

  1. Built-in parsers for projects that follow common conventions (--color-*, --spacing-*, Tailwind's theme object, W3C DTCG JSON)
  2. Custom mappers for everything else — generated by pointing an LLM at your codebase

The LLM does the one-time judgment work (which variables are colors? which are spacing?) and produces a TypeScript file that designmd-gen runs deterministically from there.

Install

npm install @darronz/designmd-gen

Quick start

# From a CSS file with standard naming conventions
designmd-gen tokens.css --name "My System"

# From a Tailwind config
designmd-gen tailwind.config.ts --name "My System"

# Merge multiple sources (later files win conflicts)
designmd-gen tokens.css brand-colors.json --name "My System"

# Preview without writing
designmd-gen tokens.css --name "My System" --dry-run --no-lint

Generate a mapper with an LLM

Most real projects don't follow the naming conventions that the built-in parsers expect. That's fine — point an LLM at your project and have it generate a mapper.

Give your LLM access to your codebase and use this prompt:

Look at the CSS custom properties in this project. I need a custom mapper
for designmd-gen that categorizes these tokens into a DESIGN.md file.

Find all CSS files that define custom properties (in :root or html selectors)
and generate a TypeScript file that exports a ParserPlugin.

Classify each variable by examining its name, value, and surrounding comments:
- Color values (hex, rgb, rgba, hsl, named colors) go in `colors`
- Font family stacks and font size/weight/line-height go in `typography`
- Spacing scale values go in `spacing`
- Border radius values go in `rounded`
- Use the variable name (minus the -- prefix) as the token key
- Normalize hex values to lowercase 6-digit format
- Handle rgba() by including the alpha as 8-digit hex

The file should be self-contained (inline types, use postcss for parsing)
and export the parser as a named export.

Here is the ParserPlugin interface the file must implement:

type ParserPlugin = {
  name: string;
  extensions: string[];
  detect(filePath: string): boolean;
  parse(filePath: string): DesignTokenSet;
};

type DesignTokenSet = {
  name: string;
  description?: string;
  colors?: Record<string, string>;
  typography?: Record<string, TypographyToken>;
  rounded?: Record<string, string>;
  spacing?: Record<string, string | number>;
  components?: Record<string, Record<string, string>>;
};

type TypographyToken = {
  fontFamily?: string;
  fontSize?: string;
  fontWeight?: number;
  lineHeight?: string | number;
  letterSpacing?: string;
};

Save the mapper to src/tokens/mapper.ts and create a designmd-gen.config.ts
in the project root that imports it.

The LLM reads your codebase, finds the token definitions, classifies them, and generates both the mapper and the config file. From there the mapper runs without an LLM — it's just a TypeScript file. If your tokens change, regenerate the mapper.

Config file

A designmd-gen.config.ts in your project root sets defaults and registers your mapper:

import { myParser } from './src/tokens/mapper.ts';

export default {
  name: 'My Design System',
  parser: myParser,
  input: ['src/styles/global.css'],
  out: 'DESIGN.md',
};

With a config file in place, run with no arguments:

designmd-gen --dry-run

CLI flags override config values when both are provided.

Built-in parsers

These work out of the box for projects that follow their expected naming conventions:

| Parser | Detects | What it maps | |--------|---------|--------------| | css | .css files | --color-* to colors, --font-{group}-{prop} to typography, --spacing-* to spacing, --radius-* to rounded | | dtcg | .json with $value keys | W3C DTCG format. color to colors, dimension to spacing/rounded/typography (by ancestor group), typography and fontFamily to typography, component-tier dimensions to components. Resolves aliases and nested three-tier structures (reference/system/component). | | style-dictionary | .json with value keys (no $ prefix) | Style Dictionary's older value/type format | | tailwind | tailwind.config.* | theme.colors, theme.fontSize, theme.fontFamily, theme.spacing, theme.borderRadius |

Force a specific parser with --parser:

designmd-gen tokens.json --parser dtcg --name "My System"

CI

Add designmd-gen to your build pipeline to keep DESIGN.md in sync with your tokens. If someone updates a token but forgets to regenerate the file, CI catches it.

GitHub Actions

- name: Check DESIGN.md is up to date
  run: |
    npx designmd-gen
    git diff --exit-code DESIGN.md

This regenerates DESIGN.md and fails if the output differs from what's committed. Works with both built-in parsers and custom mappers — as long as the config file and mapper are checked in.

Other CI systems

The same pattern works anywhere:

npx designmd-gen
git diff --exit-code DESIGN.md

Exit code 0 means the file is current. Non-zero means tokens changed but DESIGN.md wasn't updated.

Programmatic API

The CLI is a thin wrapper. Everything is importable:

import { parse, serialize, mergeTokenSets } from '@darronz/designmd-gen';

const tokens = parse('tokens.css');
const yaml = serialize(tokens);

// Merge multiple sources
const css = parse('tokens.css');
const brand = parse('brand.json', 'dtcg');
const merged = mergeTokenSets([css, brand]);
const output = serialize(merged);

CLI reference

designmd-gen [options] [files...]

Options:
  -c, --config <path>  Path to config file
  -p, --parser <name>  Force a specific parser (css, dtcg, tailwind, style-dictionary)
  -n, --name <name>    Set the design system name
  -o, --out <path>     Output path (default: DESIGN.md)
  --no-lint            Skip validation against @google/design.md linter
  --dry-run            Print to stdout without writing a file

Token merging

When multiple input files are provided, their tokens are merged into a single DESIGN.md. Later files override earlier ones for conflicting token names, with a warning printed to stderr.

designmd-gen base-tokens.css brand-overrides.css --name "My System"

Validation

Output is validated against the @google/design.md linter by default. Warnings print but don't block. Errors block and exit non-zero. Skip with --no-lint.

License

MIT