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

@davidsneighbour/draft-pipeline

v0.3.0

Published

Reusable markdown-to-pdf and optional reMarkable upload toolkit

Readme

@davidsneighbour/draft-pipeline

A standalone package extracted from the bookofhugo.dev toolchain for:

  1. Markdown to print-style PDF generation.
  2. With Tailwind CSS integration for PDF styling.
  3. Optional upload of built PDFs to a reMarkable tablet and/or any SSH/rsyncable destination.

How it works

  • Step 1: Build Tailwind CSS from TAILWIND_INPUT_CSS to OUTPUT_CSS_FILE.
  • Step 2: Convert Markdown files from MARKDOWN_INPUT_DIR into PDFs in OUTPUT_DIR (either n-to-1 or n-to-n generation).
  • Step 3: Run enabled upload integrations.

Markdown to PDF notes

  • The input is a directory tree containing Markdown files (.md, .markdown).
  • It's front matter is read with gray-matter.
  • Files with b/pdf/ignore: true in the front matter are skipped.
  • Markdown content is rendered via marked.
  • PDF generation runs through headless Playwright Chromium.
  • Header, footer, and document HTML can be configured using templates.
  • Output PDF names are flattened/sanitized from source path segments and can be in parts configured via front matter.

Upload integrations

The upload stage offers integrations to upload (synchronize) the created PDF files to various locations.

  • Generic SSH/Rsync integration - (SSH_UPLOAD_ENABLED=true|false)
  • reMarkable integration - (REMARKABLE_UPLOAD_ENABLED=true|false)

Each integration must be explicitly enabled (true).

reMarkable integration internals

This part of the project exists because I, @davidsneighbour use a reMarkable 2. reMarkable does not ingest plain PDF uploads directly into the library. It requires companion .metadata and .content JSON files, a UUID for each file, and a folder that the file is copied to. This integration creates those files on the fly, copies all files into the configured xochitl data directory, and finally restarts xochitl so the documents appear in the UI. This is relatively slow per file and, depending on the amount of files already on the tablet, the restart takes very long. It's not optimal, but it works. I suggest to create two configurations, one to create the PDF files and one that creates and uploads those files when you want to update the tablet. Or you disconnect your tablet while uploading. The script will fail gracefully when no remarkable is connected.

This README.md assumes you have your reMarkable tablet set up for SSH access and I call it remarkable in my SSH configuration instead of a dynamically assigned IP address. Read the reMarkable support article for the USB to SSH access for details on how to set this up. I might write up a guide one day.

Generic SSH integration

Uploads built PDFs to any SSH target and directory.

  • scp mode uploads one PDF at a time.
  • rsync mode uses include/exclude patterns so only *.pdf files are transferred.
  • Both modes are configurable through SSH_UPLOAD_METHOD=scp|rsync.

Installation

npm install @davidsneighbour/draft-pipeline

Commands

draft-pipeline css

To be written... creates the css file.

draft-pipeline pdf

To be written... creates the PDF files.

draft-pipeline upload

To be written... uploads to configured targets.

draft-piepline build

To be written... a successive pipeline of css > pdf > upload.

Configuration

The pipeline configuration can be changed using .env-variables, a config file, or directly via CLI parameters when you call the tool. To create the env file run the following command:

npx draft-pipeline setup-env --pipeline-env sample.env

Leaving --pipeline-env out will save the example to sample.env

All configuration is resolved in this order:

  1. Sensible defaults
  2. Environment variables (.pipeline.env by default)
  3. JSON config file (.pipeline.config.json by default)
  4. CLI flags

Later sources override earlier ones.

Print the final resolved configuration and where each value came from:

draft-pipeline build --print-config
draft-pipeline build --print-config=json

CLI-only options

  • --pipeline-env <path>: env file path (default: .pipeline.env, will be loaded automatically)
  • --pipeline-config <path>: JSON config file path (default: .pipeline.config.json)
  • --print-config[=table|json]: show resolved config and source mapping, then exit

Parameter reference (CLI / env / config)

| Purpose | CLI | Env | Config key | Default | | ------------------------------------- | --------------------- | ------------------------------- | ---------------------------- | --------------------------------- | | Markdown input dir | — | MARKDOWN_INPUT_DIR | markdownInputDir | ./book | | Output dir | — | OUTPUT_DIR | outputDir | ./dist | | Output CSS file | — | OUTPUT_CSS_FILE | outputCssFile | ./dist/output.css | | Tailwind input CSS | — | TAILWIND_INPUT_CSS | tailwindInputCss | ./styles/pdf.css | | Header template | --header-template | HEADER_TEMPLATE_PATH | headerTemplatePath | ./templates/header.html | | Footer template | --footer-template | FOOTER_TEMPLATE_PATH | footerTemplatePath | ./templates/footer.html | | Document template | --document-template | DOCUMENT_TEMPLATE_PATH | documentTemplatePath | ./templates/document.html | | Book layout CSS | --book-layout-css | BOOK_LAYOUT_CSS_PATH | bookLayoutCssPath | ./styles/pdf-book-layout.css | | Print ready mode | --printready | PDF_PRINT_READY | pdfPrintReady | false | | PDF bleed | --bleed | PDF_BLEED | pdfBleed | 3mm | | Enable reMarkable upload | — | REMARKABLE_UPLOAD_ENABLED | remarkableUploadEnabled | false | | reMarkable host | — | REMARKABLE_HOST | remarkableHost | remarkable | | reMarkable xochitl dir | — | REMARKABLE_XOCHITL_DIR | remarkableXochitlDir | .local/share/remarkable/xochitl | | reMarkable parent folder UUID | — | REMARKABLE_PARENT_FOLDER_UUID | remarkableParentFolderUuid | empty | | reMarkable parent folder display name | — | REMARKABLE_PARENT_FOLDER_NAME | remarkableParentFolderName | Book of Hugo | | Enable SSH upload | — | SSH_UPLOAD_ENABLED | sshUploadEnabled | false | | SSH target (user@host) | — | SSH_TARGET | sshTarget | empty | | SSH target dir | — | SSH_TARGET_DIR | sshTargetDir | empty | | SSH upload method | — | SSH_UPLOAD_METHOD | sshUploadMethod | scp | | SSH port | — | SSH_PORT | sshPort | unset |

Sensible defaults

Defaults are chosen to make local development work out-of-the-box with this repository layout:

  • source markdown from ./book
  • write build artifacts to ./dist
  • use repository-provided templates and CSS
  • disable all uploads by default for safe local runs
  • use scp for SSH uploads unless explicitly changed
  • keep print-ready mode disabled unless explicitly enabled

Graceful errors

The package intentionally fails with direct explanations when:

  • input/template/css files are not readable,
  • no markdown files are found,
  • an upload integration is enabled but its host is unreachable,
  • reMarkable upload is enabled but folder UUID is missing,
  • generic SSH upload is enabled but target settings are missing,
  • no PDFs are available for upload,
  • Tailwind build command fails.