Quarto Markdown: Publish Reports from .qmd Files

September 11, 2026 · 9 min read

Quarto Markdown: Publish Reports from .qmd Files

Quarto markdown is Pandoc's Markdown plus a YAML header, executable code cells, callouts, and cross-references. You save it in a .qmd file and render it with quarto render. This guide walks through one complete report, separates the syntax any Markdown editor renders from the Quarto-only parts, and ends with the commands for HTML and PDF output.

What Is a .qmd File?

A .qmd file is a plain text file in Quarto's dialect of Markdown. Quarto's own Markdown basics page states that Quarto is based on Pandoc and uses its variation of Markdown as the underlying document syntax. If you already write .md files, roughly 80 percent of a .qmd file will look familiar.

The other 20 percent is what makes it a report rather than a document:

  • A YAML header between --- lines sets the title, author, and output format.
  • Executable code cells in Python, R, Julia, or Observable JS run when you render, and their output (tables, plots, printed values) lands in the document.
  • Callouts, cross-references, and shortcodes add publishing features Markdown lacks.
  • A render step. Nothing displays the file directly; quarto render turns it into HTML, PDF, DOCX, slides, or a website.

Quarto itself is a command-line tool written in TypeScript and distributed as a standalone installer that bundles its own runtime. It's the successor to R Markdown, but it isn't tied to R or to any single language. The same .qmd file can hold a Python cell and an R cell. One project can render a single report, a book, or a full website from one folder of sources.

Is Quarto a Markdown Language?

Not quite. Quarto is a publishing system; the language it reads is Pandoc Markdown with extensions. That distinction tells you what's portable. Everything in the left column below renders in any CommonMark or Pandoc-aware editor. Everything on the right needs Quarto.

Portable (any Markdown editor)Quarto-only
Headings, emphasis, lists, links, imagesExecutable cells with #| options
Pipe tablesCallout blocks ::: {.callout-note}
Fenced code blocksCross-references @fig-plot, @tbl-data
Footnotes [^1]Shortcodes such as page break and keyboard keys
LaTeX math between dollar signsFenced div attributes for layout and columns
YAML front matter (ignored by most editors)Output options in the YAML header

That split is the reason you can draft a Quarto report in a general Markdown editor and only switch to Quarto for the render. The YAML block and the Quarto-only lines pass through as plain text; nothing breaks.

The reverse is also true. Feed a plain .md file to quarto render and it comes out as a styled HTML page with a table of contents. Pandoc Markdown is a superset of what most editors write. Quarto-specific features only appear when you ask for them.

One Complete Quarto Markdown Report

Here is a short report that uses each feature once. Save it as report.qmd.

---
title: "Sensor Calibration Report"
author: "Dana Ortiz"
date: 2026-09-11
format:
  html:
    toc: true
  pdf:
    number-sections: true
execute:
  echo: false
---

## Method {#sec-method}

We calibrated three sensors against a reference. The fit uses
$y = a x + b$ with the error defined in @eq-rmse.

::: {.callout-note}
Readings below 5 °C were excluded; see @tbl-summary.
:::

| Sensor | Slope | Offset |
|:-------|------:|-------:|
| A      | 1.02  | -0.3   |
| B      | 0.98  | 0.1    |

: Calibration summary {#tbl-summary}

$$
\text{RMSE} = \sqrt{\frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2}
$$ {#eq-rmse}

```{python}
#| label: fig-residuals
#| fig-cap: "Residuals for sensor A"
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4], [0.1, -0.2, 0.05, 0.0])
plt.show()
```

@fig-residuals shows no drift. Details are in @sec-method.

Rendered, you get a titled page with a table of contents, a numbered table with a caption, and a numbered equation. The Python cell produces a plot, and every @ reference becomes a link such as Figure 1 or Table 1. The echo: false line in the header hides the Python source in the output while keeping the plot.

Quarto-Only Syntax: Callouts, Cross-References, Cell Options, Shortcodes

These are the four additions that turn Markdown into a report. Each is documented on quarto.org; the essentials are here.

Callouts. Five types exist per the callouts documentation: note, tip, warning, caution, and important. Write a fenced div with the class callout- plus the type. Leave the title out and Quarto uses the type name, so a bare callout-warning block is headed Warning. Set a title with a ## heading inside the block or a title="..." attribute, change the look with appearance="simple" or "minimal", and make it expandable with collapse="true". Our Markdown callout post covers the equivalent syntax on GitHub, Obsidian, and Docusaurus.

Cross-references. Every referenceable item gets an ID with a reserved prefix: fig-, tbl-, eq-, sec-, lst-, and more listed in the cross-references guide. Reference it with @ and the ID. Figures from Markdown images take the ID in braces after the image; figures from code take it from the label cell option. Section references need number-sections: true in the YAML, and IDs must be lower case.

Cell options. Lines at the top of a code cell that start with #| are options, not code. The ones you'll use: echo (show the source), eval (run it), output (show results), warning, error, include (suppress everything), and fig-cap. Set defaults for the whole document under execute: in the YAML and override per cell. This is the biggest visible change from R Markdown, where the same options lived inside the chunk header braces.

Shortcodes. Double braces with angle brackets insert page breaks, keyboard keys, and embedded content, for example a page break shortcode written as {{< pagebreak >}}. Any Markdown editor shows these literally, which is harmless.

For equations, Quarto uses the same dollar-sign delimiters as GitHub and Jupyter; the Markdown equation guide covers the LaTeX inside them.

Try the Portable Parts of Quarto Markdown in the Editor

The report above, minus the YAML header and the code cell, is loaded here. The heading, callout text, table, and equation render in the preview. The callout fence, the caption ID, and the @ references show as plain text, which is what any non-Quarto renderer does with them. (The YAML header is left out because a plain renderer turns its --- lines into a rule and a heading.)

Method

We calibrated three sensors against a reference. The fit uses y=ax+by = a x + b and the error is defined in @eq-rmse.

::: {.callout-note}
Readings below 5 °C were excluded; see @tbl-summary.
:::

Sensor Slope Offset
A 1.02 -0.3
B 0.98 0.1

: Calibration summary {#tbl-summary}

@fig-residuals shows no drift.

65 words386 characters16 lines
Markdown

We prefer drafting the prose and tables this way, with a live preview, and adding the cells and references in the final pass. For a plain Markdown report that needs a PDF today, the Markdown to PDF tool skips the TeX install entirely. Just remember it renders the portable column only; callouts and cross-references need the real quarto render.

How Do You Render a .qmd to HTML and PDF?

Install Quarto from quarto.org, which offers a single installer for Windows, macOS, and Linux. Then run these from the folder holding your file.

quarto render report.qmd --to html
quarto render report.qmd --to pdf
quarto render report.qmd --to docx
quarto preview report.qmd

quarto preview opens the HTML in a browser and re-renders on every save. Without --to, Quarto renders every format listed in the YAML header; quarto preview uses the first one.

Three prerequisites trip people up:

PDF needs a TeX distribution. Quarto's PDF basics page is direct about this. The one-line fix is quarto install tinytex. The format reference lists lualatex as the default engine for LaTeX output, with xelatex and pdflatex as alternatives via pdf-engine.

Python cells need Jupyter. Install the jupyter package with pip or conda. Quarto renders .ipynb notebooks directly too, but by default it doesn't execute their cells; add --execute to run them.

R cells need R and the knitr package. Quarto picks the engine from the code cells it finds, or you can set engine: knitr or jupyter: python3 in the YAML.

The Jupyter Markdown cheat sheet covers the Markdown cells inside notebooks, which Quarto renders unchanged.

Is Quarto Replacing R Markdown?

Posit's answer, on its R Markdown FAQ, is no. R Markdown is not going away, will continue to be actively supported, and has no deprecation plans. If you like R Markdown there's no need to switch. New features, though, land in Quarto, and most .Rmd files render under Quarto without modification.

What actually changes when you move a report across:

  • The extension goes from .Rmd to .qmd.
  • Chunk options move from the braces on the fence line to #| lines inside the cell.
  • rmarkdown::render() becomes quarto render on the command line, or the Render button in RStudio and VS Code.
  • The YAML output: key becomes format:.
  • Callouts, cross-references, and multi-language cells become available without packages.

The R Markdown cheat sheet has the chunk syntax if you're maintaining both. One acknowledged limitation: Quarto's PDF output depends on LaTeX, so a machine without TeX can render HTML and DOCX but not PDF until you run the TinyTeX install.

Quarto Markdown FAQ

Quarto markdown keeps the Markdown you know and adds the four things a report needs: a YAML header, executable cells with #| options, callouts, and cross-references. Draft the portable parts in the editor, add the Quarto-only lines when the text is settled, and let quarto render produce the HTML and PDF.