Creating Documents with Quarto
Quarto is an open-source scientific and technical publishing system built on Pandoc. It extends R Markdown to support reproducible research workflows in Python, R, Julia, and Observable. This guide shows you how to create documents with Quarto, from simple HTML output to full multi-document websites.
Creating documents with Quarto starts with a .qmd file, a plain text file that combines YAML metadata, Markdown prose, and executable code chunks. The rendering process executes the code, captures output and figures, and produces a finished document in your chosen output format. Quarto handles the execution, formatting, and cross-referencing automatically.
Why Quarto?
Quarto solves several limitations of R Markdown. It provides a unified authoring framework across programming languages. The output quality is higher by default. YAML configuration is cleaner and more consistent. Projects can mix multiple languages in a single document.
If you already know R Markdown, Quarto feels familiar but with improved syntax and capabilities. The main benefits include consistent syntax across languages, better defaults for figures and tables, native support for Jupyter notebooks, and improved extension system.
Installing Quarto
Install Quarto from the command line or download from the official website. The examples below cover macOS, Linux, and Windows installation from package managers. After installing the CLI, verify the installation from R with quarto::quarto_version(), which confirms that Quarto is on your system PATH and that the R package can communicate with the CLI.
# macOS
brew install quarto
# Linux
sudo wget https://github.com/quarto-dev/quarto-cli/releases/download/v1.4.550/quarto-1.4.550-linux-amd64.deb
sudo dpkg -i quarto-1.4.550-linux-amd64.deb
# Windows
choco install quarto
After installation, verify from R that Quarto is available on your system PATH. Running quarto::quarto_version() should return the installed version number, confirming that the CLI and R package can communicate. If the function returns NULL or an error, Quarto may not be on your system PATH; reinstall via your package manager and restart the R session.
quarto::quarto_version()
Creating your first Quarto document
A Quarto document is a plain text file with the .qmd extension. The header contains YAML metadata between --- delimiters. Below the header, you write markdown content mixed with code blocks that Quarto executes during rendering. The YAML header defines metadata like the title, author, and output format, which controls how Pandoc processes the document into its final form.
---
title: "My First Quarto Document"
author: "Your Name"
date: "2026-03-11"
format: html
---
Below the YAML header, the body of the document mixes Markdown prose with executable code chunks. Each chunk is fenced with triple backticks and a language identifier; r tells Quarto to execute the code with the R engine and embed the output directly in the rendered document. The result appears as a formatted code block followed by its printed output.
# This is an R code chunk
summary(cars)
The triple backticks with r tell Quarto to execute the code with the R engine. Output appears below the code block in the rendered document.
Rendering documents
Render your document from the R console with the quarto package, which provides a programmatic interface to the Quarto CLI. The quarto_render() function accepts the file path and returns once the document has been fully rendered to its output format. You can also render directly from the terminal using the quarto CLI, which is the preferred approach in shell scripts and CI/CD pipelines where starting an R session adds unnecessary overhead.
quarto render document.qmd
Quarto produces output in the _quarto directory by default. The output filename matches the input with the appropriate extension.
Output formats
Quarto supports multiple output formats. Change the format option in the YAML header:
HTML documents
HTML is the default output format and requires no additional tools. A basic format: html produces a clean web page, but Quarto supports extensive customization through nested YAML options. You can enable a table of contents, automatic section numbering, and Bootswatch themes from a single configuration block.
# Minimal HTML output
format: html
# Full-featured HTML with toc, numbering, and theming
format:
html:
toc: true
number-sections: true
theme: cosmo
css: styles.css
The toc option generates a table of contents. number-sections adds section numbers automatically. Themes include cosmo, bootstrap, sandstone, and many others.
PDF documents
PDF output requires a working LaTeX installation on your system. The simplest way to satisfy this dependency: install tinytex from R, which provides a lightweight TeX distribution with just the packages needed for R-generated PDFs. Once LaTeX is installed, Quarto detects it and PDF rendering works without further configuration. The following command renders to PDF regardless of the default format setting:
format: pdf
Before rendering to PDF, ensure a LaTeX distribution is available. The tinytex package installs a minimal TeX environment directly from R, including everything needed for standard R-generated PDFs. After installation, Quarto’s quarto render --to pdf command works without additional configuration.
install.packages("tinytex")
tinytex::install_tinytex()
With LaTeX in place, render to PDF from the terminal using the --to flag to override the format specified in the YAML header. This lets you generate multiple formats from a single source file without editing it each time.
quarto render document.qmd --to pdf
Word documents
Word output is useful for collaborative workflows where colleagues prefer Microsoft Word. The output is a .docx file that can be edited in Word or Google Docs without any special tools, making it the most accessible format for sharing results with non-technical collaborators.
format: docx
Code execution options
Control how code chunks execute with options in the YAML header or inline. These options give you fine-grained control over what readers see: you can suppress warnings, hide source code, or show errors depending on the audience. Global option blocks apply to every chunk in the document, which is the right choice for consistent settings like always hiding code in a final report meant for non-technical readers.
execute:
echo: true # Show source code
warning: false # Hide R warnings
error: true # Show error messages
include: false # Hide code, show output only
Global options in the YAML header set document-wide defaults, but individual code chunks often need different behavior. Per-chunk options use the #| (hash-pipe) syntax — a language-agnostic comment format that works identically for R, Python, and Julia chunks. Each #| line sets one option, and chunk-level settings override the global defaults defined in the YAML execute block.
#| echo: false
#| warning: true
#| fig-width: 6
#| fig-height: 4
summary(cars)
The hash-pipe syntax is the recommended approach for Quarto documents. It keeps options close to the code they affect.
Figures and tables
Quarto automatically numbers figures and tables. Reference them in your text using the @ symbol. This creates clickable links that jump to the figure or table.
For figures, add a label and caption in your code chunk. The label uses the fig- prefix, which tells Quarto to number this as a figure and register it for cross-referencing. The caption text appears below the figure in the rendered output.
#| label: fig-scatter
#| fig-cap: "Scatter plot of pressure"
plot(pressure)
Reference it in your text as @fig-scatter. Quarto generates the figure number automatically based on its position in the document. For tables, the pattern is identical but uses the tbl- prefix instead. The tbl-cap option sets the table caption, and tables can be rendered from any R function that produces tabular output, such as kable() from the knitr package.
#| label: tbl-summary
#| tbl-cap: "Summary statistics"
#| echo: false
kable(summary(cars))
The kable() function from the knitr package produces nicely formatted tables. Cross-references work uniformly across figure and table labels: referencing @fig-scatter or @tbl-summary in prose generates the correct name and number in the output.
For sections, add an id to the heading using curly brace syntax. This assigns a machine-readable label to the section that can be referenced from anywhere in the document, even in other files within a Quarto project.
## Introduction {#sec-intro}
See @sec-intro for the background.
The curly brace syntax assigns a label to the section. Reference it with the @ symbol elsewhere in the document. For equations, Quarto supports LaTeX math notation with standard dollar-sign delimiters. Inline math uses single dollar signs, while display math uses double dollar signs to center the equation on its own line.
The mean is calculated as:
$$\bar{x} = \frac{1}{n}\sum_{i=1}^{n} x_i$$
Parameterized reports
Create reports that generate different outputs from the same template. Parameters pass values into the document at render time, so one source file can produce region-specific, year-specific, or product-specific reports without duplication. The params block in the YAML header declares parameters and their default values.
---
title: "Sales Report"
format: html
params:
region: "US"
year: 2025
product: null
---
Access parameters in R code using the params object, which is automatically available in all code chunks. Parameters behave like list elements and can be used for filtering, conditional logic, or any computation that should vary across report runs. The region and year fields control data filtering, while the product parameter is optional; checking for NULL lets the report run with or without product-specific detail.
library(dplyr)
sales_filtered <- sales |>
filter(region == params$region, year == params$year)
if (!is.null(params$product)) {
sales_filtered <- sales_filtered |>
filter(product == params$product)
}
Render specific parameter values from R by passing a named list to quarto_render(). The parameter names must match those declared in the YAML header. This programmatic approach is ideal for automated reporting pipelines that generate dozens of parameterized reports from a single template.
quarto::quarto_render("report.qmd",
params = list(region = "EU", year = 2025))
Parameterized reports are useful for recurring reports like monthly sales summaries or quarterly analytics. With a single template and a parameter sweep script, you can generate a report for every region and month without copying or editing the source document.
Projects
Quarto projects organize multiple documents into a website, book, or blog. Create a project directory with a configuration file that defines the project type, output directory, and site navigation. The _quarto.yml file at the project root is the central configuration hub: all documents in the project inherit its settings, and it defines shared elements like the navigation bar, sidebar layout, and theme.
project:
type: website
output-dir: _site
website:
title: "My Documentation"
navbar:
left:
- href: index.qmd
text: Home
- href: guide.qmd
text: Guide
Build all documents in the project with a single command. The quarto render command processes every .qmd file in the project directory, applying the shared configuration and resolving cross-references across files. The output goes to the directory specified by output-dir in the project config.
quarto render myproject/
Projects handle navigation, cross-references across files, and shared resources automatically. Quarto also includes publishing commands for several hosting platforms. Each command handles building, packaging, and uploading the rendered site to the target service with a single CLI call, making deployment a one-step CI job.
quarto publish gh-pages
This command builds the project and pushes to the gh-pages branch. For Netlify, which provides continuous deployment directly from your repository, the command creates a Netlify deployment with one step.
Posit Connect
Posit Connect hosts Quarto documents with enterprise authentication and scheduling. Publishing to Connect requires the rsconnect package and appropriate server credentials configured in your R environment. Once connected, quarto publish connect deploys the rendered document directly to the server.
quarto publish connect
Quarto project types
Quarto supports several project types: website for multi-page sites with navigation, book for long-form documents with chapters, blog for date-ordered posts, and manuscript for scientific papers with cross-references. quarto create project website my-site creates the project scaffolding. The _quarto.yml file configures the project type, navigation, theme, and output format.
For documentation sites similar to pkgdown, Quarto websites with a sidebar navigation provide a clean alternative. The key advantage: Quarto websites support multiple output formats from the same source, so a documentation site can produce both the HTML website and a PDF version from the same .qmd files.
Cross-references
Quarto has built-in cross-reference support for figures, tables, equations, and sections. @fig-scatter in prose references a figure labeled #| label: fig-scatter in a code chunk. @tbl-summary references a table. @sec-methods references a section with the id methods. Cross-references are automatically numbered and linked in HTML output, making it easy to refer to specific elements without manually tracking numbering.
Referencing them in text with the at-sign syntax produces the label text, “Figure 1” for HTML, “Fig. 1” for PDF, with a hyperlink in HTML and a correct reference in PDF. Cross-references update automatically when numbering changes, eliminating the maintenance burden of keeping reference numbers synchronized with content.
For scientific papers, cross-references to equations (@eq-model) and theorems are also supported. The citeproc integration handles bibliography management via BibTeX or CSL JSON, with citation syntax [@key] that matches the Pandoc citation convention.
For books and long reports, section cross-references with the sec- prefix let you reference earlier or later sections by label rather than by number. When sections are reordered, all references to them update without any manual editing. This makes Quarto books significantly easier to maintain than Word documents where section numbers must be updated manually.
Publishing workflows
quarto publish gh-pages deploys a website to GitHub Pages with one command. quarto publish netlify deploys to Netlify. For Posit Connect, the rsconnect package with quarto::quarto_publish_app() handles deployment. Each deploy command handles building the site, creating the deployment artifacts, and uploading them to the target platform.
For academic writing, Quarto’s manuscript project type provides journal submission support with jss, jasa, and elsevier formats. BibTeX and CSL bibliographies integrate directly. quarto::quarto_render() renders with specific output formats, and quarto check diagnoses common configuration issues.
Quarto as a universal publishing system
Quarto renders documents to HTML websites, PDF via LaTeX, Word documents, PowerPoint presentations, ePub books, and interactive formats. A single source file can target multiple output formats by changing a command-line argument. This universality makes Quarto useful beyond data analysis reports, documentation sites, technical books, academic papers, and presentation slides all fit within the same authoring system.
The multi-language support extends beyond R. Python, Julia, and Observable JavaScript all execute in Quarto documents alongside R. Mixed-language documents use the appropriate engine for each language, knitr for R, Jupyter for Python and Julia, and can share data between languages through shared file formats. This makes Quarto useful for teams that use multiple languages without requiring everyone to adopt one.
Project types
A standalone Quarto document renders to one output file. A Quarto project is a directory with a _quarto.yml configuration file that groups multiple documents with shared settings. Project types include website (multiple pages with navigation), book (ordered chapters with cross-references), and blog (chronological posts with tags). Each type applies appropriate defaults and generates the linking structure that type expects.
The website project type builds from a collection of qmd files and produces a navigable HTML site. The _quarto.yml file configures the navigation structure, theme, and sidebar organization. Rendering the project renders all documents and outputs a complete site directory that can be deployed to any static hosting service. GitHub Pages and Netlify both support direct deployment from the project output directory.
Quarto vs R markdown for new projects
For any new project that does not have an existing R Markdown infrastructure, Quarto is the better starting point. It supports multiple languages from the start without separate packages, has better cross-referencing, and has more active development. The learning curve from R Markdown is minimal because the underlying concepts, YAML header, executable code chunks, Markdown prose, are the same.
Existing R Markdown documents continue to work because Quarto can render them. The migration path is gradual: you can convert documents one by one or simply start all new documents as Quarto while leaving old ones as R Markdown. The two formats coexist in the same project without conflict.
Quarto for teams
Quarto’s multi-language support makes it the right choice for teams where some members use R and others use Python. A shared Quarto document can have R chunks that use ggplot2 for visualization and Python chunks that use scikit-learn for modeling. Both compute their results in the same render pass. The output is one unified document, not two separate pieces stitched together.
For team documentation sites built with Quarto, the same _quarto.yml project configuration applies to everyone. Version-controlling the configuration ensures that all team members build with the same settings. A CI workflow that renders the full site on every commit to the main branch catches broken documents before they reach the published site.
Rendering programmatically
Quarto’s command-line interface enables rendering from shell scripts and CI workflows. The quarto render command accepts format overrides, allowing one source file to produce multiple output formats in a single CI pipeline. Combining this with a parameter sweep — rendering the same document with different parameters using a shell loop or an R script that calls quarto_render() — produces variant documents without duplicating source files.
Quarto also provides R and Python APIs. The quarto R package wraps the CLI with R functions that accept R objects as arguments, making it easier to parameterize renders from within an R script. This is particularly useful for automated reporting pipelines that need to pass data objects directly rather than through YAML parameter files.
Inspecting and debugging renders
When a Quarto document fails to render, the error message from knitr or Jupyter identifies the failing code chunk. Rendering with quarto render --debug produces detailed output including the intermediate Markdown file before Pandoc processing. Examining this intermediate file separates execution errors (in the code) from rendering errors (in the Pandoc conversion).
Code chunk errors show up with the chunk label and line number. For documents that take a long time to render, setting execute: freeze: true in the YAML header caches all chunks so that subsequent renders skip execution entirely. This is useful for reviewing the document layout and prose when the code has not changed.
See also
- Getting Started with Quarto: Setup your first Quarto document and learn the core workflow.
- Quarto Dashboards: Build interactive dashboards directly from Quarto documents.
- String Manipulation with stringr: Clean and prepare text for your Quarto reports.
- ggplot2 Introduction: Create figures to embed in your Quarto output.
- Building R Packages: Package development practices for reproducible research.
- Data Manipulation with dplyr: Prepare data for inline Quarto analysis chunks.