Using Shiny with Quarto for Interactivity

Embed Interactive Shiny Applications in Your Quarto Documents

Learn how to embed interactive Shiny applications directly into your Quarto documents. This tutorial covers setting up the Shinylive extension, creating a standalone Shiny app, and customizing viewer options.

Tools
Author
Affiliation
Published

March 8, 2025

Keywords

Shiny integration, interactive R Shiny, Quarto Shiny article

Introduction

Interactive Shiny applications can now be embedded directly into your Quarto documents—allowing you to combine narrative text with live, reactive apps that run entirely in the browser. With the Shinylive Quarto extension and standard Shiny components, you can build, display, and interact with Shiny apps without needing a dedicated server. This tutorial provides a detailed walkthrough on how to embed a Shiny app, customize its appearance, and troubleshoot common issues.



1. Prerequisites

Before you start, ensure you have the following:

  • Quarto Installed: Download and install Quarto from quarto.org.

  • Shinylive Quarto Extension: Add the Shinylive extension to your project by running:

    quarto add quarto-ext/shinylive
  • Configure Filters: In your document’s YAML (or your _quarto.yml), include the Shinylive filter:

    filters:
      - shinylive
  • Shiny and bslib: Make sure the shiny and bslib packages are installed in R.

2. Creating a Basic Embedded Shiny App

Below is an example of a simple Shiny application embedded directly in a Quarto document using a {shinylive-r} code block. This app displays a histogram of the mtcars dataset with an interactive slider to adjust the number of bins.

Step-by-Step Walkthrough

  1. Define the UI:
    Use page_sidebar() to create a layout with a sidebar for inputs and a main panel for outputs.

  2. Create Inputs:
    Include a sliderInput() in the sidebar for selecting the number of bins for the histogram.

  3. Display Output:
    Use plotOutput() in the main panel to show the histogram.

  4. Define Server Logic:
    In the server function, use renderPlot() to compute the histogram based on the slider input.

  5. Run the App:
    Wrap the UI and server definitions in a call to shinyApp().

Basic Embedded R Shiny App Example

Source
```{shinylive-r}
#| standalone: true
#| viewerHeight: 650

library(shiny)
library(bslib)

ui <- page_sidebar(
  title = "Hello Shiny in Quarto",
  sidebar = sidebar(
    sliderInput("bins", "Number of bins:", min = 5, max = 30, value = 10)
  ),
  plotOutput("distPlot")
)

server <- function(input, output) {
  output$distPlot <- renderPlot({
    x <- mtcars$mpg
    bins <- seq(min(x), max(x), length.out = input$bins + 1)
    hist(x, breaks = bins, col = "skyblue", border = "white",
         main = "Histogram of MPG", xlab = "Miles Per Gallon")
  })
}

shinyApp(ui = ui, server = server)
```
Note
  • The #| standalone: true option indicates that this code block represents a complete Shiny application.
  • The #| viewerHeight: 420 option sets the height of the application viewer.
#| '!! shinylive warning !!': |
#|   shinylive does not work in self-contained HTML documents.
#|   Please set `embed-resources: false` in your metadata.
#| standalone: true
#| viewerHeight: 650

library(shiny)
library(bslib)

ui <- page_sidebar(
  title = "Hello Shiny in Quarto",
  sidebar = sidebar(
    sliderInput("bins", "Number of bins:", min = 5, max = 30, value = 10)
  ),
  plotOutput("distPlot")
)

server <- function(input, output) {
  output$distPlot <- renderPlot({
    x <- mtcars$mpg
    bins <- seq(min(x), max(x), length.out = input$bins + 1)
    hist(x, breaks = bins, col = "skyblue", border = "white",
         main = "Histogram of MPG", xlab = "Miles Per Gallon")
  })
}

shinyApp(ui = ui, server = server)

Customizing the Embedded Shiny Experience

If you’d like to display the code editor along with the running Shiny app (allowing users to modify and re-run the application), you can include additional components:

Source
```{shinylive-r}
#| standalone: true
#| components: [editor, viewer]
#| viewerHeight: 650

library(shiny)
library(bslib)

ui <- page_sidebar(
  title = "Editable Shiny App in Quarto",
  sidebar = sidebar(
    sliderInput("bins", "Number of bins:", min = 5, max = 30, value = 10)
  ),
  plotOutput("distPlot")
)

server <- function(input, output) {
  output$distPlot <- renderPlot({
    x <- mtcars$mpg
    bins <- seq(min(x), max(x), length.out = input$bins + 1)
    hist(x, breaks = bins, col = "skyblue", border = "white",
         main = "Histogram of MPG", xlab = "Miles Per Gallon")
  })
}

shinyApp(ui = ui, server = server)
```
Note
  • Using components: [editor, viewer] displays both the app’s source code and the running application.
  • You can also adjust the layout using #| layout: vertical if you prefer the editor to be stacked above the viewer.
#| '!! shinylive warning !!': |
#|   shinylive does not work in self-contained HTML documents.
#|   Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| viewerHeight: 650

library(shiny)
library(bslib)

ui <- page_sidebar(
  title = "Editable Shiny App in Quarto",
  sidebar = sidebar(
    sliderInput("bins", "Number of bins:", min = 5, max = 30, value = 10)
  ),
  plotOutput("distPlot")
)

server <- function(input, output) {
  output$distPlot <- renderPlot({
    x <- mtcars$mpg
    bins <- seq(min(x), max(x), length.out = input$bins + 1)
    hist(x, breaks = bins, col = "skyblue", border = "white",
         main = "Histogram of MPG", xlab = "Miles Per Gallon")
  })
}

shinyApp(ui = ui, server = server)
Note

This example displays the source code editor above the running application, allowing for real-time code modifications.

Interactive Exercise

Try an exercise to enhance the embedded app. For instance, modify the histogram color or add a new input control. Experiment by editing the code above.

5. Troubleshooting and Customization Tips

Troubleshooting Tips

  • Asset Loading Issues:
    If your app doesn’t load, verify that the Shinylive extension is correctly added and your document YAML includes:

    filters:
      - shinylive
  • Viewer Size:
    If the app appears too small, adjust the viewerHeight option.

  • Errors in the App:
    Check the browser console for errors and ensure that all required packages are installed.

Customization Tips

  • Using bslib for Styling:
    Leverage the bslib package to customize your app’s theme and appearance.

  • Layout Adjustments:
    Use Quarto layout containers (e.g., column-page-inset) to improve the display of embedded apps, especially when the editor and viewer are shown side-by-side.

  • Editor Visibility:
    Use the components option to toggle the code editor on or off, depending on whether you want to allow user modifications.

6. Performance Considerations

  • Reactive Efficiency:
    Optimize reactive expressions within your Shiny app to ensure smooth performance.

  • Browser Compatibility:
    Ensure your app runs in modern browsers that support necessary APIs like OffscreenCanvas.

  • Asset Caching:
    The Shinylive extension manages asset caching automatically. If you experience delays, check that assets are properly cached.

Further Reading

Conclusion

Embedding Shiny apps into Quarto documents using the Shinylive extension transforms your static pages into interactive experiences—allowing you to share live, reactive content without the need for a dedicated server. Experiment with the provided examples and customize your app to fit your project’s needs.

Happy coding and enjoy integrating interactive Shiny applications in your Quarto documents!

Back to top

Reuse

Citation

BibTeX citation:
@online{kassambara2025,
  author = {Kassambara, Alboukadel},
  title = {Using {Shiny} with {Quarto} for {Interactivity}},
  date = {2025-03-08},
  url = {https://www.datanovia.com/learn/interactive/r/shiny-integration.html},
  langid = {en}
}
For attribution, please cite this work as:
Kassambara, Alboukadel. 2025. “Using Shiny with Quarto for Interactivity.” March 8, 2025. https://www.datanovia.com/learn/interactive/r/shiny-integration.html.