Extending Quarto

Lecture 17

Dr. Benjamin Soltoff

Cornell University
INFO 3312/5312 - Spring 2024

March 26, 2024



  • Homework 05
  • Project 02 proposals



  • Identify a reproducible Quarto workflow
  • Define major components of Quarto documents
  • Customize individual Quarto documents using code chunk options and YAML header


  • Extend Quarto to multi-file projects/websites
  • Examine structure of Quarto blog
  • Publish Quarto documents to the web


Quarto basics

title: Gun deaths
author: Your name
date: today
format: html

#| label: setup
#| include: false

youth <- gun_deaths |>
  filter(age <= 65)

# Gun deaths by age

We have data about `r nrow(gun_deaths)` individuals killed by guns. Only `r nrow(gun_deaths) - nrow(youth)` are older than 65. The distribution of the remainder is shown below:

#| label: youth-dist
#| echo: false
ggplot(data = youth, mapping = aes(x = age)) + 
  geom_freqpoly(binwidth = 1)

# Gun deaths by race

#| label: race-dist
youth |>
  mutate(race = fct_infreq(race) |> fct_rev()) |>
  ggplot(mapping = aes(y = race)) +
  geom_bar() +
  labs(y = "Victim race")

Major components

  1. A YAML header surrounded by ---s
  2. Chunks of code surounded by ```
  3. Text mixed with simple text formatting using the Markdown syntax

Quarto code chunks

Rendering process

A schematic representing rendering of Quarto documents from .qmd, to knitr or jupyter, to plain text markdown, then converted by pandoc into any number of output types including html, PDF, or Word document.

Rendering process

A schematic representing the multi-language input (e.g. Python, R, Observable, Julia) and multi-format output (e.g. PDF, html, Word documents, and more) versatility of Quarto.

Code chunks

#| label: youth-dist
#| message: false
#| warning: false

# code goes here
  • Naming code chunks
  • Code chunk options
  • eval: true
  • include: true
  • echo: true
  • message: true or warning: true
  • cache: true

Inline code

We have data about `r nrow(gun_deaths)` individuals killed by guns.

Only `r nrow(gun_deaths) - nrow(youth)` are older than 65. The distribution of the remainder is shown below:

We have data about 100798 individuals killed by guns.

Only 15687 are older than 65.

YAML header

YAML header

title: Gun deaths
author: Benjamin Soltoff
date: today
format: html
  • YAML Ain’t Markup Language
  • Standardized format for storing hierarchical data in a human-readable syntax
  • Defines how quarto renders your .qmd file

HTML document

title: Gun deaths
author: Benjamin Soltoff
date: today
format: html

Table of contents

title: Gun deaths
author: Benjamin Soltoff
date: today
    toc: true
    toc-depth: 2

Appearance and style

title: Gun deaths
author: Benjamin Soltoff
date: today
    theme: superhero
    highlight-style: github

Global options

title: "My Document"
    fig-width: 7
  echo: true
  message: false
    dev: ragg_png
  • Default document-level options
  • Some options are set with format
  • Some options are set with execute
  • Some options are set by knitr/jupyter

PDF document

title: Gun deaths
author: Benjamin Soltoff
date: today
format: pdf


title: Gun deaths
author: Benjamin Soltoff
date: today
format: revealjs

Quarto supports multiple presentation formats

  • revealjs (HTML)
  • pptx (PowerPoint)
  • beamer (\(\LaTeX\)/PDF)

Websites using Quarto


  • Websites are essentially format: html + a Quarto Project
  • Website is different than format: html in that it has multiple pages
  • Website is our first exploration into Quarto Projects
    • Similar to R Projects, but for Quarto!
    • You used them for project 01

Why not WordPress, Tumblr, Medium.com, Blogger.com, etc?1

  • No Quarto support (even math support is often nonexistent or awkward)

  • Huge benefits of static websites compared to dynamic websites

  • All static files, no PHP or databases, no login/password, work everywhere (even offline)

  • Typically fast to visit (no computation needed on the server side), and easy to speed up via CDN

RStudio > New Project > New Quarto Blog

Create a blog

  • A blog is a website with specific “opinions” already made
  • Includes a listing automatically from posts directory
  • Can build custom listings in several ways

Core blog workflow

  • Create a new folder under /posts - this folder will be the “slug” URL (like bensoltoff.com/my-new-post/)
  • Create a new index.qmd within the new folder

Application exercise


  • Go to the course GitHub org and find your ae-14 (repo name will be suffixed with your GitHub name).
  • Clone the repo in RStudio Workbench, open the Quarto document in the repo, and follow along and complete the exercises.
  • Render, commit, and push your edits by the AE deadline – end of tomorrow

Your Turn

  • Explore the repo directories and file structure
  • What types of files are stored in the repo? Where can you find source code files? Output files?

Rendering posts

Rendering posts

  • On a specific post, Render with RStudio > Render
  • Build tab > Render/Preview Website

These will preview the entire website

When you render the website, it will re-execute code in older posts. Not ideal in many situations!

Your Turn

  • Let’s render the index.qmd together!
  • Now, let’s try Build > Render Website
  • Stage/commit/push all changes to GitHub


You can use the freeze option to denote that computational documents should never be re-rendered during a global project render, or alternatively only be re-rendered when their source file changes

  freeze: true  # never re-render during project render
  freeze: auto  # re-render only when source changes

freeze: true is typically added to a _metadata.yml file within a specific directory, affecting all files in that directory.

In the case of a blog - the _metadata.yml is saved at the root of the posts directory. You can have it only within specific subdirectories for more complex sites.


Cache on the other hand, stores the results of computations for a specific file.

Note that cache invalidation is triggered by changes in chunk source code (or other cache attributes you’ve defined).

  cache: true

I typically use cache throughout various types of outputs when I have computationally expensive chunks.

Your Turn

  • Render index.qmd in the project directory and note the items that are built

  • Explore the _freeze directory

  • Marvel at the “beautiful” JSON - it’s not for you, it’s for the machine



default, cerulean, cosmo, cyborg, darkly, flatly, journal, litera, lumen, lux, materia, minty, morph, pulse, quartz, sandstone, simplex, sketchy, slate, solar, spacelab, superhero, united, vapor, yeti, zephyr

To change theme, modify the bottom of your website’s _quarto.yml

    theme: cosmo


Your Turn

  • Open _quarto.yml and change the theme to one of the support Bootswatch themes
  • Modify posts/gun-deaths/index.qmd in some way
  • Render the website!

Adding an About page

Adding an About page

title: "Benjamin Soltoff"
  template: jolla
  image: profile.png
    - icon: twitter
      text: twitter
      href: https://twitter.com/soltoffbc
    - icon: github
      text: Github
      href: https://github.com/bensoltoff
    - icon: building
      text: Faculty page
      href: https://infosci.cornell.edu/content/soltoff

About page templates

  template: trestles

Your Turn

  • Open your about page (about.qmd)
  • Change some of the details, add more details and choose a specific template (jolla, trestles, solana, marquee, broadside)
  • Render it!

Website organization

Landing page

  • The landing page for your website defaults to the blog/listings page
  • your-proj/index.qmd becomes your “home page”
  • If you want your “About Me” page to be the landing page, rename your index.qmd -> blog.qmd and about.qmd -> index.qmd
  • Re-structuring your website also requires modifying your _quarto.yml
  title: "My blog name"
  site-url: "https://MyBlogSiteUrl.com"
     - blog.qmd
     - icon: twitter
       href: "https://twitter.com/my_user_name"

Example: https://www.ericekholm.com/posts/demo-quarto-site/



Type Description
default A blog style list of items.
table A table of listings.
grid A grid of listing cards.


By default, listings will appear in full width rows that display the item’s metadata (author and date), title, description, and image.

Grid style listings display a card for each item.

The table listing style provides a traditional tabular layout.

Your Turn

  • Open your existing Quarto blog from before
  • Let’s change the listing type of our blog - change from default to grid
  • Re-render the index.qmd



Destination Description
GitHub Pages Publish content based on source code managed within a GitHub repository. Use GitHub Pages when the source code for your document or site is hosted on GitHub.
RStudio Connect Publishing platform for secure sharing of data products within an organization. Use RStudio Connect when you want to publish content within an organization rather than on the public internet.
Netlify Professional web publishing platform. Use Netlify when you want support for custom domains, authentication, previewing branches, and other more advanced capabilities.
Other Services Content rendered with Quarto uses standard formats (HTML, PDFs, MS Word, etc.) that can be published anywhere. Use this if one of the methods above don’t meet your requirements.


Static Only

  • quarto R package: quarto::quarto_publish_???()


  • Evaluate R/Python code and render on a schedule

  • RStudio Connect

  • rsconnect::deployDoc(quarto = "path/to/quarto")

    • rsconnect::deployDoc(quarto = quarto::quarto_path())

Static Publish

  • quarto::quarto_publish_???()

    • quarto_publish_site(server = "rstudioconnect.example.com")
    • quarto_publish_doc(server = "rpubs.com")
    • quarto_publish_app(server = "shinyapps.io")


  • Cheat code: Netlify drop

GitHub Pages

  • Render contents locally with the “Build Website” button
  • Stage/commit/push the rendered files to GitHub – site built automatically

Check out your site at



Similar to blog, but less of a focus on listing/posts and more focus on individual pages and overall navigation.

Quarto Project

When you create a project, a _quarto.yml config file is created. Here is an example of what the _quarto.yml looks like:

  output-dir: _output

toc: true
number-sections: true
bibliography: references.bib  
    css: styles.css

Quarto Projects

  • Minimal project has at least 1x file and 1x _quarto.yml
  • A project is a directory (and can have sub-directories)

A typical project is used to:

  • Aggregate content (website/blog/book)
  • Share metadata (YAML config) across multiple files
  • Render an entire directory together or redirect output to another directory
  • Freeze computation across a project or team

Wrap up

Wrap up

  • Quarto is a versatile tool for creating documents, websites, and more
  • Can be used for single or multiple-document projects
  • Generates static websites incorporating programmatic content (R, Python, etc.)
  • Websites can be published directly through GitHub or alternative providers