Chapter 2 Your first Shiny app

2.1 Introduction

In this chapter, we’ll create a simple Shiny app. I’ll start by showing you the minimum boilerplate needed for a Shiny app, and then you’ll learn how to start and stop it. Next you’ll learn the two key components of every Shiny app: the UI (short for user interface) which defines how your app looks, and the server function which defines how your app works. Shiny uses reactive programming to automatically update outputs when inputs change so we’ll finish off the chapter by learning the third important component of Shiny apps: reactive expressions.

If you haven’t already installed Shiny, install it now with:

Then load in your current R session:

2.2 Create app directory and file

There are several ways to create a Shiny app. The simplest is to create a new directory for your app, and put a single file called app.R in it. This app.R file will be used to tell Shiny both how your app should look, and how it should behave.

Try it out by creating a new directory, and adding an app.R file that looks like this:

This is a complete, if trivial, Shiny app! Looking closely at the code above, our app.R does four things:

  1. It calls library(shiny) to load the shiny package.

  2. It defines the user interface, the HTML webpage that humans interact with. In this case, it’s a page containing the words “Hello, world!”.

  3. It specifies the behavior of our app by defining a server function. It’s currently empty, so our app doesn’t do anything, but we’ll be back to revisit this shortly.

  4. It executes shinyApp(ui, server) to construct and start a Shiny application from UI and server.

2.3 Running and stopping

There are a few ways you can run this app:

  • Click the Run App button in the document toolbar.

  • Use a keyboard shortcut: Cmd/Ctrl + Shift + Enter.

  • If you’re not using RStudio, you can source() the whole document, or call shiny::runApp() with the path to the directory containing app.R.

Pick one of these options, and check that you see the same app as in Figure 2.1. Congratulations! You’ve made your first Shiny app.

The very basic shiny app you'll see when you run the code above

Figure 2.1: The very basic shiny app you’ll see when you run the code above

Before you close the app, go back to RStudio and look at the R console. You’ll notice that it says something like:

This tells you the URL where your app can be found: 127.0.0.1 is a standard address that means “this computer” and 3827 is a randomly assigned port number. You can enter that URL into any compatible1 web browser to open another copy of your app.

Also notice that R is busy: the R prompt isn’t visible, and the console toolbar displays a stop sign icon. While a Shiny app is running, it “blocks” the R console. This means that you can’t run new commands at the R console until after the Shiny app stops.

You can stop the app and return access to the console using any one of these options:

  • Click the stop sign icon on the R console toolbar.

  • Click on the console, then press Esc (or press Ctrl + C if you’re not using RStudio).

  • Close the Shiny app window.

The basic workflow of Shiny app development is to write some code, start the app, experiment with the app, play the app, write some more code, … You’ll learn other patterns later in Chapter 6.

2.4 Adding UI controls

Next, we’ll add some inputs and outputs to our UI so it’s not quite so minimal. We’re going to make a very simple app that shows you all the built-in data frames included in the datasets package.

Replace your ui with this code:

This example uses four new functions:

  • fluidPage() is a layout function that sets up the basic visual structure of the page. You’ll learn more about them in Section 3.4.

  • selectInput() is an input control that lets the user interact with the app by providing a value. In this case, it’s a select box with the label “Dataset” and lets you choose one of the built-in datasets that come with R. You’ll learn more about inputs in Section 3.2.

  • verbatimTextOutput() and tableOutput() are output controls that tell Shiny where to put rendered output (we’ll get into the how in a moment). verbatimTextOutput() displays code and tableOutput displays tables. You’ll learn more about outputs in Section 3.3.

Layout functions, inputs, and outputs have different uses, but they are fundamentally the same under the covers: they’re all just fancy ways to generate HTML, and if you call any of them outside of a Shiny app, you’ll see HTML printed out at the console. Don’t be afraid to poke around to see how these various layouts and controls work under the hood. You’ll learn more of the details in Chapter 13.

Go ahead and run the app again. You’ll now see Figure 2.2, a page containing a select box. We only see the input, not the two outputs, because we haven’t yet told Shiny how the input and outputs are related.

The datasets app with UI

Figure 2.2: The datasets app with UI

2.5 Adding behavior

Next, we’ll bring the outputs to life by defining them in the server function.

Shiny uses reactive programming to make apps interactive. You’ll learn more about reactive programming in Chapter 4, but for now, just be aware that it involves telling Shiny how to perform a computation, not ordering Shiny to actually go do it. It’s like the difference between giving someone a recipe versus demanding that they go make you a sandwich.

In this simple case, we’re going to tell Shiny how to fill in the summary and table outputs—we’re providing the “recipes” for those outputs. Replace your empty server function with this:

Almost every output you’ll write in Shiny will follow this same pattern:

The left-hand side of the assignment operator (<-), output$ID, indicates that you’re providing the recipe for the Shiny output with the matching ID. The right-hand side of the assignment uses a specific render function to wrap some code that you provide; in the example above, we use renderPrint() and renderTable() to wrap our app-specific logic.

Each render* function is designed to work with a particular type of output that’s passed to an *Output function. In this case, we’re using renderPrint() to capture and display a statistical summary of the data with fixed-width (verbatim) text, and renderTable() to display the actual data frame in a table.

Run the app again and play around, watching what happens to the output when you change an input. Figure 2.3 shows what you’ll see when you open the app.

Now that we've provided a server function that connects and inputs, we have a fully functional app

Figure 2.3: Now that we’ve provided a server function that connects and inputs, we have a fully functional app

Notice that I haven’t written any code that checks for changes to input$dataset and explicitly updates the two outputs. That’s because outputs are reactive: they automatically recalculate when their inputs change. Because both of the rendering code blocks I wrote used input$dataset, whenever the value of input$dataset changes (i.e. the user changes their selection in the UI), both outputs will recalculate and update in the browser.

2.6 Reducing duplication with reactive expressions

Even in this simple example, we have some code that’s duplicated: the following line is present in both outputs.

In every kind of programming, it’s poor practice to have duplicated code; it can be computationally wasteful, and more importantly, it increases the difficulty of maintaining or debugging the code. It’s not that important here, but I wanted to illustrate the basic idea in a very simple context.

In traditional R scripting, we use two techniques to deal with duplicated code: either we capture the value using a variable, or capture the computation with a function. Unfortunately neither of these approaches work here, for reasons you’ll learn about in Section 14.2, and we need new mechanism: reactive expressions.

You create a reactive expression by wrapping a block of code in reactive({...}) and assigning it to a variable, and you use a reactive expression by calling it like a function. But while it looks like you’re calling a function, a reactive expression has an important difference: it only runs the first time it is called and then it caches its result until it needs to be updated.

We can output our server() to use reactive expressions, as shown below. The app behaves identically, but works a little more efficiently because it only needs to retrieve the dataset once, not twice.

We’ll come back to reactive programming multiple times, but even armed with a cursory knowledge of inputs, outputs, and reactive expressions, it’s possible to build quite useful Shiny apps!

2.7 Cheat sheet

Before you continue on to read more about user interfaces and reactive programming, now is a great time to grab a copy of the Shiny cheatsheet from https://www.rstudio.com/resources/cheatsheets/. This is a great resource to help jog your memory of the main components of a Shiny app.

2.8 Exercises

  1. Create an app that greets the user by name. You don’t know all the functions you need to do this yet, so I’ve included some lines of code below. Figure out which lines you’ll use and then copy and paste them into the right place in a Shiny app.

  2. Suppose your friend wants to design an app that allows the user to set a number (x) between 1 and 50, and displays the result of multiplying this number by 5. This is their first attempt:

    But unfortunately it has an error:

    Can you help them find and correct the error?

  3. Extend the app from the previous exercise to allow the user to set the value of the multiplier, y, so that the app yields the value of x * y. The final result should look like this:.

  4. Replace the UI and server components of your app from the previous exercise with the UI and server components below, run the app, and describe the app’s functionality. Then reduce the duplication in the app by using a reactive expression.

  5. The following app is very similar to one you’ve seen earlier in the chapter: you select a dataset from a package (this time we’re using the ggplot2 package) and the app prints out a summary and plot of the data. It also follows good practice and makes use of reactive expressions to avoid redundancy of code. However there are three bugs in the code provided below. Can you find and fix them?


  1. Shiny strives to support all modern browsers, and you can see the set currently supported at https://www.rstudio.com/about/platform-support/. Note that Internet Explorer versions prior to IE11 are not compatible when running Shiny directly from your R session., However, Shiny apps deployed on Shiny Server or ShinyApps.io can work with IE10 (earlier versions of IE are no longer supported).