md-to-pdf

Convert Markdown documents with YAML frontmatter into styled, print-ready PDFs using Chrome headless.

5 stars

Best use case

md-to-pdf is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Convert Markdown documents with YAML frontmatter into styled, print-ready PDFs using Chrome headless.

Teams using md-to-pdf should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/md-to-pdf/SKILL.md --create-dirs "https://raw.githubusercontent.com/vamseeachanta/workspace-hub/main/.agents/skills/data/documents/md-to-pdf/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/md-to-pdf/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How md-to-pdf Compares

Feature / Agentmd-to-pdfStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Convert Markdown documents with YAML frontmatter into styled, print-ready PDFs using Chrome headless.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# md-to-pdf Skill

Convert Markdown documents with YAML frontmatter into styled, print-ready PDFs using Chrome headless.

## Quick Start

```bash
python3 .Codex/skills/data/documents/md-to-pdf/md_to_pdf.py document.md -o output.pdf
```

## When to Use

- Professional reports (GTM strategy, proposals, engineering summaries)
- Any document that needs a styled cover page, section headers, and print-optimized layout
- When you need consistent PDF output without hand-coding HTML

## Prerequisites

- **Chrome**: `/usr/bin/google-chrome` (v145+ recommended)
- **Python**: `markdown` library (v3.5.2+ with tables, fenced_code, toc, attr_list, meta, sane_lists)
- **System Python 3.10+**

## CLI Reference

```
python3 md_to_pdf.py input.md [-o output.pdf] [--screenshot] [--no-cover] [--keep-html] [--template base]
```

| Flag | Description |
|------|-------------|
| `-o`, `--output` | Output PDF path (default: `<input>.pdf`) |
| `--screenshot` | Also generate a QA PNG screenshot |
| `--no-cover` | Skip automatic cover page from frontmatter |
| `--keep-html` | Retain intermediate HTML file for inspection |
| `--template` | Template name from `templates/` (default: `base`) |

## Frontmatter Reference

```yaml
---
title: Document Title
subtitle: Subtitle displayed in accent color
date: February 16, 2026
author: Author Name
version: 1.0
confidentiality: Confidential
accent_color: "#0066cc"
footer: "Company Name | Confidential"
---
```

All fields are optional. `title` defaults to "Untitled Document".

## Component Gallery

### Section Header
```html
<div class="section-header">
  <div class="section-label">SECTION 01</div>
  <h2>Executive Summary</h2>
</div>
```

### Card
```html
<div class="card">
  <h3>Item Name <span class="score-chip score-5">5/5</span></h3>
  <p><span class="field-label">Category:</span> Description text</p>
</div>
```

### Tier Header
```html
<div class="tier-header">Tier 1 — Critical Priority</div>
```

### Score Chips
```html
<span class="score-chip score-5">5/5</span>  <!-- teal -->
<span class="score-chip score-4">4/5</span>  <!-- blue -->
<span class="score-chip score-3">3/5</span>  <!-- orange -->
<span class="score-chip score-2">2/5</span>  <!-- red -->
<span class="score-chip score-1">1/5</span>  <!-- gray -->
```

### Priority Badges
```html
<span class="priority-badge high">High</span>
<span class="priority-badge medium">Medium</span>
<span class="priority-badge low">Low</span>
<span class="priority-badge ongoing">Ongoing</span>
```

### Metric Grid
```html
<div class="summary-grid">
  <div class="metric-card">
    <div class="metric-value">42</div>
    <div class="metric-label">Total Items</div>
  </div>
  <div class="metric-card">
    <div class="metric-value">$1.2M</div>
    <div class="metric-label">Revenue</div>
  </div>
</div>
```

### Standard Markdown (auto-styled)
- **Tables**: dark header, zebra striping — use standard markdown table syntax
- **Blockquotes**: blue left-border callout — use `>` prefix
- **Code blocks**: dark background with monospace — use fenced code blocks
- **Headings**: h1 gets accent underline, h2-h4 styled progressively

### Page Control
```html
<div class="page-break"></div>       <!-- force page break -->
<div class="avoid-break">           <!-- keep content together -->
  ... content ...
</div>
```

## Chrome Flags

The script uses these Chrome headless flags:

| Flag | Purpose |
|------|---------|
| `--headless` | No GUI window |
| `--no-sandbox` | Required in containers/CI |
| `--disable-gpu` | Prevents GPU errors in headless |
| `--print-to-pdf=FILE` | Generate PDF output |
| `--no-pdf-header-footer` | Suppress default Chrome header/footer |
| `--print-background` | Render CSS backgrounds (critical for gradients, chips) |
| `--screenshot=FILE` | Generate PNG for QA |
| `--window-size=W,H` | Viewport for screenshots |

## Integration with Engineering Reports

Existing HTML report generators (wall thickness, dynacard) can reuse `components.css` by including it as a stylesheet. The CSS components are independent of the markdown pipeline.

```python
from pathlib import Path
css = (Path(__file__).parent / "../../.Codex/skills/data/documents/md-to-pdf/templates/components.css").read_text()
```

## Browser QA Step

Always use `--screenshot` during development to visually verify layout before final PDF:

```bash
python3 md_to_pdf.py draft.md -o draft.pdf --screenshot --keep-html
# Check draft.png for visual issues
# Check draft.html for template injection correctness
# Final: draft.pdf
```

## Troubleshooting

| Issue | Cause | Fix |
|-------|-------|-----|
| Blank PDF | Chrome not found | Verify `which google-chrome` |
| No background colors | Missing `--print-background` | Already set by default in script |
| Section headers cut off | Missing page-break-before | Use `.section-header` class (has it built-in) |
| Tables split across pages | Large table | Wrap in `<div class="avoid-break">` |
| Accent color wrong | Frontmatter typo | Check `accent_color` is valid CSS color with quotes |
| Cover page missing | `--no-cover` flag | Remove flag, or add frontmatter `title` |

Related Skills

test-oversized-skill

5
from vamseeachanta/workspace-hub

A test fixture skill that exceeds 200 lines with multiple H2/H3 sections for split testing.

interactive-report-generator

5
from vamseeachanta/workspace-hub

Generate interactive HTML reports with Plotly visualizations from data analysis results. Supports dashboards, charts, and professional styling.

data-validation-reporter

5
from vamseeachanta/workspace-hub

Generate interactive validation reports with quality scoring, missing data analysis, and type checking. Combines Pandas validation, Plotly visualization, and YAML configuration for comprehensive data quality reporting.

agent-os-framework

5
from vamseeachanta/workspace-hub

Generate standardized .agent-os directory structure with product documentation, mission, tech-stack, roadmap, and decision records. Enables AI-native workflows.

OrcaFlex Specialist Skill

5
from vamseeachanta/workspace-hub

```yaml

repo-ecosystem-hygiene

5
from vamseeachanta/workspace-hub

Interpret the daily read-only repo ecosystem hygiene audit and route remediation through approved workflows.

domain-knowledge-sweep

5
from vamseeachanta/workspace-hub

Systematic multi-source research of an engineering domain. Spawns parent issue → 6 research subissues (Standards, Academic, Industry, LinkedIn-marketing, Code-audit, Synthesis) → gap implementation subissues. Replaces LinkedIn-only extraction with defensible comprehensive sourcing.

subagent-write-verification

5
from vamseeachanta/workspace-hub

Independently verify subagent-claimed file writes with filesystem and git checks before treating the artifact as real, before committing it, and before referencing the path in downstream prompts.

git-operation-serialization-preflight

5
from vamseeachanta/workspace-hub

Before any commit, stash, merge, reset, rebase, or checkout in a multi-agent or shared-checkout environment, run a bounded preflight to detect active git writers and stale index/config locks, then serialize the mutating step under a single-writer guarantee.

public-knowledge-graph-governance

5
from vamseeachanta/workspace-hub

Maintain public-safe knowledge graph artifacts for llm-wiki and similar markdown knowledge bases. Use when changing graph generators, validators, schema docs, weekly freshness checks, or public/private source-scope boundaries.

llm-wiki-weekly-freshness

5
from vamseeachanta/workspace-hub

Class-level governance workflow for keeping llm-wiki-style markdown knowledge bases current, public-safe, graph/index-valid, and useful for code development. Use when reviewing llm-wiki architecture/content, scanning new LLM concepts, maintaining public knowledge graphs, producing an issue roadmap, or running recurring freshness cadence.

llm-wiki-source-extraction-coverage

5
from vamseeachanta/workspace-hub

Doc-type-aware extraction contract for llm-wiki source ingestion with measurable coverage and source-anchored traceability. Use when (1) ingesting a PDF, DOCX, XLSX, PPTX, HTML, or scanned-image source into a wiki `sources/` page, (2) computing the pre-extraction estimate (what fraction of the source we expect to recover) and post-extraction yield (what fraction we actually recovered), (3) anchoring wiki claims back to specific page / paragraph / cell / slide positions in the source so a reviewer can re-verify or revise against the actual document, (4) deciding whether OCR fallback or manual transcription is needed. Codifies workspace-hub's existing OCR fallback chain and python-docx / openpyxl / trafilatura patterns into a format-specific routing table. Companion to research/llm-wiki-page-shape-contract (Rule 7 input-layer pages) and research/llm-wiki — this skill is the defense against silent extraction failure.