19  shinyapps.io

Published

2025-02-19

This chapter covers deploying your app-package to shinyapps.io, a cloud-based hosting service provided by Posit (formerly RStudio) for deploying and managing Shiny applications, Quarto/RMarkdown reports, APIs, and other content. We deployed the production version of our application in the previous Section 9.4.2, but we will go into more depth below.

19.1 Publishing to Connect

Below we’ll cover deploying your Shiny app-package in RStudio and Positron . The Positron IDE was still in the early stages of development when this section was written, so some of these steps may change in future versions.

Make sure the rsconnect package is installed and loaded:

install.packages("rsconnect")
library(rsconnect)

19.1.1 In RStudio

RStudio can be configured to work with your shinyapps.io account by clicking on Tools > Global options > Publishing and following the documentation.

shinyapps.io account added to RStudio

shinyapps.io account added to RStudio

You can also manually set the shinyapps.io account info using rsconnect::setAccountInfo():

rsconnect::setAccountInfo(
  name = 'your_username',
  token = 'your_token',
  secret = 'your_secret')

After configuring our shinyapps.io account and loading, documenting, and installing the sap package, we can launch the application and click on the Publish icon:

Send app.R to Console and click Publish

Send app.R to Console and click Publish

Make sure all the files in the package are selected, enter an app title, then click Publish:

Publishing apps to shinyapps.io

Publishing apps to shinyapps.io

The Deploy pane will open and you’ll see a deployment log as your application is sent to the server:

── Preparing for deployment ────────────────────────────────────────────────────
✔ Deploying "movie-reviews" using "server: shinyapps.io / username: paradigmdata"
ℹ Creating application on server...
✔ Created application with id 14030745
ℹ Bundling 72 files: .Rbuildignore, .Rprofile, .vscode/tasks.json, app.R, 
data/movies.rda, data/movies.RData, data-raw/tidy_movies.R, DESCRIPTION, 
NAMESPACE, README.md, vignettes/specs.Rmd, inst/extdata/movies.fst, 
inst/prod/app/.DS_Store, inst/prod/app/app.R, inst/quarto/_quarto.yml, 
inst/quarto/.gitignore, inst/quarto/index.html, inst/quarto/index.qmd, …, 
tests/testthat/test-text_logo.R, and tests/testthat.R
ℹ Capturing R dependencies
✔ Found 103 dependencies
✔ Created 3,283,848b bundle
ℹ Uploading bundle...
✔ Uploaded bundle with id 9818877
── Deploying to server ─────────────────────────────────────────────────────────
Waiting for task: 1510689240
  building: Parsing manifest
  building: Building image: 12075212
  building: Installing system dependencies
  building: Fetching packages
  building: Installing packages
building: Installing files
  building: Pushing image: 12075212
  deploying: Starting instances
  rollforward: Activating new instances
  success: Stopping old instances
── Deployment complete ─────────────────────────────────────────────────────────
✔ Successfully deployed to <https://yourusername.shinyapps.io/app-name/>
Deployment completed: https://yourusername.shinyapps.io/app-name//

19.1.2 In Positron

After authenticating shinyapps.io, loading, documenting, and installing our app-package, we can deploy it in Positron using the rsconnect::deployApp() function.

rsconnect::deployApp(
  appDir = getwd(),
  appName = "movie-reviews")

Deploying Shiny app from Positron’s Console

Deploying Shiny app from Positron’s Console

As we can see, Positron doesn’t open a Deploy window or separate Terminal task for launching the application (it’s printed directly to the Console).

19.2 Deploy logs

On shinyapps.io, the deployment log shows the loadSupport() warning persists (but the application still deploys). The server-side warning is a known issue.1

shinyapps[12692760]: Running as user: uid=10001(shiny) gid=10001(shiny) groups=10001(shiny)
shinyapps[12692760]: Connect version: 2024.05.0
shinyapps[12692760]: LANG: C.UTF-8
shinyapps[12692760]: Working directory: /srv/connect/apps/movie-reviews
shinyapps[12692760]: Using R 4.4.0
shinyapps[12692760]: R.home(): /opt/R/4.4.0/lib/R
shinyapps[12692760]: Content will use current R environment
shinyapps[12692760]: R_LIBS: (unset)
shinyapps[12692760]: .libPaths(): /usr/lib/R, /opt/R/4.4.0/lib/R/library
shinyapps[12692760]: shiny version: 1.9.1
shinyapps[12692760]: httpuv version: 1.6.15
shinyapps[12692760]: rmarkdown version: (none)
shinyapps[12692760]: knitr version: (none)
shinyapps[12692760]: jsonlite version: 1.8.8
shinyapps[12692760]: RJSONIO version: (none)
shinyapps[12692760]: htmltools version: 0.5.8.1
shinyapps[12692760]: reticulate version: (none)
shinyapps[12692760]: Using pandoc: /opt/connect/ext/pandoc/2.16
shinyapps[12692760]: 
shinyapps[12692760]: Starting R with process ID: '31'
shinyapps[12692760]: Shiny application starting ...
shinyapps[12692760]: Warning in warn_if_app_dir_is_package(appDir) :
shinyapps[12692760]:   Loading R/ subdirectory for Shiny application, 
  but this directory appears to contain an R package. Sourcing files 
  in R/ may cause unexpected behavior. See `?loadSupport` for more details.
shinyapps[12692760]: ℹ Loading sap
shinyapps[12692760]: 
shinyapps[12692760]: Listening on http://127.0.0.1:123456
1
loadSupport() warning

19.3 The rsconnect folder

When deploying a Shiny app, the rsconnect/ folder is automatically created to store configuration settings and deployment metadata for the app.

rsconnect/
└── shinyapps.io
    └── paradigmdata
        └── movie-reviews.dcf

3 directories, 1 file

rsconnect/ contains deployment-related metadata, including information about our shinyapps.io account, and app-specific deployment history and settings.

The rsconnect/ folder should not be included in your Git repository because it contains machine-specific settings and is not required for running the app locally. This folder can also lead to conflicts when multiple users work on the same repo.

To ensure the rsconnect folder is not included in your Git repository, add rsconnect/ to .gitignore:

.Rproj.user
.Rhistory
.RData
.Ruserdata
.DS_Store
sap.Rcheck/
sap*.tar.gz
sap*.tgz
rsconnect/

/.quarto/
inst/doc
# {shinytest2}: Ignore new debug snapshots for `$expect_values()`
*_.new.png

If you need to remove rsconnect/ from Git because it’s already been committed, remove it with the following commands:

git rm -r --cached rsconnect/
git commit -m "Remove rsconnect folder from repository"
git push origin main

This will remove it from the Git history while keeping it locally. If we need to share deployment details with our team, we can document the deployment process in the README.Rmd or create a deploy.Rmd vignette.

19.4 App logs

We’ve covered the deployment logs that are generated when we publish our app to shinyapps.io, but what about the logs we’re using to track our application’s behavior (we covered this in Section 13.3)? In this branch, I’ve added the store_log argument to logr_msg() that toggles a ‘save log to external log file’ functionality:

show/hide logr_msg()
logr_msg <- function(message, level = "INFO", log_file = "app_log.txt", json = FALSE, store_log = TRUE) {
  
  # Console logging 
  logger::log_formatter(formatter = logger::formatter_glue)
  logger::log_layout(layout = logger::layout_glue_generator())
  
  if (store_log) {
    log_dir <- dirname(log_file)
    if (!dir.exists(log_dir)) {
      dir.create(log_dir, recursive = TRUE)
    }
    if (!file.exists(log_file)) {
      file.create(log_file)
    }
    
    if (json) {
      logger::log_appender(appender = logger::appender_tee(log_file))
      logger::log_layout(layout = logger::layout_json())
    } else {
      logger::log_appender(appender = logger::appender_tee(log_file))
      logger::log_layout(layout = logger::layout_glue_generator())
    }
  } else {
    logger::log_appender(appender = logger::appender_console)
  }
  
  # levels
  switch(
    level,
    "FATAL" = logger::log_fatal("{message}"),
    "ERROR" = logger::log_error("{message}"),
    "WARN" = logger::log_warn("{message}"),
    "SUCCESS" = logger::log_success("{message}"),
    "INFO" = logger::log_info("{message}"),
    "DEBUG" = logger::log_debug("{message}"),
    "TRACE" = logger::log_trace("{message}"),
    logger::log_info("{message}") # default to INFO if level is invalid
  )
}
1
Configure file logging
2
Log as JSON file
3
Prevent file logging

I’ve set the default value of store_log to FALSE, but we can change this TRUE and logr_msg() will automatically save the logs (after loading, documenting, and installing the package).

To ensure the logs are stored when the application is deployed, we need to add a logger::log_threshold() argument in inst/prod/app/app.R:

library(sap)
logger::log_threshold('TRACE')
launch_app(app = "bslib")

After loading, documenting and installing sap, we can re-deploy with rsconnect::deployApp() (with the forceUpdate = TRUE argument, because we’re updating an existing application).

rsconnect::deployApp(
  appDir = getwd(), 
  appName = "movie-reviews", 
  forceUpdate = TRUE)

After the application re-deploys, we can view and/or download the Logs in the shinyapps.io interface:

logs in the shinyapps.io interface

logs in the shinyapps.io interface

It’s also possible to get the application logs remotely using rsconnect::showLogs(). We can also download the code image from the Overview tab.

Download image from shinyapps.io interface

Download image from shinyapps.io interface

The downloaded image will contain the files we’ve published. A downloaded image is stored in the inst/image folder of this branch:

inst/image/e47f9753baa54a599719c0b68c05521f/
├── DESCRIPTION
├── NAMESPACE
├── R
│   ├── data.R
│   ├── display_type.R
│   ├── launch_app.R
│   ├── log_message.R
│   ├── logr_msg.R
│   ├── mod_aes_input.R
│   ├── mod_scatter_display.R
│   ├── mod_var_input.R
│   ├── movies_server.R
│   ├── movies_ui.R
│   ├── scatter_plot.R
│   ├── testthat.R
│   ├── text_logo.R
│   └── zzz.R
├── README.md
├── app.R
├── data
│   ├── movies.RData
│   └── movies.rda
├── data-raw
│   └── tidy_movies.R
├── inst
│   ├── extdata
│   ├── prod
│   ├── quarto
│   ├── tidy-movies
│   └── www
├── man
│   ├── display_type.Rd
│   ├── launch_app.Rd
│   ├── log_message.Rd
│   ├── logr_msg.Rd
│   ├── mod_aes_input_server.Rd
│   ├── mod_aes_input_ui.Rd
│   ├── mod_scatter_display_server.Rd
│   ├── mod_scatter_display_ui.Rd
│   ├── mod_var_input_server.Rd
│   ├── mod_var_input_ui.Rd
│   ├── movies.Rd
│   ├── movies_server.Rd
│   ├── movies_ui.Rd
│   ├── scatter_plot.Rd
│   ├── test_logger.Rd
│   └── text_logo.Rd
├── manifest.json
├── tests
│   ├── testthat
│   └── testthat.R
└── vignettes
    └── specs.Rmd

14 directories, 40 files
1
manifest of application dependencies

The manifest.json contains the application dependencies (similar to the lock file created by renv).

Recap

Deploying a Shiny app-package to shinyapps.io requires keeping a clutter-free package structure, authenticating with rsconnect, and managing dependencies for a smooth workflow.

Recap: shinyapps.io
  1. Store the app in the package so it can be accessed using system.file() (i.e., inst/) in an app.R file.

  2. Be able to run the app locally (i.e., using devtools::install() and sap::launch_app())

  3. Install rsconnect and authenticate with shinyapps.io using setAccountInfo() or by accessing Tools > Global Options > Publishing in RStudio.

  4. Deplo the app by clicking on the Publish icon or by using rsconnect::deployApp().

  5. Add rsconnect/ to the .gitignore file to keep deployment metadata out of Git.

    • If already committed, remove it:
    git rm -r --cached rsconnect/
    git commit -m 'Removed rsconnect folder'
    git push origin main
  6. Check logs if issues arise by downloading log file from shinyapps.io interface or using rsconnect::showLogs().


  1. You can learn more about this warning by reading these posts on StackOverflow: How can I deploy my shiny app as a package?; Problem with directory when deploying app on shinyapps, and this post on Posit Community: Errors when deploying app on shinyapps.io.↩︎