Package Documentation Sites with pkgdown
Introduction
When you publish an R package on CRAN, users need a way to explore your functions, understand how to use them, and learn about new features. pkgdown solves this by generating a beautiful, static HTML package documentation site from your existing R documentation files. It reads your roxygen2 comments, vignettes, and NEWS file and turns them into a searchable, linked website that makes your package accessible to users who may never open an R console.
This guide walks you through setting up pkgdown, configuring your site, and deploying it automatically with GitHub Pages. By the end, you’ll have a professional documentation site hosted and automatically updated whenever you push changes to your package.
Installation and initial setup
First, install pkgdown from CRAN:
install.packages("pkgdown")
# Loading the package
library(pkgdown)
Once pkgdown is installed, run use_pkgdown() from your package directory. This usethis function scaffolds the configuration file, creates a GitHub Actions workflow for continuous deployment, and updates your DESCRIPTION with the repository URL — everything you need to start building professional documentation:
usethis::use_pkgdown()
This command does several important things: it creates a _pkgdown.yml configuration file in your package root, adds a GitHub Actions workflow for automated builds, and updates your package’s DESCRIPTION with the repository URL. After running this command, you’ll have a working site structure ready to build. The workflow file will handle building and deploying your site automatically whenever you push to your repository.
Building your site
The core function is build_site():
pkgdown::build_site()
# Building site in: docs/
This reads your package’s documentation and generates HTML files in the docs/ directory. The site includes several sections automatically, pulling content from different parts of your package. The home page is built from your README.md or index.md, the reference section is generated from all .Rd files in man/, articles are compiled from vignettes/, and the news section is rendered from NEWS.md. Each section has its own dedicated builder function so you can iterate on one part of the documentation without rebuilding everything.
During development, building individual sections saves time. This is particularly useful when you are iterating on reference documentation or article content and do not need to rebuild the entire site on every change:
pkgdown::build_home() # Just the home page
pkgdown::build_reference() # Just the reference section
pkgdown::build_articles() # Just the vignettes
Configuring your site
The _pkgdown.yml file controls your site’s appearance and organization. Every aspect of the site is configured through this single YAML file. The most important setting is the URL, which enables proper linking throughout your site and improves search engine indexing with canonical URLs on every page:
url: https://yourusername.github.io/packagename
You can customize the Bootstrap theme to match your package’s branding. Choose from built-in Bootswatch themes like cerulean, flatly, or darkly, or define custom colors with the bslib package for a unique look that distinguishes your package documentation from the default appearance:
template:
bootstrap: 5
bootswatch: cerulean
Organize the reference section by grouping related functions together, which makes it much easier for users to find what they need. Without explicit grouping, pkgdown lists all exported functions alphabetically, which works for small packages but becomes unwieldy for packages with dozens of functions spread across unrelated categories. The desc field under each group title explains what the group of functions does in one sentence:
reference:
- title: "Data Import"
desc: "Functions for reading data into R"
contents:
- read_csv
- read_excel
- read_fst
- title: "Data Export"
contents:
- starts_with("write_")
The starts_with(), ends_with(), and matches() helper functions let you include multiple functions at once based on naming patterns, so you do not need to list every function individually. Once your reference sections are organized and your site builds correctly locally, you are ready to deploy it for others to see.
Publishing with GitHub pages
The easiest deployment method is GitHub Pages. Run this command once to set up automatic deployments that build and publish your site on every push:
usethis::use_pkgdown_github_pages()
This sets up a GitHub Actions workflow that automatically builds and deploys your site whenever you push to main. Under the hood, the workflow runs pkgdown::build_site() and pushes the output to the gh-pages branch, where GitHub Pages serves it. This means every time you push an update to your package, your documentation updates automatically.
After setup, your site will be available at https://yourusername.github.io/packagename/. Update your DESCRIPTION file to include the URL so users can find it:
URL: https://yourusername.github.io/packagename, https://github.com/yourusername/packagename
A well-maintained NEWS.md file shows in your pkgdown site as the changelog. Use level-1 headings for version numbers and level-2 headings for feature categories to create a clean, scannable history that users can browse. CRAN requires NEWS.md for all submitted packages, so keeping it current serves both documentation and submission requirements:
## New Features
- Added `read_json()` function for reading JSON files
- Added support for parquet format in `write_data()`
## Bug Fixes
- Fixed error in `write_csv()` when handling NA values
- Fixed timeout issue in `download_data()`
Common issues
If links aren’t working, make sure you’ve configured the url field in _pkgdown.yml. Without it, pkgdown generates relative links that only work when viewing the site locally but break when deployed.
Examples that fail during build_site() will stop the entire build. Use \dontrun{} for examples that require external resources, or \donttest{} for examples that take too long to run.
If your site looks wrong after an update, try running pkgdown::build_site() twice; the first build sometimes has caching issues that clear up on subsequent builds.
What makes a good pkgdown site
A well-organized pkgdown site does more than list functions alphabetically. Group related functions into reference sections with descriptive titles so users can browse by task rather than by name. Write at least one vignette that walks through a realistic workflow using multiple functions together; this shows users how the pieces fit together in practice. Keep your README focused on installation and a quick example, saving deep tutorials for vignettes where you have room to explain.
The navbar should prioritize the sections users need most. For most packages, this means Reference, Articles, and News. If your package has a website or a paper associated with it, add those links to the navbar as well. Every exported function should have a working example in its roxygen2 documentation that demonstrates typical usage in one or two lines of code. Examples that fail during build_site() stop the entire build, so wrap examples that need external resources in \dontrun{} or use \donttest{} for slow examples. A consistent site helps users learn your package faster and reduces the support burden of answering questions already covered in the documentation.
See also
- Building R Packages from Scratch: learn package structure before documenting it
- Writing R Packages with devtools: roxygen2 documentation and package workflows
- Simple R Package Guide: a minimal package example to practice pkgdown on