1 Introduction
Everything you’ve done so far using R – your wrangled data and visualizations – lives on your laptop. This session changes that: we’ll take the analysis you built in the previous lesson and publish it as a live, interactive website anyone can visit by URL.
Quarto’s HTML output format unlocks capabilities that static formats (PDF, Word) can’t match:
- Interactive plots you can zoom, hover, and filter (you already made one with
ggplotly) - Sortable, searchable tables that let readers explore data directly in the browser
- Interactive maps readers can pan, zoom, and click
These elements are powered by JavaScript libraries (plotly.js, DataTables, and Leaflet.js) that R packages ggplotly(), DT, and leaflet make it easy for you to use in R. They work because web browsers run JavaScript; HTML is the right output format when you want to share interactive analyses.
Here is an example of a published data analysis site built with these same tools. Notice the interactive maps, the clean landing page, and how individual analyses are linked from it. That is the structure we will build today.
2 Set Up GitHub Pages
Make sure you are in your
training_{USERNAME}projectCreate a new Quarto document called
index.qmdat the top level of your project- File → New File → Quarto Document
- Set the title (e.g.,
"Delta Socioecological Monitoring"), keep Default Output Format as HTML, click OK - If your IDE added default template content below the YAML header, delete it
- Add a brief description and a placeholder for your analyses:
Welcome to my Delta socioecological monitoring analysis. ## Course Analyses - Data Visualization (link coming soon)Save as
index.qmd. Be sure to use this exact name, all lowercase. Web servers returnindex.htmlby default when no specific file is requested, so this name matters.Render
index.qmdand observe the newindex.htmlin the same directoryCommit both
index.qmdandindex.htmlwith a descriptive message, and push to GitHub- If an
index_files/folder appears, commit it too – it holds supporting files for the HTML
- If an
In your browser, go to your GitHub repo → Settings → Pages
- Keep Source as “Deploy from a branch”
- Change Branch from “None” to
main, keep folder as/ (root), click Save - The message changes to “Your GitHub Pages site is currently being built from the
mainbranch”
GitHub Pages follows a URL convention based on your username and repository name:

Note that it changes from github.com to github.io.
- Visit
https://{username}.github.io/{repo_name}/(note the trailing/) - It may take a minute or two on first setup; refresh if you get a 404 error
Now make a small edit to confirm the full publish cycle works:
- Add the text “Under construction” somewhere in
index.qmd - Render
index.qmd - Git workflow: Stage → Commit → Pull → Push
- Wait ~1 minute, then revisit
https://{username}.github.io/{repo_name}/and confirm the change appears
3 Link Your Content Page
Now let’s connect your landing page to the visualization analysis you built in the previous session.
When linking between pages in your site, use a relative path from the linking file to the target file. Your index.qmd is at the repo root, and your visualization notebook is in a notebooks/ subfolder, so the correct link looks like this:
[Data Visualization](notebooks/data-visualization.html)Common mistakes and what goes wrong:
| Path | Problem |
|---|---|
notebooks/data-visualization.html |
✓ correct |
data-visualization.html |
✗ missing subfolder → 404 |
notebooks/Data-Visualization.html |
✗ wrong case → 404 on case-sensitive servers |
notebooks/data-visualization.qmd |
✗ links to source, not rendered output |
A 404 error (“Not Found”) means the browser cannot find the file at the path you gave it. Getting the path exactly right is one of the most common publishing stumbling blocks.
4 Add Interactive Elements
Quarto’s HTML output format supports interactive elements powered by JavaScript, such as tables that users can sort and search, and maps they can pan and zoom. We’ll add two of these to notebooks/data-visualization.qmd: a searchable table using DT and an interactive map using leaflet.
Open notebooks/data-visualization.qmd and add the following to your setup chunk and then at the end of the document.
4.1 Setup
Add these packages to your setup chunk (or create one at the top of the document if you don’t have one yet):
```{r}
#| message: false
#| warning: false
library(readr)
library(here)
library(dplyr)
library(tidyr)
library(janitor)
library(DT)
library(leaflet)
```The examples below use a daily_visits_loc data frame derived from the Delta socioecological monitoring dataset. Add this code after your setup chunk if you don’t already have it:
```{r}
delta_visits_raw <- read_csv(here("data/Socioecological_monitoring_data.csv"),
show_col_types = FALSE)
daily_visits_loc <- delta_visits_raw %>%
janitor::clean_names() %>%
tidyr::pivot_longer(
cols = c(sm_boat, med_boat, lrg_boat, bank_angler, scientist, cars),
names_to = "visitor_type",
values_to = "quantity"
) %>%
dplyr::rename(restore_loc = eco_restore_approximate_location) %>%
dplyr::select(-notes) %>%
dplyr::group_by(restore_loc, date, visitor_type) %>%
dplyr::summarize(daily_visits = sum(quantity), .groups = "drop")
```4.2 Interactive Table with DT
DT is an R package that wraps the DataTables JavaScript library, producing tables that readers can sort, search, and page through directly in the browser.
Add a new section:
## Interactive Table
```{r}
DT::datatable(
daily_visits_loc,
caption = "Daily visitor counts at Delta restoration sites",
colnames = c("Location", "Date", "Visitor type", "Daily visits"),
options = list(pageLength = 10)
)
```Render the document and try sorting by column, searching for a specific location or visitor type, and paging through results.
datatable() options
The options list accepts standard DataTables options. A few worth knowing:
pageLength: default number of rows showndom: controls which UI controls appear (search box, pagination, info, etc.)columnDefs: per-column formatting (width, sorting, visibility)
See ?DT::datatable or the DT documentation for the full reference.
4.3 Interactive Map with leaflet
leaflet wraps the Leaflet.js JavaScript library for interactive maps. Its syntax is similar to ggplot2 in that you build up a map by adding layers, but it uses the pipe operator %>% rather than +.
We can pull the unique restoration site locations directly from the data we already loaded. Add this to your document:
## Interactive Map
```{r}
restoration_sites <- delta_visits_raw %>%
janitor::clean_names() %>%
distinct(restore_loc = eco_restore_approximate_location,
latitude, longitude) %>%
drop_na(latitude, longitude)
leaflet(restoration_sites) %>%
addTiles() %>%
addMarkers(
lng = ~longitude,
lat = ~latitude,
popup = ~restore_loc
)
```Render the document, then pan the map, zoom in, and click a marker to see the popup.
For more control over marker appearance, use addCircleMarkers() instead of addMarkers():
leaflet(restoration_sites) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitude,
lat = ~latitude,
popup = ~restore_loc,
radius = 8,
fillColor = "steelblue",
fillOpacity = 0.8,
stroke = FALSE
)As an extension exercise, try joining restoration_sites with total visit counts from daily_visits_loc and mapping fillColor to visit volume.
6 What’s Next
In this module, we published individual HTML pages linked from a landing page. A natural next step might be a proper Quarto website. This is a multi-page site where navigation, themes, and shared settings are configured in a single _quarto.yml file, giving you a consistent navigation bar across all pages.
For truly dynamic content that responds to user input in real time (e.g., filtering data on the fly, running models), look into Shiny, an R framework for building interactive web applications backed by a live R session.
If you want to share a single HTML file that works without a web server (e.g., via email), add this to your YAML header:
format:
html:
embed-resources: trueThis bundles all JavaScript, CSS, and images into the HTML file itself. The trade-off is a larger file size; for sharing via URL, omitting embed-resources: true produces smaller, faster-loading pages.
7 Resources
- Quarto Websites - documentation for building multi-page sites with shared navigation and
_quarto.yml - GitHub Pages documentation - details about custom domains, build workflows, and more
- DT package documentation - a full reference for interactive table options
- Leaflet for R - a comprehensive guide including polygons, WMS tiles, and color scales