Short Course on R Tools

Building Interactive Web Apps with Shiny

Mehdi Maadooliat and Hossein Haghbin

Marquette University
SCoRT - Summer 2025

Outline

  • Introduction to Shiny
  • App Structure: UI & Server
  • Inputs & Outputs
  • Shinyapps Gallery
  • Reactivity, Isolate & Observer
  • Deployment & Best Practices
  • Hands-on Exercises

Introduction to Shiny

Structure of a Shiny App

# app.R single-file app
library(shiny)
ui <- fluidPage(
  ...
)

server <- function(input, output) {
  ...
}

shinyApp(ui, server)
  • ui defines layout and inputs/outputs

  • server contains R code & reactivity

Structure of a Shiny App

# app.R single-file app
library(shiny)
ui <- fluidPage(
  titlePanel("Hello Shiny"),
  sidebarLayout(
    sidebarPanel(sliderInput("obs", "Observations:", 1, 100, 50)),
    mainPanel(plotOutput("distPlot"))
  )
)

server <- function(input, output) {
  output$distPlot <- renderPlot({
    hist(rnorm(input$obs))
  })
}

shinyApp(ui, server)
  • ui defines layout and inputs/outputs

  • server contains R code & reactivity

Structure of a Shiny App

Shiny apps come in two parts:

UI

  • Defines the layout and appearance.

  • Contains elements such as:

    • layout structures (sidebars)
    • inputs (text boxes, sliders, buttons)
    • outputs (plots, tables)

Server

  • Performs calculations.

  • Contains the logic to respond to user inputs, and update outputs.

  • Communicates with the UI to dynamically render outputs.

Exercise

05:00
  • Open up your IDE of choice.

  • Make sure you have the {shiny} package installed.

  • Create an app.R file.

  • Add ui and server elements, as well as shiny::shinyApp(ui, server).

  • Check it works.

Inputs & Outputs

  • Inputs: textInput(), selectInput(), sliderInput(), etc.

  • Outputs: renderPlot(), renderTable(), renderUI(), etc.

  • Binding: output objects referenced by output$...

input$slider  # numeric
input$check   # logical

Widgets - Input

Widgets - Output Table

Reactivity Fundamentals

  • Reactive expressions: cache results

    rv <- reactive({ rnorm(input$obs) })
    output$plot <- renderPlot(hist(rv()))
  • isolate(): break reactive chain

    output$summary <- renderText({
      paste0('input$text is "', input$text,
      '", and input$n is ', isolate(input$n))
    })      
  • Observers: side-effect actions

    observeEvent(input$go, { showModal(...) })

Reactivity Demo

Isolate Demo

Observers Demo

Deploying a Shiny app

  • What do we mean by deployment?

    • Getting the Shiny app off your laptop and out into the world!
  • Traditional deployment
  • We need a server to run the R code:
    • shinyapps.io
    • Posit Connect
    • Private server (e.g. university)

Screenshot of Rstudio

Shinylive deployment

Traditional diagram

Shinylive diagram

Shinylive deployment

See posit-dev.github.io/r-shinylive.

The {shinylive} package converts a standard shiny app into a shinylive app:

install.packages("shinylive")

Assuming your app.R file is in a folder called app:

shinylive::export("app", "site")

You can then use the files in the site folder to deploy it as a normal website.

*not all R packages are available for shinylive.

**initial load time is still quite slow.

Tips for building Shiny apps

  • Build tests using shinytest2.

  • Building apps as packages helps with dependency management.

  • Learn a little bit of HTML, CSS, and Javascript.

  • Modules are a good way to reuse bits of UI and server code across the application.

  • Start with pen and paper… (think about user experience!)

Hands-on Exercises (30 min)

Resources & Further Reading

Q&A

Thank You

  • Happy coding with Shiny!