ETC5523: Communicating with Data

Tutorial 11: Package and audit a Shiny app

Author

Michael Lydeamore

Published

1 November 2001

🎯 Objectives

By the end of this tutorial, you will be able to:

  • add a package function that launches a Shiny app; and
  • audit an app before web deployment.

Install the packages used in this tutorial if you do not already have them:

install.packages(c("devtools", "rsconnect", "usethis"))

Bring the etc5523-wpl-share project you used in the workshop. If you missed the workshop, or would like a clean copy containing everything completed in class, clone the workshop-progress branch:

#| eval: false
#| echo: true
git clone --branch workshop-progress --single-branch \
  https://github.com/numbats/etc5523-wpl-share.git

Open wplshare.Rproj, restart R, then install any dependencies declared by the package:

devtools::install_deps(dependencies = TRUE)

Run the app and confirm that the number, plot and table agree when Minimum runs is exactly 150 in season 2024/25:

shiny::runApp("inst/app")
Important

In the workshop, we completed Steps 1–3: running the app, inspecting its reactive graph and replacing the repeated filters with selected_batters(). This tutorial continues from that point with Steps 4 and 5.

4. Make the app launchable from the package

The repository already has the structure of an R package. Files under inst/app will be installed with it.

Create R/run_app.R, then add a documented, exported run_app() function:

usethis::use_r("run_app")

The function should:

  1. locate the installed app directory with system.file(); and
  2. pass that directory to shiny::runApp().

Generate the documentation, install the package and test the launcher:

devtools::document()
devtools::install()
wplshare::run_app()

Why would a path such as /Users/name/wpl-share/inst/app fail for another package user?

5. Audit the web deployment

Treat the hosting service as a clean Linux computer that receives only the app bundle. Mark each item ready, not ready, or not applicable:

  • all required files are inside inst/app;
  • file paths are relative and match the exact case of the file names;
  • package dependencies can be detected from the app code;
  • there is no install.packages() call in the app;
  • no password, token or secret is stored in the repository;
  • every possible input state produces a useful response; and
  • any durable writes use storage outside the app’s local filesystem.

Ask rsconnect what it detects:

rsconnect::appDependencies("inst/app")

Which audit item does the current app handle least well? Make one improvement and rerun the app.

Extra practice: a clean-room handover test

Exchange repositories with a partner. Open your partner’s project in a fresh R session and test whether the package can be installed and run without relying on their source directory or your installed copy of wplshare.

Create a temporary package library, install the package into it, then launch the app from that installation:

test_library <- file.path(tempdir(), "wplshare-library")
dir.create(test_library, showWarnings = FALSE)

devtools::install(lib = test_library)

library(wplshare, lib.loc = test_library)
wplshare::run_app()

Record any missing dependency, path assumption or unclear setup instruction. Fix one issue, restart R and repeat the handover test.

Note

Installing into test_library prevents your partner’s package from replacing the usual installed copy of wplshare. The temporary installation is removed when R clears its temporary directory.