Pseudo-apps in the browser with WebR and Quarto?


January 20, 2024

Meme from Super Mario Movie. Top panel is the king penguin from the start of the film labelled 'R Stats' and saying 'do you yield?' Lower panel is Bowser labelled 'the browser', laughing and saying 'I do not', except the 'not' has been censored with a black bar.


A demo post to test out embedded WebR chunks that source a non-CRAN R package. Readers can edit and re-run code later in this blog post, entirely within the browser.

World Wide WebR

WebR lets you run R code in a browser with no need for a server, thanks in large part to George Stagg’s efforts. And these days you can embed editable R chunks into Quarto documents, thanks to James Balamuta’s quarto-webr extension.

I’ve written before about how powerful this could be for demonstrating how to use code. Readers can adjust the code themselves to better understand the approach without having to install anything.

This blog has been ported to Quarto since I wrote that post, so it’s now possible for me to include WebR chunks in my posts directly.

Even better, it’s now possible to install remote, non-CRAN packages for use in WebR sessions. Thanks to James Goldie for his excellent blog post on how you can get this set up and running1. That post should be your first port of call; I’m not going to repeat all of his advice here because you should read his post in the first instance.

So much of this blog could have benefited from the inclusion of WebR chunks and I hope to use it a lot more in future. The rest of this post is a chance for me to try out the process of using WebR and installing a GitHub-hosted package.

A ‘pseudo-app’?

In some cases, WebR helps could help your blog post become a pseudo web app2. Load a package and provide some code that performs basic functionality, which readers can then fiddle with. If the package is simple enough, people may not need to install the package at all; they could just visit your blog post.

I call it a ‘pseudo’ app because of the lack of control: in a Shiny app I can force you to select certain elements from a dropdown, or only show you certain outputs. With WebR and Quarto I can only demo functions and let you adjust the arguments; if you delete all the code, that’s on you.


So here’s an example of what I mean. My {dialga} package is very focused: its goal is to make it easier to compose cron strings programmatically. Provide numeric values to its arguments, convert them to cron strings and then convert those to an English interpretation.

The package is not on CRAN, but I’ve added it to my R-universe, thanks to the amazing R-universe project by rOpenSci and particularly the mighty Jeroen Ooms3. This is crucial for sourcing the package with WebR.


Following James G’s post, I first installed James B’s WebR extension to this blog’s source by running quarto add coatless/quarto-webr in the terminal. Within this post I added filters: ["webr"] to the YAML header and specified the webr-r engine for chunks that I wanted to let users interact with.

I also added the hidden code chunk below, which installs in the background a WebR-ready version of the {dialga} package from R-universe when the page loads (as dictated by the context: setup instruction).

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

How do you know this has worked? You may have noticed when you arrived that ‘WEBR STATUS: 🟡 Loading…’ was shown at the top of the post before changing to ‘🟢 Ready!’ to indicate that the WebR chunks are ready to use.


Now let’s use the {dialga} package.

Use r2cron() to convert values into a cron string. The integer values for each argument below show the full range of possibilities, which you can adjust. The output will be * * * * *, which means ‘every minute’. Start by running the code with the ‘Run Code’ button.

Let’s say you wanted ‘every minute past hour 12’ instead. Change the hours argument to 12 and press the ‘Run Code’ button again. And so on as you please.

For completeness, you can convert the output above into English with cron2eng().

In other words… if you don’t want to install {dialga} you can just visit this page and adjust the WebR chunks!

That, or you can use one of the already-existing, excellent sites like, lol. Your call.

Regardless, I think this is a good indication of how a WebR post can help readers understand—or simply just use—your package in a demonstrative blog post.


Session info
Last rendered: 2024-01-23 11:49:58 GMT
R version 4.3.1 (2023-06-16)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.2.1

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0

[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: Europe/London
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] htmlwidgets_1.6.2 compiler_4.3.1    fastmap_1.1.1     cli_3.6.2        
 [5] tools_4.3.1       htmltools_0.5.6.1 rstudioapi_0.15.0 yaml_2.3.8       
 [9] rmarkdown_2.25    knitr_1.45        jsonlite_1.8.7    xfun_0.41        
[13] digest_0.6.33     rlang_1.1.3       evaluate_0.23    


  1. I note also that James G has clearly written some CSS on his blog to make the WebR code blocks match the theme of his blog. I haven’t done this yet at time of writing, so the chunks do a look a bit conspicuous.↩︎

  2. Although these days you can also use {shinylive} to write a Shiny app that can run entirely in the browser! I wrote about this in a previous post.↩︎

  3. There really isn’t enough space in this post to talk about the R-universe, but you can learn more on the rOpenSci site.↩︎