Running Shiny without a server

Joe Cheng

What is a “server”?

A computer running 24/7, connected to the internet, that stands ready to run your Shiny app using R or Python.

Want to share your Shiny app with others? You need a server, and it needs to run R or Python.

Photo credit: Jainath Ponnala on Unsplash

Photo credit: Matthew Henry on Unsplash

Lots of great options

But all have tradeoffs between cost, scalability, and features.

“Academics hate this one simple equation!”

\[ \text{Cost} = k \cdot (\text{Computational Complexity} \cdot \text{Number of Users}) \]

Wouldn’t it be easier if it all just blew away?

WebAssembly (wasm)

What is wasm?

  • For years, browsers’ only native tongue was JavaScript
  • Now, browsers all speak JavaScript and wasm
  • JavaScript is designed for humans to write, wasm is designed for compilers to emit
  • Write code in C/C++, compile to wasm, and run it in the browser!

I was wrong about wasm!

“Their” reasoning:

  • Shiny is written in R
  • R is written in C/C++
  • C/C++ can be compiled to wasm
  • Shiny can be compiled to wasm, QED

My response: “Well, actually…”

Porting is even more difficult than it seems

Some fairly basic computing capabilities are just not available in the browser!

  • Cannot launch a process
  • Cannot open a network connection
  • Cannot perform synchronous I/O (e.g. fetch a web page)
  • Cannot handle interrupt signals (e.g. Ctrl-C)

wasm doesn’t change these limitations, it just makes them hurt more.

Dèyè mòn, gen mòn –Haitian proverb

Translation: Beyond mountains, more mountains

Some people are just built different

  • Me: “Stop suggesting we port things to wasm! It’s never going to work!”
  • Alon Zakai: “👋 I built a compiler toolchain and computing platform that runs on wasm” → emscripten
  • Michael Droettboom: “👋 I patched NumPy, Matplotlib, and Pandas to run on emscripten” → Pyodide
  • Winston Chang: “👋 I made Shiny run on Pyodide” → Shinylive
  • George Stagg and Lionel Henry: “👋 We patched R and built a <canvas> graphics device to run on emscripten” → WebR

Alon Zakai Michael Droettboom Winston Chang George Stagg Lionel Henry

July 2022: Announced Shinylive for Python

Traditional Shiny deployment: Python runs on the server, not in the browser

Shinylive deployment: Python runs in the browser, not on the server

Today: Announcing Shinylive for R!!!

Traditional Shiny deployment: R runs on the server, not in the browser

Shinylive deployment: R runs in the browser, not on the server

How to use Shinylive

Several different options are available




Option 1: Convert

{shinylive}: Convert local Shiny app to static HTML/CSS/JS/wasm

app.R -> shinylive::export() -> index.html & assets

Option 1: Convert

{shinylive}: Convert local Shiny app to static HTML/CSS/JS/wasm -> shinylive export -> index.html & assets

Option 1: Convert

Caveat: For browser security reasons, you can’t just double-click index.html to run it locally. You need a real web server. Fortunately, both R and Python have one-liners to start a web server for a directory.

Shiny for R:

> shinylive::export(app_dir="myapp", output_dir="site")
> httpuv::runStaticServer("site")

Shiny for Python:

$ shinylive export myapp site
$ cd site
$ python -m http.server 8000

Option 2: Fiddle Write and share Shiny apps directly in the browser

Shiny for Python:

Shiny for R:

Option 2: Fiddle Write and share Shiny apps directly in the browser

  • View and run examples
  • Create your own apps
  • Share via URL
  • Save to GitHub gist

Option 3: Include

Shinylive Quarto extension: Static Shiny apps as Quarto code chunks

#| standalone: true

ui <- ...

server <- function(input, output, session) {

shinyApp(ui, server)

Option 3: Include

Shinylive Quarto extension: Static Shiny apps as Quarto code chunks

#| standalone: true
#| viewerHeight: 600

theme <- bs_theme(font_scale = 1.5)

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

server <- function(input, output, session) {
  data <- reactive({
    if (!isTRUE(input$pause)) {
  output$plot <- renderPlot({
      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)

“I think the students really appreciate seeing it in action, since it’s such a tricky concept to grasp.” –Erin Howard, Oregon State University

Not just cheaper

Mainframe computer

Photo credit: Norsk Teknisk Museum, CC BY-SA 4.0


Photo credit: Florian Schäffer, CC BY-SA 4.0, via Wikimedia Commons


Photo credit: bert b on Unsplash


Photo credit: on Unsplash

AirTag on keychain

Photo credit: Eddie Pipocas on Unsplash

New uses for Shiny

Shiny for Python tutorial is all shinylive

A tutorial page, featuring text plus an editor pane and Shiny app preview

New uses for Shiny

Shiny for Python function reference docs embed example apps

A function reference page, showing running Shiny app examples

New uses for Shiny

pkgdown sites for R could use Shiny apps to demonstrate package functionality (hypothetically)

The documentation website for the gt package for R Another screenshot of gt documentation

New uses for Shiny

An R Consortium working group and the FDA are exploring the possibility of WebR and Shinylive as a way to include reproducible reports and apps in clinical study reports.

New uses for Shiny

Your turn!

  • Could your next presentation be more compelling with some interactivity?
  • Could your lecture notes lead to deeper understanding if they had interactive examples?
  • Would your blog posts be more powerful if they featured interactive apps?
  • Could you bewilder your students with a random game of Hangman in the middle of their homework?


  • Convert: Use the {shinylive} package to convert app.R/ to static HTML
  • Fiddle: Visit or to start writing and running Shiny apps in the browser
  • Include: Use quarto-shinylive to embed Shiny apps in Quarto documents, presentations, and websites


  • Slower startup time, larger download size
    • Especially bad for R right now, fixes coming very soon
  • Not all of CRAN or PyPI is available
  • Some functions just don’t work (R: system() and {future}, Python: multiprocessing)
  • Can’t connect directly to databases (but API calls may work)
  • Code/data is fully visible to users

Thank you!

Copy of these slides, and links to next steps:

QR code to the same link as above