install.packages("rsconnect")
library(rsconnect)
19 shinyapps.io
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:
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.
You can also manually set the shinyapps.io account info using rsconnect::setAccountInfo()
:
::setAccountInfo(
rsconnectname = '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:
Make sure all the files in the package are selected, enter an app title, then click Publish:
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.
::deployApp(
rsconnectappDir = getwd(),
appName = "movie-reviews")
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()
<- function(message, level = "INFO", log_file = "app_log.txt", json = FALSE, store_log = TRUE) {
logr_msg
# Console logging
::log_formatter(formatter = logger::formatter_glue)
logger::log_layout(layout = logger::layout_glue_generator())
logger
if (store_log) {
<- dirname(log_file)
log_dir if (!dir.exists(log_dir)) {
dir.create(log_dir, recursive = TRUE)
}if (!file.exists(log_file)) {
file.create(log_file)
}
if (json) {
::log_appender(appender = logger::appender_tee(log_file))
logger::log_layout(layout = logger::layout_json())
loggerelse {
} ::log_appender(appender = logger::appender_tee(log_file))
logger::log_layout(layout = logger::layout_glue_generator())
logger
}else {
} ::log_appender(appender = logger::appender_console)
logger
}
# 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}"),
::log_info("{message}") # default to INFO if level is invalid
logger
) }
- 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)
::log_threshold('TRACE')
loggerlaunch_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).
::deployApp(
rsconnectappDir = getwd(),
appName = "movie-reviews",
forceUpdate = TRUE)
After the application re-deploys, we can view and/or download the 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.
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.
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.↩︎