R-shinylive app in Quarto!

Interested in deploying a Shiny application for R within Quarto without a server? Check out:

https://github.com/coatless-quarto/r-shinylive-demo

For the demo, we’re showing the source code used in Joe Cheng’s posit::conf(2023) demo (Warning: Large file size, don’t open on mobile!) [Source Code]

Updates

  • 4/25/2025
    • We’ve switched the GitHub Pages to use GitHub Actions to deploy the website instead of commiting into the GitHub Pages branch.
    • We’ve also pinned the version of shinylive being used to v0.1.1 to ensure consistency with the quarto-ext/shinylive Quarto extension.
  • 10/26/2023
    • We’ve updated the version of shinylive being used to v0.1.0 to ensure consistency with the quarto-ext/shinylive Quarto extension.
    • Ensured that bslib was loaded for the page_sidebar() function.
  • 09/21/2023
    • Initial release of the tutorial.

Sample Application

We’ll be walking through the process of creating the following R Shinylive application. Please be aware that it may take some time to load.

#| standalone: true
#| viewerHeight: 600
library(shiny)
library(bslib)

# Define UI for app that draws a histogram ----
ui <- page_sidebar(
  sidebar = sidebar(open = "open",
    numericInput("n", "Sample count", 100),
    checkboxInput("pause", "Pause", FALSE),
  ),
  plotOutput("plot", width=1100)
)

server <- function(input, output, session) {
  data <- reactive({
    input$resample
    if (!isTRUE(input$pause)) {
      invalidateLater(1000)
    }
    rnorm(input$n)
  })
  
  output$plot <- renderPlot({
    hist(data(),
      breaks = 40,
      xlim = c(-2, 2),
      ylim = c(0, 1),
      lty = "blank",
      xlab = "value",
      freq = FALSE,
      main = ""
    )
    
    x <- seq(from = -2, to = 2, length.out = 500)
    y <- dnorm(x)
    lines(x, y, lwd=1.5)
    
    lwd <- 5
    abline(v=0, col="red", lwd=lwd, lty=2)
    abline(v=mean(data()), col="blue", lwd=lwd, lty=1)

    legend(legend = c("Normal", "Mean", "Sample mean"),
      col = c("black", "red", "blue"),
      lty = c(1, 2, 1),
      lwd = c(1, lwd, lwd),
      x = 1,
      y = 0.9
    )
  }, res=140)
}

# Create Shiny app ----
shinyApp(ui = ui, server = server)

Video Tutorial

Prefer a hands-on visual guide? Check out the following YouTube video:

Creating a Serverless Shiny App using Quarto with R Shinylive

Creating a Serverless Shiny App using Quarto with R Shinylive

We’ll go through every step and provide some commentary along the way!

Using r-shinylive for Serverless Shiny Apps in Quarto Documents

Are you interested in creating your own Quarto document with embedded static Shiny apps? This tutorial will guide you through the process of using the r-shinylive R package to achieve just that. Let’s get started!

Installation

Step 1: Install the r-shinylive R package from CRAN. It can be obtained from the R console using the following command:

install.packages("shinylive")
Note

This step differs from when the tutorial and video were written as the shinylive package was only able to be obtained from GitHub.

Setting Up Your Quarto Project

Step 2: Create a new Quarto project. Open your terminal and execute the following command:

quarto create project default

Screenshot showing the Terminal tab of RStudio with the command to create a Quarto project.

While creating the project, you’ll be prompted to specify a directory name. This name will also serve as the filename for your Quarto document. It’s crucial to note that skipping this step will result in the absence of a _quarto.yml file, leading to an error when you attempt to render the document. The error message will resemble the following:

ERROR:
The shinylive extension must be used in a Quarto project directory
(with a _quarto.yml file).

Ensure that the contents of the _quarto.yml file match the following structure:

project:
  title: "R-shinylive-demo"

Here, the title field should contain the name of the Quarto file up to the extension.

Installing the Quarto Extension for r-shinylive

Step 3: Install the Quarto extension for shinylive. In the Terminal tab, run the following command:

quarto add quarto-ext/shinylive

Screenshot showing the Terminal tab of RStudio with the Quarto Extension installation command.

Including the Shiny App in Your Quarto Document

Step 4: To include a Shiny app directly in your Quarto file (.qmd), you need to add a filter key for shinylive at the top of the desired Quarto file. Open your Quarto file and add the following YAML header:

filters:
  - shinylive

Step 5: You can insert the code for a Shiny application in a code block marked with {shinylive-r}. Below is a skeletal example of how your code block might look:

---
title: "Our first r-shinylive Quarto document!"
filters:
  - shinylive
---

```{shinylive-r}
#| standalone: true

library(shiny)

# Define your Shiny UI here
ui <- fluidPage(
  # Your UI components go here
)

# Define your Shiny server logic here
server <- function(input, output, session) {
  # Your server code goes here
}

# Create and launch the Shiny app
shinyApp(ui, server)
```

Please note that the code block must include #| standalone: true, which indicates that the code represents a complete standalone Shiny application. In the future, Quarto will hopefully support Shiny applications with parts spread throughout the document.

For an example file, you can refer to this bare-bones implementation: template-r-shinylive.qmd

With this in mind, let’s use Joe’s shiny app inside our code block. So, we’ll end up using:

```{shinylive-r}
#| standalone: true
#| viewerHeight: 600
library(shiny)
library(bslib)

# Define UI for app that draws a histogram ----
ui <- page_sidebar(
  sidebar = sidebar(open = "open",
    numericInput("n", "Sample count", 100),
    checkboxInput("pause", "Pause", FALSE),
  ),
  plotOutput("plot", width=1100)
)

server <- function(input, output, session) {
  data <- reactive({
    input$resample
    if (!isTRUE(input$pause)) {
      invalidateLater(1000)
    }
    rnorm(input$n)
  })
  
  output$plot <- renderPlot({
    hist(data(),
      breaks = 40,
      xlim = c(-2, 2),
      ylim = c(0, 1),
      lty = "blank",
      xlab = "value",
      freq = FALSE,
      main = ""
    )
    
    x <- seq(from = -2, to = 2, length.out = 500)
    y <- dnorm(x)
    lines(x, y, lwd=1.5)
    
    lwd <- 5
    abline(v=0, col="red", lwd=lwd, lty=2)
    abline(v=mean(data()), col="blue", lwd=lwd, lty=1)

    legend(legend = c("Normal", "Mean", "Sample mean"),
      col = c("black", "red", "blue"),
      lty = c(1, 2, 1),
      lwd = c(1, lwd, lwd),
      x = 1,
      y = 0.9
    )
  }, res=140)
}

# Create Shiny app ----
shinyApp(ui = ui, server = server)
```

You can view a standalone version of Joe’s app here: R-shinylive-demo.qmd

Rendering Your Quarto Document

Step 6: Once you are satisfied with your Shiny app and content, render the document by pressing the Render button in RStudio.

Press the render button in RStudio

Or type in the Terminal tab:

quarto preview R-shinylive-demo.qmd --no-browser --no-watch-inputs

Folder Structure

During the render process, the output directory should contain the following structure:

.
├── _extensions
   └── quarto-ext/shinylive # Added by 'quarto add'
├── _quarto.yml              # Created by 'quarto create'
├── R-shinylive-demo.html    # Rendered Document
├── R-shinylive-demo.qmd     # Quarto Document with Shiny App
├── R-shinylive-demo_files   # Supporting files
└── shinylive-sw.js          # Service Worker

Publishing Your Quarto Document

Step 7: Once you are satisfied with your shinylive app and Quarto document, it’s time to publish your work. There are multiple options for publishing with Quarto, and we’ll present two of them. Choose the option that best suits your needs for sharing and distributing your Quarto document with your embedded shinylive app.

Option 1: Publish to GitHub Pages

To make your Quarto document accessible on GitHub Pages via Quarto, use the following command in your terminal:

quarto publish gh-pages

This option is great if you want to share your document through a GitHub Pages website.

Option 2: Publish to Quarto Pub

Alternatively, you can publish your Quarto document on Quarto Pub via Quarto. Use the following command in your terminal:

quarto publish quarto-pub

This option provides you with a shareable link for easy access by others and is a good choice if you prefer a dedicated platform for your documents.

A Quick Fix for Service Worker Inclusion

If you’ve encountered issues with the quarto publish command not including the required service worker JavaScript file, you can quickly resolve this by adding the following lines under the html key in your document header:

format:
  html:
    resources: 
      - shinylive-sw.js

This addition ensures that the necessary service worker JavaScript file (shinylive-sw.js) is included when you publish your Quarto document. The Quarto team is aware of the issue regarding service workers not being uploaded automatically from extensions.

If you encounter this issue, you may see an error message in your browser’s JavaScript console that looks like:

Uncaught Error: ServiceWorker controller was not found!
The above error occurred in the <Viewer> component:

By implementing this quick fix, you can prevent this error and ensure the proper functioning of your shinylive app within your Quarto document.

Advanced (Optional Step): Continuous Publishing Using GitHub Actions

For advanced users, you can set up continuous integration (CI) to automatically update your application whenever changes are committed to the Quarto document. This process involves creating a workflow for GitHub Actions and utilizing actions from r-lib/actions (for R installation) and quarto-dev/quarto-actions (for Quarto setup and publishing).

Follow these steps to configure continuous publishing:

Step 1: Create a .github/ folder in your repository if it doesn’t already exist. Place the workflows/ folder inside it. Then, create a workflow configuration file called publish-website.yml with the following content:

on:
  push:
    branches: [main, master]
  release:
      types: [published]
  workflow_dispatch: {}

name: demo-website

jobs:
  demo-website:
    runs-on: ubuntu-latest
    # Only restrict concurrency for non-PR jobs
    concurrency:
      group: quarto-website-${{ github.event_name != 'pull_request' || github.run_id }}
    permissions:
      contents: read
      pages: write
      id-token: write
    steps:
      - name: "Check out repository"
        uses: actions/checkout@v4

      # To render using knitr, we need a few more setup steps...
      # If we didn't want the examples to use `engine: knitr`, we could
      # skip a few of the setup steps.
      - name: "Setup pandoc"
        uses: r-lib/actions/setup-pandoc@v2

      - name: "Setup R"
        uses: r-lib/actions/setup-r@v2

      - name: "Setup R dependencies for Quarto's knitr engine"
        uses: r-lib/actions/setup-r-dependencies@v2
        with:
          packages:
            cran::shinylive@0.1.1 ## Pin version to ensure consistency
            any::knitr
            any::rmarkdown
            any::downlit
            any::xml2

      # Back to our regularly scheduled Quarto output
      - name: "Set up Quarto"
        uses: quarto-dev/quarto-actions/setup@v2

      # Render the Quarto file
      - name: "Render working directory"
        uses: quarto-dev/quarto-actions/render@v2

      # Upload a tar file that will work with GitHub Pages
      # Make sure to set a retention day to avoid running into a cap
      # This artifact shouldn't be required after deployment onto pages was a success.
      - name: Upload Pages artifact
        uses: actions/upload-pages-artifact@v2
        with: 
          retention-days: 1
      
      # Use an Action deploy to push the artifact onto GitHub Pages
      # This requires the `Action` tab being structured to allow for deployment
      # instead of using `docs/` or the `gh-pages` branch of the repository
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v2
Note

We have pinned the version of shinylive package on CRAN to v0.1.1 to ensure consistency with the quarto-ext/shinylive Quarto extension.

Step 2: Enable GitHub Pages deployment using GitHub Actions in your repository by going to the repository’s Settings tab, selecting Pages, and then under the build and deployment section set scource to GitHub Actions. Please make sure to also check the Enforce HTTPS option.

Enabling GitHub Pages deployment through GitHub Actions

By implementing this advanced setup, your Quarto document with the embedded shinylive app will automatically update whenever changes are pushed to the specified branches or when a release is published. This ensures that your audience always has access to the latest version of your interactive document.

Fin

Now you have successfully integrated static Shiny apps into your Quarto documents using the r-shinylive package. Happy Quarto + r-shinyliving!

References