Your new R package? Write a WebR blog post for it

If you can write a blog post, you can let people try your R package out, right in the browser.

January 19, 2024

Your R package is ready to go out into the world? That’s great news!

You’re probably thinking about writing a blog post to celebrate the release, to tell everyone how your package works and what they can do with it.

But what if people could try your package out, right there inside the blog post, without installing anything? Not just running the examples that you give them, but modifying them and playing with them?

If you have a Quarto blog, you can do this right now, thanks to the power of WebR.

In fact, why don’t you give one of my old packages a test run?

Try it out

The package is called {collateral}. It’s designed to help you catch errors and warnings when you’re working on large, grouped datasets.

To demonstrate, I’ve taken the famous mtcars data set and sabotaged a few of the rows so that they have a negative wt column.

Take a look the new dataset by clicking the Run button below:

At first glance, it doesn’t look too different from the first few rows.

Try tapping on that textbox and changing the code to bad_mtcars |> summary().

Now you can see that I’ve tampered with the wt column, making some of its values negative.

These boxes aren’t just displaying code — you can run any R code directly in your browser!

{collateral} lets you run an operation — building a plot, fitting a model, or something more complex — on many groups of data, while identifying any errors or warnings that crop up.

It’s good for people who aren’t ready to step up to a full data pipeline framework like {targets} but who find themselves running the same code over and over, solving edge cases in order to get any results at all.

It’s also the sort of package that is best demoed, rather than described. But it’s always an uphill push to get someone to install a package locally — a lot of people will just close the blog post and forget the package altogether.

Two great technologies have come together to let you, or anybody, take an R package for a spin directly in the browser: R-Universe and WebR.

R code in the browser

This blog post uses WebR to run a copy of R directly in your browser as you read it.

If you’ve used frameworks like Shiny before, you know that it requires a copy of R to be constantly running, or at least waiting to run, 24/7 in the cloud somewhere.

Whenever someone flicks a switch, or drags a slider, their browser sends a request off to the cloud to request that a new graphic be made or model be fitted. Keeping that copy of R running all the time isn’t always cheap!

WebR does away with all that. The browser, whether it’s on Windows or Mac, downloads a copy of R that is safely sandboxed away from the rest of the computer, and the page interacts with that.

WebR can power a whole range of experiences, whether it’s a full R-Studio development environment in your browser or something more restrained. But it’s also designed for web developers.

James Balamuta (@coatless) has been working on opening WebR up to regular Quarto users. quarto-webr is the Quarto extension you see above: instead of running R code when an author renders the page and having the results baked in for all users, the code can be run at any time — or even modified — by the reader.

The biggest constraint on WebR initially was that you only had the base R packages. Then the WebR developers set up a version of CRAN exclusively for WebR, so you can install most CRAN packages either by adding them to the post frontmatter or by running webr::install().1

But if your package isn’t on CRAN, how can you demo it?

R-Universe to the rescue

R-Universe is a less onerous alternative to CRAN. It lets anybody build their own R packages in the cloud, and it does it automatically. It now builds versions of your packages that work with WebR, so any R-Universe package can be run with quarto-webr.

These kinds of services that built your code automatically intimidated me for a long time. But R-Universe makes it incredibly simple: you connect the R-Universe app to your GitHub, and it creates a place where you can list the R packages you want built (like this one for me). They can be your packages, or they can be someone else’s (like members of a lab group or team, or dependencies that you rely on).

R-Universe takes care of building the packages any time they receives pushes on GitHub. You just worry about building the R package.


Using quarto-webr is a pretty seamless process:

  1. Install the extension alongside your blog post by running quarto add coatless/quarto-webr
  2. Add the extension to your blog by adding filters: ["webr"] to your post’s frontmatter
  3. Instead of {r} code chunks, use {webr-r} ones

If you want to have CRAN packages installed when someone opens the page, the fourth step is to add a webr key to your frontmatter, with a list of packages below it:

  - "webr"
  - "dplyr"
  - "tidyr"
  - "purrr"
  - "tibble"
  - "crayon"

If you want to install an R-Universe package, you need to use a code chunk to do so:

#| context: setup
webr::install("collateral", repos = c(""))

There’s a really important property on that code chunk: context: setup. If you add this to a WebR code chunk, it’ll run automatically when the page opens, without the user doing anything.

This doesn’t just have to be for package installation. For example, I used it above to create bad_mtcars, since I didn’t want to slow the blog post down with the details of making some sample data.

If you install an R-Universe package, you currently have to install its dependencies manually. For example, I added crayon, a dependency of collateral, to my frontmatter under webr.packages.


quarto-webr isn’t an entirely free lunch, although it gets pretty close. A few things to keep in mind:

  1. Your readers have to wait while R and the packages download when they first open the page. WebR itself is about a 5 MB download — about as big as a photo from a modern phone. Other packages might be a few hundred kB apiece on top of that. Which means that…

  2. Your users will need to wait several seconds for R and the packages to install. That might be acceptable in a lot of cases, particularly if you can give them something to look at (like a blog post introduction!) in the mean time. In other contexts, it might be unacceptable.

  3. Including private data in your WebR blog post will expose it to users. An advantage of frameworks like Shiny is that the analysis happens in the cloud, and your users only get the graphic or summary at the end, without seeing, say, individual medical data.

But there are lot of upsides too! You can get early feedback on a new package, without the hassle of waiting for CRAN submission (you can even set up R-Universe to build from a development branch). You can invite people to experiment with your package, rather than try a single example.

You can even suggest several options for people to run, using Quarto’s tabsets:

There are a lot of possibilities here for teaching. No worrying about one reader getting an error that you can’t reproduce: the WebR environment is the same for everybody. And you still have all the power of the web to make a very tailored learning experience.

This post’s example with {collateral} just has text output, but yes, quarto-webr can do plots too! Here’s a basic example with base R plotting, but you can install ggplot2 and any of your usual extensions through CRAN or R-Universe, of course!

It’s is also a great way to expose open data and encourage people to experiment with it!

I think quarto-webr is going to be pretty rad. The next time you publish an R package, try it out—or write a post to reintroduce people to your old packages!


  1. Soon, it’ll be even easier: you’ll just be able to use install.packages() as usual!↩︎