# pkgdown: turning an R package into a documentation website

> pkgdown is the r-lib tool that builds a static site from an R package, so README becomes the homepage, man pages become a function reference and vignettes become articles. It is a good fit for package authors who want real documentation pages without hand-writing HTML.

**r-lib/pkgdown** — Generate static html documentation for an R package

- Repository: https://github.com/r-lib/pkgdown
- Website: https://pkgdown.r-lib.org/
- Stars: 777 · Forks: 360
- Language: R
- License: NOASSERTION
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/r-lib-pkgdown

## What pkgdown generates from a package

pkgdown takes an R package as its input and produces a static HTML website. The README describes the mapping directly: your `README.md` becomes the homepage, documentation in `man/` generates a function reference, and vignettes are rendered into `articles/`. There is no separate content to write and no server to run. The output is a directory of files that any static host can serve.

The project dogfoods itself. The pkgdown site at pkgdown.r-lib.org is described as the output of pkgdown applied to the latest version of pkgdown, which is the shortest possible demonstration of what the tool produces and of the standard it aims for.

The target audience is package maintainers rather than application developers. The README points to the `vignette("pkgdown")` guide and the `?build_site` help topic for the details, and it frames the goal as making it quick and easy to build a website for your package. Anyone who ships an R package on CRAN or GitHub and has ever wished their `?function` pages were readable by someone who has not opened R yet is in scope.

## Installing pkgdown from CRAN or from GitHub

The README gives two installation paths. The released version comes from CRAN.

```bash
install.packages("pkgdown")
```

The development version comes from GitHub through pak, which is itself installed as a package.

```bash
pak::pak("r-lib/pkgdown")
```

Neither path changes how the tool is used. The rest of the workflow is identical, so the choice is only about which version you want to pin: the CRAN build is the one most users should take, while the GitHub build tracks the main branch, where work is in progress between releases.

Version numbers move fairly often. Releases include pkgdown 2.2.1 on 2026-07-07, pkgdown 2.2.0 on 2025-11-06 and pkgdown 2.1.3 on 2025-05-18, and the repository's last push was on 2026-08-12. A site built on a two year old install will not match what current maintainers see, which is worth considering if you are copying a _pkgdown.yml from someone else.

## Setting up a package with usethis and deploying the site

The README routes new users through usethis, and the setup step is a single call that both configures the package and wires up deployment.

```bash
usethis::use_pkgdown_github_pages()
```

The README states that this adds the necessary components and sets up GitHub Actions for automatic site building when deploying. The GitHub Actions part matters more than it first appears, since it is what turns a local build into a site that updates itself on every push.

Before publishing, the site is previewed locally with a direct call to the builder.

```bash
pkgdown::build_site()
```

Running that on your own checkout produces the same static output the deployment will publish, so it is the fastest way to see what a broken reference index or a missing vignette looks like before it goes live. A build you have not previewed locally tends to produce broken links that only surface after the workflow has pushed the files.

If GitHub is not part of your setup, the README points to the alternative: `usethis::use_pkgdown()` combined with `pkgdown::build_site()` creates a website without the GitHub Pages deployment.

## The Bootstrap 5 opt-in and what it breaks

pkgdown 2.0.0 upgraded the site templates from Bootstrap 3 to Bootstrap 5, and the README is unusually direct about the risk: if you have heavily customised your site, there is a small chance the upgrade will break it. Because the framework changed underneath, the upgrade is not automatic. Everyone has to opt in by adding a template block to `_pkgdown.yml`.

```yaml
template:
  bootstrap: 5
```

The opt-in is a deliberate design decision rather than an oversight. It gives maintainers with heavily customised sites a chance to update their custom CSS against a known-good baseline, and it keeps the default behaviour stable for everyone else who did not touch their theme. The cost is a config file that must be edited and a documentation site that is running a different framework depending on when the maintainer got around to it.

The README then points to `vignette("customise")` for the many ways to change a site, and the top level of the repository includes a `pkgdown/` directory, a `po/` directory for translations and a `vignettes/` directory, which is where those guides live.

## Configuration file and the site layout you have to own

The `_pkgdown.yml` file is the control surface. It is where the template choice, the navbar, the reference index grouping and the articles listing are declared, and it is what turns a generic build into a site specific to one package. The presence of `_pkgdown.yml` in a package is also how the project is found: the README notes that pkgdown is used by over 12,000 packages, with the count taken from a GitHub code search for that file path.

That reference index is the part that most often needs attention. A package with 200 exported functions produces a reference page that is technically complete and practically useless unless the functions are grouped by topic, and grouping is declared in the config file rather than inferred. The same applies to the navbar, which decides what a reader sees first.

The README suggests a practical way to learn the layout conventions: look at the source of established sites and compare it with the output. The examples it names are bayesplot for posterior analysis plots, valr for genome intervals and signals, mkin for FOCUS kinetics calculations, and NMF for non-negative matrix factorization, and the tidyverse and r-lib packages are pointed at as a group. Copying an existing _pkgdown.yml is a legitimate way to start, as long as you understand which parts are structural and which are site specific.

## Where pkgdown is the wrong tool

Several cases are worth naming.

A package with no exported functions, or one consumed only inside a single organisation, gains little. The output is static HTML with a navbar and a reference index, and a static site for an internal library nobody outside the team will visit is overhead without a payoff.

Heavy customisation is the second trap. A site that has been restyled past the point where the templates can be recognised is expensive to maintain, because every pkgdown upgrade then becomes a CSS and YAML exercise rather than a version bump. The Bootstrap 3 to 5 episode is the documented precedent for that cost.

There is also a licensing and hosting asymmetry to keep in mind. GitHub lists the repository licence as one it cannot classify, with LICENSE and LICENSE.md files at the root, and the site itself depends on GitHub Pages for the automatic deployment path. A team that cannot or will not host on GitHub Pages has to arrange hosting and run the build itself, which the README supports through the usethis::use_pkgdown() route but does not automate.

## Maintenance, release cadence and the cost of keeping a site alive

The project is not archived and its last push was on 2026-08-12, so the tool itself is being worked on. Three releases are visible in the range from 2025-05-18 to 2026-07-07, roughly one every few months, which is a pace that lets maintainers pick up framework changes without waiting long.

The cost of keeping a pkgdown site alive sits mostly in the config file and in the reference index. When a package gains or renames functions, the grouping declared in `_pkgdown.yml` has to follow, otherwise the reference page accumulates orphans and the navbar points at topics that no longer exist. A second cost is the rendering of vignettes, which pulls in whatever the vignette needs to build cleanly.

The repository itself gives a good picture of what a mature R package looks like: DESCRIPTION, NAMESPACE, NEWS.md, R/, man/, tests/, vignettes/, a revdep/ directory for reverse dependency checks, a cran-comments.md file, an AGENTS.md file, and a .github/ directory with an R-CMD-check workflow. The presence of tests/ and of reverse dependency checking is the practical reason to expect upgrades not to break your site quietly.

## Conclusion

pkgdown suits maintainers of R packages who want a browsable site, a searchable function reference and vignettes rendered as articles, and who are prepared to keep a _pkgdown.yml file honest. It is a poor fit for a private internal package that never leaves a team, since the extra configuration buys nothing there. Before adopting it, run pkgdown::build_site() on your own package and check the reference index and the navbar, because those are the parts that need hand-tuning.

## FAQ

### How do I install pkgdown?

The released version installs from CRAN with install.packages("pkgdown"), and the development version comes from GitHub with pak::pak("r-lib/pkgdown") after installing pak. The README lists pkgdown 2.2.1 as the most recent release, dated 2026-07-07.

### How do I set up a pkgdown site for my R package?

Run usethis::use_pkgdown_github_pages() once, which adds the necessary components and sets up GitHub Actions for automatic site building, then preview locally with pkgdown::build_site(). If you do not use GitHub, the README suggests usethis::use_pkgdown() with pkgdown::build_site() instead.

### What changed in pkgdown 2.0.0?

pkgdown 2.0.0 moved the site templates from Bootstrap 3 to Bootstrap 5, along with a set of minor UI improvements. The upgrade is opt-in, so you have to add a template block with bootstrap: 5 to _pkgdown.yml, and the README warns that heavily customised sites may need fixing.

### Where does pkgdown put my README, function documentation and vignettes?

Your README.md becomes the homepage, documentation in man/ generates the function reference, and vignettes are rendered into articles/. The rest of the layout, including the reference index groups and the navbar, is controlled by the _pkgdown.yml file in your package.

## Sources

- [Issues](https://github.com/r-lib/pkgdown/issues)
- [Project website](https://pkgdown.r-lib.org/)
- [README](https://github.com/r-lib/pkgdown/blob/main/README.md)
- [Releases](https://github.com/r-lib/pkgdown/releases)
- [r-lib/pkgdown on GitHub](https://github.com/r-lib/pkgdown)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/r-lib-pkgdown
