#' Launch the application
#'
#' @export
run_app <- function() {
app_dir <- system.file("shiny", package = "myshinyapp")
if (app_dir == "") {
stop("Could not find app directory. Try re-installing the package.")
}
shiny::runApp(app_dir)
}Packaging Shiny Applications as R Packages
A Shiny application built as an R package can be installed by others with a single command, has its dependencies declared formally in a DESCRIPTION file, and can be shared via GitHub without requiring the recipient to manage file paths or install packages manually. This guide shows how to create a minimal package structure around a Shiny application and how to expose it through a run_app() function.
Why package a Shiny application
A standalone app.R file works well during development and for personal use. Distributing it to colleagues is another matter. They need to obtain the file, install the correct packages, and call shiny::runApp() with the right path. If the application changes, they need to replace their copy.
Wrapping the application in an R package solves all of this. The package declares its dependencies in a DESCRIPTION file, so installation handles everything automatically. The user runs the application with a single call such as myshinyapp::run_app(). The application code is version controlled alongside any helper functions or documentation, and updating the installed version requires only a single reinstall command.
Minimal package structure
A package containing a Shiny application needs the following files.
myshinyapp/
├── DESCRIPTION
├── NAMESPACE
├── R/
│ └── run_app.R
└── inst/
└── shiny/
└── app.R
inst/shiny/app.R contains the ordinary Shiny application exactly as you would write it standalone. R/run_app.R provides a single exported function that locates and runs it. DESCRIPTION declares the package name, version, and dependencies. NAMESPACE lists the exported functions and is generated automatically by roxygen2.
The DESCRIPTION file
Package: myshinyapp
Title: A Minimal Shiny Application Package
Version: 0.1.0
Author: Mark Andrews
Maintainer: Mark Andrews <m.andrews@ntu.ac.uk>
Description: Demonstrates how to distribute a Shiny app as an R package.
License: MIT + file LICENSE
Imports:
shiny,
ggplot2
Encoding: UTF-8
The Imports: field lists every package the application uses. When someone installs your package, these are installed automatically. Add every package that appears in library() calls inside your application.
The run_app function
system.file("shiny", package = "myshinyapp") resolves the path to inst/shiny/ regardless of where the package is installed on the user’s machine. This means the function works identically whether the package is installed from source, from CRAN, or from GitHub. The check for an empty string guards against the package being loaded but not properly installed.
The application itself
Place a standard app.R inside inst/shiny/. It is identical to any other Shiny application.
# inst/shiny/app.R
library(shiny)
library(ggplot2)
ui <- fluidPage(
titlePanel("Normal distribution explorer"),
sidebarLayout(
sidebarPanel(
sliderInput("n", "Sample size", min = 10, max = 1000, value = 200),
sliderInput("mean", "Mean", min = -5, max = 5, value = 0, step = 0.5),
sliderInput("sd", "SD", min = 0.1, max = 5, value = 1, step = 0.1)
),
mainPanel(plotOutput("hist"))
)
)
server <- function(input, output) {
output$hist <- renderPlot({
df <- data.frame(x = rnorm(input$n, mean = input$mean, sd = input$sd))
ggplot(df, aes(x = x)) +
geom_histogram(bins = 30, fill = "steelblue", colour = "white") +
theme_minimal()
})
}
shinyApp(ui, server)Building and installing the package
From the package root directory, generate the NAMESPACE file and install:
devtools::document() # read roxygen2 comments and write NAMESPACE
devtools::install() # install the package into your R libraryAfter installation, run the application like any other package function:
library(myshinyapp)
run_app()Or without loading the package:
myshinyapp::run_app()Deciding what goes where
Keep the application logic in inst/shiny/app.R as a self-contained file. If the application uses helper functions for data preparation or plotting, you can define those in the R/ directory and call them from within the app. Shiny loads all files in R/ automatically when the package is installed, so the functions will be available without any additional source() calls.
# R/plot_helpers.R (available inside inst/shiny/app.R automatically)
make_histogram <- function(x, bins = 30, colour = "steelblue") {
df <- data.frame(x = x)
ggplot(df, aes(x = x)) +
geom_histogram(bins = bins, fill = colour, colour = "white") +
theme_minimal()
}This separation keeps the app.R clean and makes the helper functions independently testable with standard tools such as testthat.