Markdown Publishing skill for Claude Code

One Markdown source, clean PDF, DOCX and HTML. Claude sets up repeatable pandoc builds instead of one-off commands: a defaults file per output, a reference.docx that carries your Word house styles, citeproc with real CSL styles, and the right PDF engine for the job, whether LaTeX, Typst or WeasyPrint. It handles cross-references, math, diagrams and Lua filters, then opens each output to check it.

  • namemarkdown-publishing
  • size190 lines · ≈1,800 tokens
  • files1
  • licenseMIT
  • updated

What Claude sees before loading it

This description is the only part of the skill that sits in context all the time. Claude reads it to decide when to load the full playbook below.

description: Converts Markdown into polished HTML, PDF, and DOCX with pandoc — YAML metadata, defaults files for repeatable builds, tables of contents and numbered sections, citations with citeproc and CSL styles, reference.docx styling for Word output, PDF engines (LaTeX, Typst, WeasyPrint), custom templates, Lua filters, and diagram handling. Use when the user wants Markdown turned into a PDF report, Word document, standalone HTML page, or ebook, needs a consistent house style across exports, or has citations, TOC, or math to render.

Try asking

  • Convert our Markdown handbook into a styled PDF and Word version
  • Make pandoc use our company Word template when exporting this report
  • Add citations with APA style to this Markdown paper and build a PDF

Use it when

  • Markdown needs to ship as PDF, DOCX, or standalone HTML
  • Several documents must share one consistent house style
  • A Markdown document has citations, math, or a table of contents
  • Builds must be reproducible in CI from committed config

Skip it when

  • You are building a navigable multi-page docs website — use docs-site instead
  • The document is authored directly in LaTeX — use latex-documents instead

How to check the result

Every target builds from a clean directory without citation or missing-resource warnings, and each output is opened or rendered to confirm the TOC, figures, tables and citations.

The common mistake it prevents

Styling Word output by editing the generated DOCX each time instead of the reference.docx styles, so every rebuild loses the formatting work.

~/.claude/skills/markdown-publishing/SKILL.md

--- name: markdown-publishing description: Converts Markdown into polished HTML, PDF, and DOCX with pandoc — YAML metadata, defaults files for repeatable builds, tables of contents… license: MIT ---

Done well means: one command (or one defaults file) rebuilds every output from the same Markdown source; headings, TOC, citations, figures, and code render correctly in each format; Word output uses the house styles from a reference document; and you opened or rendered each output to check it rather than trusting the exit code.

Setup

brew install pandoc            # or apt install pandoc / download a 3.x release; check: pandoc --version
# PDF engines (pick one):
brew install --cask mactex-no-gui    # LaTeX (lualatex/xelatex); Debian: apt install texlive-luatex texlive-latex-extra
brew install typst                   # Typst: fast, small install (pandoc 3.1.2+)
pip install weasyprint               # HTML + CSS to PDF

Choose the PDF route

NeedRoute
Academic look, math-heavy, precise typography--pdf-engine=lualatex (LaTeX template)
Fast builds, simple install, modern defaults--pdf-engine=typst
Design matches a website / CSS skills on handHTML + CSS, --pdf-engine=weasyprint
Must be edited by others in WordDOCX with --reference-doc, then PDF from Word if required

Source conventions

---
title: "Incident Review: Checkout Latency"
subtitle: "March 2026"
author: ["Jane Doe", "Platform Team"]
date: 2026-03-02
lang: en-GB
bibliography: refs.bib
csl: ieee.csl
link-citations: true
abstract: |
  One-paragraph summary.
---

# Summary {#sec-summary}

Latency rose after the cache change [@dean2013tail, p. 76]. See @fig-latency.

![p99 latency by hour](figures/latency.png){#fig-latency width=80%}

| Region | p99 (ms) |
|:-------|---------:|
| EMEA   |      310 |

: Latency by region {#tbl-latency}
  • One # level per document section; do not skip levels.
  • Image paths are relative to the working directory pandoc runs in (or --resource-path).
  • Pipe tables cannot hold multi-line cells; use grid tables or list tables (filter) for that.
  • Raw HTML in Markdown only survives HTML outputs; raw LaTeX only LaTeX/PDF outputs.

Defaults file (repeatable builds)

pdf.yaml:

from: markdown+smart
to: pdf
pdf-engine: lualatex
input-files: [report.md]
output-file: build/report.pdf
standalone: true
table-of-contents: true
toc-depth: 2
number-sections: true
citeproc: true
resource-path: [".", "figures"]
variables:
  geometry: margin=2.5cm
  mainfont: "Source Serif 4"
  monofont: "JetBrains Mono"
  colorlinks: true
  linkcolor: blue

docx.yaml and html.yaml follow the same shape. Build:

pandoc -d pdf.yaml
pandoc -d docx.yaml
pandoc -d html.yaml

Equivalent one-liners:

pandoc report.md -o build/report.html --standalone --embed-resources --toc --citeproc --css style.css
pandoc report.md -o build/report.docx --toc --citeproc --reference-doc=reference.docx
pandoc report.md -o build/report.pdf  --pdf-engine=typst --toc --number-sections --citeproc
pandoc report.md -o build/report.pdf  --pdf-engine=weasyprint --css print.css --citeproc

--embed-resources --standalone inlines images, CSS, and scripts into one HTML file (the older --self-contained flag is deprecated).

Word output with house styles

  1. Generate the default reference document: pandoc -o reference.docx --print-default-data-file reference.docx
  2. Open it in Word or LibreOffice and modify the styles (Normal, Heading 1–3, Title, Body Text, First Paragraph, Compact, Table, Source Code, Hyperlink, header/footer, margins). Do not add content; only styles and page setup are used.
  3. Build with --reference-doc=reference.docx.

Pandoc maps Markdown to those named styles, so changing a style changes every document. Custom paragraph styles: ::: {custom-style="Callout"} … ::: uses a style named “Callout” in the reference doc.

Citations

  • Bibliography formats: BibTeX/BibLaTeX (.bib), CSL JSON (.json), CSL YAML.
  • Styles: download .csl files from the Zotero Style Repository / citation-style-language styles repo (e.g. apa.csl, ieee.csl, chicago-author-date.csl).
  • Syntax: [@key], [@key, p. 4], [-@key] (suppress author), @key (in-text), [@a; @b]. The bibliography is placed at the end, or where ::: {#refs} ::: appears.
  • Unresolved keys print as ?key and pandoc warns Citeproc: citation key not found; treat warnings as errors in CI (--fail-if-warnings).
  • Never invent references; use the user’s bibliography and flag anything unverifiable.

Cross-references, math, code, diagrams

  • Cross-references (@fig-latency → “Figure 1”): use the pandoc-crossref filter (--filter pandoc-crossref, before --citeproc), or Quarto, which builds on pandoc and supports them natively. Plain pandoc does not number figure references by itself.
  • Math: $...$ and $$...$$. HTML needs --mathjax or --katex; DOCX converts to native Word equations; LaTeX/Typst PDF render natively.
  • Code highlighting is on by default; choose a theme with --highlight-style=tango (newer pandoc releases also accept --syntax-highlighting; check pandoc --help).
  • Mermaid/PlantUML: pandoc does not render them. Pre-render to SVG/PDF (see mermaid-diagrams: mmdc -i README.md -o README.out.md replaces blocks with images) or use a filter. For PDF via LaTeX, use PDF or PNG figures; SVG needs rsvg-convert installed.

Templates and filters

  • Inspect and customize a template: pandoc -D html > templates/report.html, then --template templates/report.html. Same for latex, typst.
  • Small transformations belong in Lua filters, not regex post-processing:
-- filters/callout.lua: turn > **Note:** blockquotes into a styled div
function BlockQuote(el)
  local first = el.content[1]
  if first and first.t == "Para" and first.content[1] and first.content[1].t == "Strong" then
    local label = pandoc.utils.stringify(first.content[1])
    if label == "Note:" then
      return pandoc.Div(el.content, pandoc.Attr("", {"callout"}))
    end
  end
end

pandoc report.md --lua-filter filters/callout.lua -o report.html

Gotchas

  • PDF via LaTeX fails on Unicode glyphs missing from the font (emoji, CJK). Set mainfont to a font with coverage and use lualatex/xelatex, or use Typst.
  • Wide tables overflow PDF pages; use landscape sections, smaller font via template, or split the table.
  • Relative links between Markdown files (other.md) stay as .md links in HTML; rewrite with a Lua filter or a site generator if publishing multiple pages.
  • Smart quotes and dashes come from the smart extension; disable with markdown-smart for code-heavy prose that must keep straight quotes.
  • DOCX tables take the reference doc’s “Table” style; pandoc does not apply Word table styles beyond that.

Verification

  • Build every target from a clean build/ directory with --fail-if-warnings where practical; no citation key not found or missing-resource warnings.
  • Open each output (render the PDF first page to PNG with pdftoppm -png -r 60 -f 1 -l 1, inspect the DOCX with docx-documents tooling, view the HTML) and check TOC, headings, figures, tables, citations, and code blocks.
  • Commit the defaults files, reference.docx, CSL, templates, and filters so builds are reproducible.

About this skill

Written and maintained by the Claude Skills editors to the same editorial standard as every skill in the directory: a selective trigger, a real workflow, known pitfalls and a verification step. First published , last updated . MIT licensed.

esc