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-2-ats

v0.1.2

Published

Generate ATS-friendly CV/PDF from Markdown

Readme

Markdown 2 ATS

Write an ATS-friendly resume in Markdown, render it to PDF. Optimized for developers.

npm License: MIT Node.js Buy Me A Coffee

About

Markdown 2 ATS is a Node.js library that turns a Markdown resume into a clean, ATS-friendly PDF. It parses Markdown into a structured document, validates it against sensible resume rules, and renders a restrained single-column layout that parses reliably through Applicant Tracking Systems.

The default template is based on the ATS Standard, using a restrained layout, standard PDF fonts, and readable content structure so a resume works well for both applicant tracking systems and people.

It is a library, not an editor or a web app: you call it from your own script, CLI, or build step, and you stay in control of your files.

I can't guarantee that using this will improve your job search success rate. But I hope it helps.

See the Changelog for the complete project history and latest changes.

Notice

Output uses standard PDF fonts (Helvetica) by default, which only cover Latin-1 characters. To render CJK/Kana/Hangul text, provide your own TTF font (see Custom Fonts).

Features

  • Write your resume in Markdown and render it to a clean PDF
  • ATS-friendly single-column layout, based on the CareerCup template
  • Automatic page breaking for multi-page resumes
  • Profile photo support (PNG and JPEG)
  • Custom TTF fonts for non-Latin text (e.g. Noto Sans CJK)
  • Theming: font family, sizes, colors, and spacing
  • Supports headings, lists (nested), blockquotes, thematic breaks, and inline formatting
  • ESM and CommonJS builds with TypeScript types included
  • CLI (md-2-ats) for one-off renders
  • Works offline and never uploads your data anywhere

Install

pnpm add md-2-ats
# or: npm install md-2-ats

Requires Node.js >= 18.

Usage

import { generateCV } from "md-2-ats";
import { readFile } from "node:fs/promises";

await generateCV({
  input: "./cv.md",
  output: "./cv.pdf",
  profile: {
    bytes: await readFile("./profile.png"),
    size: 96,
    position: "right",
  },
});

Options

| Option | Type | Description | | --------- | -------------- | ----------------------------------------------------- | | input | string | Path to the source Markdown file (required). | | output | string | Path where the PDF is written (required). | | profile | ProfileImage | Profile photo (bytes, optional size, position). | | fonts | FontSet | Custom TTF fonts for non-Latin text (e.g. CJK). | | theme | Theme | Customize fonts, colors, and spacing. | | page | PageConfig | Page size and margins (default A4, 40pt margins). |

CLI

The package ships a md-2-ats binary:

npx md-2-ats cv.md                  # after publish; runs the default bin
md-2-ats cv.md                      # if installed (local or global)
md-2-ats cv.md -o out.pdf -p photo.png
md-2-ats cv.md --profile-position left --profile-size 80
md-2-ats cv.md --font-regular NotoSansSC-Regular.ttf

| Flag | Description | | -------------------------- | ------------------------------------------------ | | -o, --output <path> | Output PDF path (default: input with .pdf). | | -p, --profile <path> | Profile photo (PNG or JPEG). | | --profile-size <points> | Profile photo side length (default 96). | | --profile-position <pos> | left | center | right (default right). | | --font-regular <path> | Custom TTF regular font. | | --font-bold <path> | Custom TTF bold font. | | --font-italic <path> | Custom TTF italic font. | | -h, --help | Show help. | | -v, --version | Show version. |

Profile Photo

A standalone image in its own paragraph renders as a top-right profile photo:

# Jane Doe

![](profile.png)

**Software Engineer** · Jakarta

Supply the photo bytes via the profile option; size (side length in points, default 96) and position ("left" | "center" | "right", default "right") are optional:

profile: {
  bytes: await readFile("./profile.png"),
  size: 96,
  position: "right",
}

Supported formats: PNG and JPEG. When no profile is provided, the image is skipped silently.

Custom Fonts

Standard fonts only cover Latin-1. To render CJK/Kana/Hangul, provide a TTF font (e.g. Noto Sans SC):

await generateCV({
  input: "./cv.md",
  output: "./cv.pdf",
  fonts: {
    regular: await readFile("./NotoSansSC-Regular.ttf"),
    bold: await readFile("./NotoSansSC-Bold.ttf"), // optional
    italic: await readFile("./NotoSansSC-Italic.ttf"), // optional
  },
});

bold/italic fall back to regular when omitted. Font files are your responsibility (check their license). .ttc collections are not supported; use a single .ttf/.otf.

Theming

import { createDefaultTheme } from "md-2-ats";

const theme = createDefaultTheme();
theme.text.body.family = "Times"; // "Helvetica" | "Times" | "Courier"
theme.text.name.size = 24;
theme.color.accent = { r: 0.1, g: 0.2, b: 0.5 };
theme.spacing.sectionGap = 8;

await generateCV({ input: "./cv.md", output: "./cv.pdf", theme });

Validation

generateCV validates the document before rendering:

  • Errors (throw): empty document, missing the level-1 # Name heading.
  • Warnings (returned in result.issues): missing contact/email, invalid email, heading-level skips, missing ## Experience/## Education, empty entries, and unsupported Markdown.
const result = await generateCV({ input, output });
for (const issue of result.issues) console.warn(issue.message);

Markdown Support

Supported blocks: headings (#–###), paragraphs, unordered/ordered lists (including nested), blockquotes, thematic breaks (---), and inline formatting (bold, italic, links, images, inline code).

Not rendered (reported as warnings): tables, code blocks, raw HTML.

Development

Clone the repo and install dependencies:

pnpm install

Run the test suite and type-checking:

pnpm test
pnpm typecheck

Build the library:

pnpm build

Render the bundled example (example/cv.md → example/cv.pdf):

pnpm example

License

This project is licensed under the MIT license.


Made with ☕ by Iqmal.