Building Dashboards with Quarto

· 5 min read · Updated March 11, 2026 · intermediate
quarto dashboards interactive data-viz shiny

Quarto dashboards transform your R analysis into interactive, visually appealing web pages. A dashboard presents key metrics, charts, and data tables in a layout that stakeholders can explore without touching code.

This tutorial covers creating a Quarto dashboard from scratch. You’ll learn the dashboard format, layout components, and deployment options.

What is a Quarto Dashboard?

A Quarto dashboard is an HTML document with a special format that arranges content in a grid. Each cell in the grid can contain text, plots, tables, or interactive components. The browser renders the dashboard without requiring a Shiny server, though you can add Shiny for full interactivity.

Dashboards differ from regular Quarto documents in three ways:

  1. The document format is dashboard instead of html
  2. Content lives in a grid layout defined by YAML
  3. Special components like value boxes and tabsets organize information

Setting Up Your Dashboard

Create a new Quarto file with the dashboard format. In RStudio, choose File > New File > Quarto Dashboard. Alternatively, create a .qmd file with this YAML header:

---
title: "My Dashboard"
format: dashboard
---

The dashboard format enables several layout options. You define the page structure in the YAML, then add content in markdown and code cells below.

Layout Options

Quarto dashboards support several layout mechanisms. Choose based on how you want to present your data.

Pages and Rows

The simplest layout uses pages. Each page is a separate tab in the dashboard:

---
format: dashboard
pages:
  - title: "Overview"
    blocks:
      - |
        ## Welcome
        This is the overview page.
  - title: "Details"
    blocks:
      - |
        ## Detailed View
        More information here.
---

Place navigation in a sidebar that stays visible while users explore content:

---
title: "Sales Dashboard"
format: dashboard
theme: cosmo
sidebar:
  - title: "Navigation"
    items:
      - text: "Overview"
        href: "#overview"
      - text: "Trends"
        href: "#trends"
content:
  - id: overview
    blocks:
      - |
        ## Sales Overview
        Welcome to the sales dashboard.
  - id: trends
    blocks:
      - |
        ## Sales Trends
        Charts and analysis go here.
---

Value Boxes

Value boxes highlight key metrics at the top of your dashboard. They display a number with a label and optional icon:

```{r}
#| value-boxes
library(bslib)
library(gapminder)

total_gdp <- gapminder::gapminder |>
  dplyr::filter(year == 2007) |>
  dplyr::summarise(sum(gdpPercap * pop)) |>
  dplyr::pull()

bslib::value_box(
  "Total GDP",
  scales::dollar(total_gdp),
  showcase = bsicons::bs_icon("graph-up-arrow"),
  theme = "primary"
)
```

The value-boxes cell option tells Quarto to render the output as value boxes. Each value box appears as a card in a responsive grid.

Tabsets

Group related content into tabs within any section:

## Analysis

::: panel-tabset
### Chart View

```{r}
#| fig-width: 6
plot(mtcars$wt, mtcars$mpg)
```

### Table View

```{r}
#| echo: false
head(mtcars)
```
:::

The `::: panel-tabset` div wraps content into clickable tabs. Users see one tab at a time, keeping the interface clean.

Adding Interactive Components

Plotly Charts

Make plots interactive with the Plotly library:

```{r}
#| fig-width: 8
library(plotly)

plot_ly(mtcars, x = ~wt, y = ~mpg, color = ~factor(cyl),
        mode = "markers", type = "scatter")
```

Plotly renders interactive charts that users can zoom, pan, and hover for details. This works without a Shiny server.

Shiny Integration

For full interactivity, embed a Shiny app in your dashboard:

---
format: dashboard
server: shiny
---

```{r}
library(shiny)

ui <- fluidPage(
  sliderInput("n", "Number of points:", 10, 100, 50),
  plotOutput("plot")
)

server <- function(input, output) {
  output$plot <- renderPlot({
    plot(rnorm(input$n))
  })
}

shinyApp(ui, server)
```

The server: shiny option runs a Shiny server in the background. Users interact with controls, and the output updates in real-time.

Complete Example

Here is a practical dashboard showing sales metrics:

---
title: "Quarterly Sales Dashboard"
format: dashboard
theme: cosmo
---

```{r}
#| value-boxes
library(bslib)
library(tidyverse)

quarterly_sales <- tibble(
  quarter = c("Q1", "Q2", "Q3", "Q4"),
  sales = c(125000, 142000, 138000, 165000),
  growth = c(8.2, 13.6, -2.8, 19.6)
)

total_sales <- sum(quarterly_sales$sales)
best_quarter <- quarterly_sales |>
  filter(sales == max(sales)) |>
  pull(quarter)
avg_growth <- mean(quarterly_sales$growth)

bslib::value_box(
  "Total Annual Sales",
  scales::dollar(total_sales),
  showcase = bsicons::bs_icon("currency-dollar"),
  theme = "primary"
)
```

```{r}
#| value-boxes
bslib::value_box(
  "Best Quarter",
  best_quarter,
  showcase = bsicons::bs_icon("trophy-fill"),
  theme = "success"
)
```

```{r}
#| value-boxes
bslib::value_box(
  "Average Growth",
  paste0(round(avg_growth, 1), "%"),
  showcase = bsicons::bs_icon("graph-up-arrow"),
  theme = "info"
)
```

## Sales by Quarter

```{r}
#| fig-height: 5
ggplot(quarterly_sales, aes(x = quarter, y = sales, fill = quarter)) +
  geom_col() +
  scale_fill_brewer(palette = "Blues") +
  labs(title = "Quarterly Sales", y = "Sales ($)") +
  theme_minimal() +
  theme(legend.position = "none")
```

## Growth Trends

::: panel-tabset
### Bar Chart

```{r}
#| fig-height: 4
ggplot(quarterly_sales, aes(x = quarter, y = growth, fill = growth > 0)) +
  geom_col() +
  scale_fill_manual(values = c("firebrick", "forestgreen")) +
  labs(title = "Quarter-over-Quarter Growth", y = "Growth (%)") +
  theme_minimal() +
  theme(legend.position = "none")
```

### Table

```{r}
#| echo: false
quarterly_sales |>
  mutate(
    sales = scales::dollar(sales),
    growth = paste0(growth, "%")
  ) |>
  knitr::kable()
```
:::

This example combines value boxes, a bar chart, and a tabset with both a chart and table view.

Publishing Your Dashboard

GitHub Pages

Publish to GitHub Pages by enabling it in your repository settings and committing the rendered HTML:

quarto render dashboard.qmd
git add dashboard.html
git commit -m "Update dashboard"
git push

GitHub Pages serves your dashboard at https://username.github.io/repo/dashboard.html.

Quarto Pub

Use Quarto Pub for free hosting:

quarto publish quarto-pub dashboard.qmd

Your dashboard appears at your-account.quarto.pub/dashboard.

Connect Servers

For enterprise deployment, publish to RStudio Connect or Shiny Server. These platforms handle authentication and provide monitoring:

quarto publish connect dashboard.qmd

Summary

Quarto dashboards let you create polished, interactive data presentations. The key concepts are:

  • Use format: dashboard in your YAML header
  • Arrange content with pages, sidebars, and value boxes
  • Add interactivity through Plotly, HTML widgets, or embedded Shiny apps
  • Publish via GitHub Pages, Quarto Pub, or Connect

Start with a simple layout. Add value boxes for key metrics. Then layer in charts and interactive components as needed.