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
andbslib
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
Define the UI:
Usepage_sidebar()
to create a layout with a sidebar for inputs and a main panel for outputs.Create Inputs:
Include asliderInput()
in the sidebar for selecting the number of bins for the histogram.Display Output:
UseplotOutput()
in the main panel to show the histogram.Define Server Logic:
In the server function, userenderPlot()
to compute the histogram based on the slider input.Run the App:
Wrap the UI and server definitions in a call toshinyApp()
.
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)
```
- 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)
```
- 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)
This example displays the source code editor above the running application, allowing for real-time code modifications.
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 theviewerHeight
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 thebslib
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 thecomponents
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
- Interactive Code Blocks Explained
Learn how to create and customize interactive code blocks in Quarto Live. - Loading and Using Packages
Discover techniques for installing and loading additional R packages. - Shinylive for R
Dive deeper into the Shinylive ecosystem for running Shiny apps in the browser. - Cell Options Reference
Explore the advanced configuration options available for interactive code blocks.
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!
Explore More Articles
Here are more articles from the same category to help you dive deeper into the topic.
Reuse
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}
}