7 Easy Steps to Building your Own Shiny App from Scratch

Shiny is a powerful tool in R for you to show off your work to the world, without explaining all the complicated code behind your analysis. Because of its free and open-source development and deployment structure, sharing your methods or work online was never easier. For example, in our recent publication in the Journal of European Psychology Students my colleagues and me used Shiny to implement a network method in which we used the concept of network centrality to determine the most relevant articles in a research field. Because I believe there are a lot of benefits in sharing one’s methods, my hopes are that this blog post has the possibility to also inspire you to share your own work through Shiny. I will walk you though developing your own R Shiny application from scratch, tailoring it to your design choices, and publishing it online, in 7 easy steps. Together we will create an application that has a pleasant layout, allows the user to upload a data file, performs some calculations on selected variables and returns the output in a nice format. Code snippets will be given at every step along the way, which you can paste directly into R to see how the application develops from basic functionality to a fully functioning web app. The result can be found here.

Step 1: The Idea

The first step in any design process is thinking of an idea. This, for me, is also the most important step in the process. I that it helps me a great deal when the application and the features that I want in it are completely defined in my head. I will often draw the layout and the features that I have in mind on a piece of paper. The reason I do this is that, because you will build your Shiny application step-by-step, it would be a waste if you would have to go back and change things in the layout. So, I drew our imagined application on a piece of paper. I will make a one-page application that allows the user to upload some data, perform a correlation analysis and inspect the results.

Step 2: Launching Shiny

Shiny itself is an R package that works best in RStudio, which is the most used R environment among users. For RStudio to work properly, you need to separately install R on your computer. Once you open RStudio, in the new file menu, click the option to open a new Shiny Web App. RStudio will now prompt you with the screen below, asking you to specify the folder name for the application, whether you want a single file app or multiple file app, and the directory on your computer in which you want the app folder to be created. For ease of illustration we will create the application in a single file, but both options are okay to use. I am going to name the app directory “correlation” and it will go into one of my many folders, probably never to see the light of day again.

Tip. If you are familiar with Github, this is probably a good time to set up a repository in the application directory for version control.

Step 3: The Shiny Structure

Any Shiny application has two parts, the user interface (UI) function and the server function, which interact with each other. The UI function has an important visual task. It creates the html environment that allows the user to interact with the server function using buttons, sliders and other custom inputs while also rendering the visual output. All these components are placed in a layout in the UI function. The server function is responsible for all the calculations according to the input options that is receives from the UI function. The server function is where all the computational heavy-lifting is performed, like calculating the statistics for our correlation analysis. For example, if the user enables a checkbox (UI) that controls whether a regression line should be drawn in a scatter plot, the plot should be created (server) with a regression line and rendered in html (UI) to be displayed on the screen. The picture below shows how input and output are bounced around between the UI function and the server function and hopefully gives you an idea about the interaction between the two.

Tip. Try to get a feeling of the interaction between the UI and server functions. Ask questions like: what options should I have, and what should happen to the output when the user changes these options?

Step 4: Creating Your Layout

Let me say that there is a lot of packages out there that make shiny applications look pretty, and I agree that these downloadable add-ons can really improve the quality to your work and are worth looking into. Packages like Shiny Dashboard will make your applications look and feel fantastic. For now, I consider these topics advanced knowledge and I will provide you with a list of them at the end, so you can explore them yourself. However, they still require a basic understanding of Shiny concepts and therefore I will stick to the basics in this post.

When you first create a new Shiny app, R presents you with a default template application drawing a histogram. Check it out if you want, by pressing the “Run App” button in RStudio. However, the first step to any good and original app is to start from scratch. So, to start off, completely empty the pre-defined ui() and server() functions that R presents you with. We are going to make our own, better functions. All the information that I discuss here can also be found at the Shiny layout guide, which is a great resource when starting with Shiny.

The number of pages or tabs of your application will be defined by one of the page functions. Page functions are the top level of your UI function. For an application with multiple tab-pages, you can assign the navbarPage() function to the UI object. However, the default page equals a fluidPage() layout, which gives you a single page to work with. Since our application requires only one tab, let’s keep the default page function. The page will be assigned to the UI function. You can check out code snippet #1 for how I applied this in R. Remember you can check the application at any time by running the app through RStudio.

We are now going to further layout our page, since it still empty. In my applications, I often use a sidebar to indicate the difference between the input (options) and the output (result). With a sidebar, the application is divided in two parts; the sidebar for the input options and the main panel for the output display. The sidebar layout can be set by inserting the sidebarLayout() function into the fluid page. Since this layout can include a sidebar and a main panel, we will insert them into the sidebar layout by calling their appropriate layout functions as well, see code snippet #2. Finally, a title panel can be inserted above the sidebar layout with titlePanel(“Correlation”).

This skeleton will be the framework of the application. We will fill these layouts with drop-down menus, upload buttons, tables and plots. Remember that at this point, the server() function is still empty. We don’t need it yet, since we want to build up the entire user-interface first.

The Sidebar

Let’s start with filling the sidebar. Shiny is rendered in an html environment and uses recognizable html functions for text rendering. For example, we can display our intro text with the p() function, displaying regular text. However, if we would like to adjust the font size of the text, we could also use one of h1() through h6() to enlarge the font size. We can add our first interactive element, the upload button, by inserting the fileInput() function in the sidebar. Every interactive UI element has an inputId argument, which basically names the element. This name is used to refer to the element in the server function and should always be filled. For our data input, inputid=”datafile” will be an appropriate name. The file input allows the user to browse their computer for a file to upload to your application. The two drop-down menu’s for selecting variables can be inserted via the selectInput() function. We’ll leave the choices argument in these functions empty for now, I’m going to show you a neat little trick I’ve come across to automatically read in the variable names from the uploaded data set. Going down, we are going to insert a bold title for the plot header with p(strong(“Plot”)). Underneath this header there are two checkboxes, one for the regression line and one for the residuals, for which we use checkboxInput(). We repeat this process for the table header. Lastly, we add an update button using the actionButton() function. I find these buttons working very nicely, as they allow the application to only perform a calculation when all options are set correctly by the user. This saves computation time and makes your application faster, and easier to work with.

The Main Panel

The main panel is where we are going to display the output of our correlation analysis, namely the plot and the results table. It basically works the same as filling the sidebar panel. First, we want to display a header for the results which is slightly larger than regular text, so we’ll use h3(“Result”) for that. Adding plots and tables is extremely easy in Shiny and is done by output functions. These functions reserve a spot for the specific output in the main panel. The plot is reserved with the plotOutput() function and the table with tableOutput(). Remember that we have to give them appropriate input id’s. The result when we run our application is now a nice and clean layout, visually and in code.

Tip Online resources are your friend. Try to use them as much as possible, as they will increase your understanding of the process of making a Shiny application. Look for YouTube clips and blog posts to clarify the material for you.

Step 5: Creating Functionality

Let’s give the application some functionality by filling in the server function. The first logical step is to make sure that the data is read in correctly. For this purpose, we are going to make the drop-down menus recognize the variable names by performing a neat little trick in the server function. When we insert the following code snippet in our server function and run the application, you can see that it now recognizes our variable names in the data file as inputs.

Now it’s time to create the true functionality within the app, namely creating a scatter plot of two user-specified variables, inserting an optional regression line and residuals, and creating a table of the results. As stated in the previous paragraphs, an action button is ideal for monitoring user actions. Only when this button is clicked, the output will be updated. Monitoring buttons is done with the observeEvent() function, which links functionality to an event. In our case, the event is the click on the action button and the functionality is all that I mentioned above. The functionality will only get activated when the action button is clicked by the user. The code for what happens when the button is clicked is inside the second part of the observeEvent() function. This way of thinking makes Shiny a very intuitive and chronological way of working for me. For example, when the button is clicked, the following happens in order (see code snippet #4): 1) a data frame is made with both variables in it, 2) the correlation analysis is run, 3) the output data frame is made, 4) the table is rendered, 5) the plot is created, 6) the additional elements are drawn conditionally and, 7) the plot is rendered. Code snippet #4 shows this chronological order within the server function. Check out how it works by running the app locally if you feel like it.

Tip Programming in Shiny will be a lot of trial-and-error when you do it for the first couple of times. Refresh the browser page in which you are running the application to see the effect of your code changes immediately, instead of closing and opening it each time.

Step 6: Fine-tuning

When the functionality of your application is finished, it is time for the most fun part: making your Shiny app pretty. For example, use shinycssloaders to display some pretty graphics as plots are being created within the server function. It is extremely easy to use, just put withSpinner() around the plotOutput() part of code in the UI function. Other R packages that are be very useful for making your app beautiful are Shinyjs for JavaScript features like showing and hiding options, ShinyWidgets for upgraded and additional widgets, like turning checkboxes into toggle switches (picture below) and ShinyBS to add bootstrap html elements to your app. It is important to remember to load additional packages into your application by calling the library() function at the top of your R file.

Step 7: Publishing Your App

When every component of your application is finished, you are ready to publish your shiny app online. Next to the “Run App” button in RStudio you find a little blue icon   which, when clicked, brings you to the next screen:

If you do not have an account on https://shinyapps.io, create one as it is needed for publishing your application, and connect it to RStudio. When this is done, life gets easy. You just have to click the “Publish” button and all work will be done for you. The application will be uploaded to the shiny server and is accessible from your account, but also from a specific URL. The URL for my application for example, is https://koenderks.shinyapps.io/correlation/. Share your work and enjoy!

Additional R Packages

Shiny Dashboard https://rstudio.github.io/shinydashboard/

CSS Loaders https://github.com/andrewsali/shinycssloaders

Shinyjs https://deanattali.com/shinyjs/

ShinyWidgets https://github.com/dreamRs/shinyWidgets

ShinyBS https://ebailey78.github.io/shinyBS/


Koen Derks

Koen Derks is a PhD student at Nyenrode Business University. Before he started researching Bayesian statistics in financial auditing, he studied psychological methods at the University of Amsterdam (UvA), where his interests for statistics and programming developed itself. Today, he is still collaborating with the UvA to develop software tools for students and practitioners to make data analysis fun and intuitive.

More Posts