launch_app(run = 'p')
9 Resources
In this chapter, weβll cover how to include external resources (i.e., the images, CSS styling, JavaScript files, etc. previously served from the www/
folder) in an app-package.
When we launch our app, we see the Shiny logo (shiny.png
) in the www/
folder is not being loaded into the UI:
Shinyβs internal functions previously automatically handled serving the contents of www/
.1 Now that weβve converted our application into a package, weβll need to tell the application where to find these resources explicitly.2
Package files
While developing, we get used to accessing and interacting with our package files from the Files pane or Explorer window:
However, as noted in the data chapter, the arenβt the files in our installed package. We can use system.file()
and fs::dir_tree()
to print a folder tree of our installed package files:
sap/
βββ DESCRIPTION
βββ NAMESPACE
βββ R
β βββ data.R
β βββ display_type.R
β βββ mod_scatter_display.R
β βββ mod_var_input.R
β βββ launch_app.R
β βββ movies_server.R
β βββ movies_ui.R
β βββ scatter_plot.R
βββ README.md
βββ app.R
βββ data
β βββ movies.RData
β βββ movies.rda
βββ inst
β βββ extdata
β βββ movies.fst
βββ man
β βββ display_type.Rd
β βββ mod_scatter_display_server.Rd
β βββ mod_scatter_display_ui.Rd
β βββ mod_var_input_server.Rd
β βββ mod_var_input_ui.Rd
β βββ movies.Rd
β βββ launch_app.Rd
β βββ movies_server.Rd
β βββ movies_ui.Rd
β βββ scatter_plot.Rd
βββ sap.Rproj
βββ www βββ shiny.png
sap/
βββ DESCRIPTION
βββ INDEX
βββ Meta
β βββ Rd.rds
β βββ data.rds
β βββ features.rds
β βββ hsearch.rds
β βββ links.rds
β βββ nsInfo.rds
β βββ package.rds
βββ NAMESPACE
βββ R
β βββ sap
β βββ sap.rdb
β βββ sap.rdx
βββ data
β βββ Rdata.rdb
β βββ Rdata.rds
β βββ Rdata.rdx
βββ extdata
β βββ movies.fst
βββ help
β βββ AnIndex
β βββ aliases.rds
β βββ sap.rdb
β βββ sap.rdx
β βββ paths.rds
βββ html
βββ 00Index.html βββ R.css
- 1
-
DESCRIPTION
is in both source and installed versions, and format remains unchanged. - 2
-
Metadata files, such as
data.rds
andpackage.rds
, are created in theMeta/
directory
- 3
-
NAMESPACE
is in both source and installed versions, and format remains unchanged. - 4
-
R code in the
R/
directory is byte-compiled for improved performance, stored in.rdb
and.rdx
files.
- 5
-
Datasets in the
data/
directory are serialized into a lazyload database and stored as.rdb
and.rdx
files in theR/
directory.
- 6
-
The
extdata/
folder is in both source and installed versions, and themovies.fst
file remains unchanged.
- 7
-
.Rd
files are processed into binary help files
- 8
- HTML and styling for help index
Very few of the source folders and files weβve been working with remain in the installed version of our package. An exception is the movies.fst
file (stored in inst/extdata/
). Hopefully seeing these two folder trees side-by-side demystifies what devtools::install()
does.
When we want to add non-R package files to our app (like the shiny.png
logo), we store these files in the inst/
folder and access them with system.file()
.3
βThe contents of the
inst/
subdirectory will be copied recursively to the installation directory. Subdirectories ofinst/
should not interfere with those used by R (currently,R/
,data/
,demo/
,exec/
,libs/
,man/
,help/
,html/
andMeta/
, and earlier versions usedlatex/
,R-ex/
).β - Writing R extensions, Package subdirectories
9.1 Image files
To include the contents of www/
in our app-package, weβll need to move www/
into inst/
, and then access its contents with system.file()
.4
9.1.1 system.file()
We used system.file()
in the Data chapter (see Section 7.1.3) to access the movies.fst
file in inst/extdata/
. system.file()
gives us access to the package files on installation (i.e., the files we saw in the folder tree above).
system.file() is accessing movies.fst from the installed location
::read_fst(
fstpath = system.file("extdata/", "movies.fst",
package = "sap")
)
In essence, movies.fst
has βsourceβ package and βinstalledβ locations.
Source package files
inst/
βββ extdata/
βββ movies.fst
- 1
- What we see
Installed package files
βββ extdata/
βββ movies.fst
- 1
- What R sees
9.1.2 addResourcePath()
The addResourcePath()
function will add a βdirectory of static resources to Shinyβs web server.β5 In sap
, we want to add the www
directory, which includes the shiny.png
file.
Current www
location
βββ inst
β βββ extdata
β βββ movies.fst
βββ www
βββ shiny.png
New www
location
inst/
βββ extdata/
β βββ movies.fst
βββ www/
βββ shiny.png
In R/movies_ui.R
, weβll include the addResourcePath()
at the top of the tagList()
and reference the image in img()
using only the subfolder in the path:
show/hide movies_ui()
<- function() {
movies_ui addResourcePath(
prefix = "www",
directoryPath = system.file("www", package = "sap")
)tagList(
::page_fillable(
bslibh1("Movie Reviews"),
::layout_sidebar(
bslibsidebar =
::sidebar(
bslibtitle = tags$h4("Sidebar inputs"),
img(
src = "www/shiny.png",
height = 60,
width = 55,
style = "margin:10px 10px"
),mod_var_input_ui("vars")
),::card(
bslibfull_screen = TRUE,
::card_header(
bslib$h4("Scatter Plot")
tags
),mod_scatter_display_ui("plot"),
::card_footer(
bslib$blockquote(
tags$em(
tags$p(
tags"The data for this application comes from the ",
$a("Building web applications with Shiny",
tagshref = "https://rstudio-education.github.io/shiny-course/"
),"tutorial"
)
)
)
)
)
)
)
) }
- 1
-
Prefix (or folder name) of installed location
- 2
-
Path to installed package files
- 3
- Reference to installed package image file
The application includes the image file after loading, documenting, and installing our package:
Ctrl/Cmd + Shift + L
Ctrl/Cmd + Shift + D
Ctrl/Cmd + Shift + B
library(sap)
launch_app(run = 'p')
We can also use inst/
to store alternate image files and configure the UI to display a different layout. This method ensures our app has the exact same functionality, but a different UI layout.6
The updated movies_ui()
function below has an optional bslib
argument that will change the layout an display an alternate image (stored in inst/www/bootstrap.png
).
show/hide updated movies_ui()
#' User Interface for the Movies Review Application
#'
#' Creates the user interface (UI) for the Movies Review application, which
#' allows users to create customizable scatter plots based on movie data.
#'
#' @param bslib View bslib logo?
#'
#' @return A Shiny `tagList` object containing the UI elements.
#'
#' @section Details:
#' The interface is built using [`bslib`](https://rstudio.github.io/bslib/)
#' - **Page (fillable)**: [`bslib::page_fillable()`](https://rstudio.github.io/bslib/reference/page_fillable.html)
#' displays the app title.
#' - **Sidebar**: [`bslib::layout_sidebar()`](https://rstudio.github.io/bslib/reference/sidebar.html)
#' includes a logo and the variable
#' selection module.
#' ([`mod_var_input_ui`]).
#' - **Card**: [`bslib::card()`](https://rstudio.github.io/bslib/reference/card.html)
#' displays the scatter plot module
#' ([`mod_scatter_display_ui`]).
#'
#' @seealso
#' - [`movies_server()`] for the server logic of the app.
#' - [`mod_var_input_ui()`] and [`mod_scatter_display_ui()`] for the modules
#' included in the UI.
#'
#' @family **Application Components**
#'
#' @examples
#' if (interactive()) {
#' shiny::shinyApp(ui = movies_ui(), server = movies_server)
#' }
#'
#' @export
<- function(bslib = FALSE) {
movies_ui addResourcePath(
prefix = 'www',
directoryPath = system.file('www', package = 'sap'))
if (isFALSE(bslib)) {
tagList(
::page_fillable(
bslibh1("Movie Reviews"),
::layout_sidebar(
bslibsidebar =
::sidebar(
bslibtitle = tags$h4("Sidebar inputs"),
img(
src = "www/shiny.png",
height = 60,
width = 55,
style = "margin:10px 10px"
),mod_var_input_ui("vars")
),::card(
bslibfull_screen = TRUE,
::card_header(
bslib$h4("Scatter Plot")
tags
),::card_body(fillable = TRUE,
bslibmod_scatter_display_ui("plot")
),::card_footer(
bslib$blockquote(
tags$em(
tags$p(
tags"The data for this application comes from the ",
$a("Building web applications with Shiny",
tagshref = "https://rstudio-education.github.io/shiny-course/"
),"tutorial"
)
)
)
)
)
)
)
)else {
} tagList(
::page_fillable(
bslibtitle = "Movie Reviews (bslib)",
theme = bslib::bs_theme(
bg = "#101010",
fg = "#F6F5F5",
primary = "#EE6F57",
secondary = "#32E0C4",
success = "#FF4B5C",
base_font = sass::font_google("Ubuntu"),
heading_font = sass::font_google("Ubuntu")
),::layout_sidebar(
bslibsidebar = bslib::sidebar(
open = TRUE,
mod_var_input_ui("vars")
),::card(
bslibfull_screen = TRUE,
::card_header(
bslibimg(src = "www/bootstrap.png",
height = 80,
width = 100,
style = "margin:10px 10px")
),::card_body(fillable = TRUE,
bslibmod_scatter_display_ui("plot")
)
)
)
)
)
} }
- 1
-
Include
inst/www
resources
- 2
-
Original
bslib
layout
- 3
-
New
bslib
layout
- 4
-
Reference to alternate image (in
inst/www/bootstrap.png
)
The new bslib
argument in our updated moves_ui()
function toggles between the two UI options. We should also add an app
argument to launch_app()
to handle the two UI options:
show/hide updated launch_app()
#' Movies app standalone function
#'
#' Wrapper function for `shinyApp()`
#'
#' @param app which app to run. Options are:
#' * `NULL` = the default app (`"movies"`)
#' * `"bslib"` = Alternative `bslib` layout
#' @param options arguments to pass to `options()`
#' @param run where to launch app:
#' * `p` = launch in viewer pane
#' * `b` = launch in external browser
#' * `w` = launch in window
#' @param ... arguments passed to UI
#'
#' @return shiny app
#'
#' @seealso [mod_var_input_ui()], [mod_var_input_server()], [mod_scatter_display_ui()], [mod_scatter_display_server()]
#'
#'
#' @export
#'
#' @import shiny
#'
<- function(app = NULL, options = list(), run = "p", ...) {
launch_app
if (interactive()) {
display_type(run = run)
}
if (is.null(app)) {
<- "movies"
app
}
if (app == "bslib") {
shinyApp(
ui = movies_ui(bslib = TRUE),
server = movies_server,
options = options
)else {
} shinyApp(
ui = movies_ui(...),
server = movies_server,
options = options
)
} }
Now we can load, document, and build the package and confirm app = "bslib"
works:
Ctrl/Cmd + Shift + L
Ctrl/Cmd + Shift + D
Ctrl/Cmd + Shift + B
launch_app(app = 'bslib')
This alternate version of launch_app()
uses the same modules and utility functions as the previous versions but when app = "bslib"
, the app displays the alternate UI layout:
The inst/
folder is a versatile tool for storing various files needed in our application (logos or images, CSS styling, JavaScript functions, HTML, etc.). The example above was simple, but using inst/
to hold resources for alternate UIs that can be displayed with a single argument is handy for demoing versions for stakeholders.
9.2 Data files
It is not uncommon to develop an application that can handle data from multiple sources. In these situations, we can sometimes store the alternative data files in the inst/
folder.7
9.2.1 A tidy-movies
app
Weβll create an alternative application in sap
that uses a tidy version of the ggplot2movies
data, which we create using a function stored in the data-raw/tidy_movies.R
file.8
We can place the application modules, UI, and server functions in inst/tidy-movies/R
:
inst/tidy-movies/
βββ R
β βββ devServer.R
β βββ devUI.R #
β βββ dev_mod_scatter.R
β βββ dev_mod_vars.R
βββ app.R
βββ imdb.png
βββ tidy_movies.fst
2 directories, 7 files
- 1
-
Tidy movies app folder
- 2
-
App ui, server, and modules
- 3
-
Launch
tidy-movies
app - 4
-
Alternate image/logo
- 5
- Alternate data
All of the functions from sap
are available in the tidy-movies/
app with explicit namespacing (i.e., sap::fun()
):
dev_mod_vars_ui()
contains choices for the columns in thetidy_movies
data, but thereβs no need to rewrite themod_var_input_server()
function.9The
dev_mode_scatter
module functions have been rewritten to add functionality for importing thetidy_movies.fst
data file and an option to removing missing values from the graph.inst/tidy-data/app.R
contains a call toshinyApp()
and any other packages weβll need to launch the application. The data and alternative image file can be placed in the root folder (with theapp.R
file):
%%{init: {'theme': 'neutral', 'themeVariables': { 'fontFamily': 'monospace', "fontSize":"16px"}}}%% flowchart LR subgraph R["<strong>R/ folder</strong>"] subgraph launch["launch_app('ggp2')"] display_type["display_type()"] end mod_var_input_server["mod_var_input_server()"] scatter_plot["scatter_plot()"] end subgraph tidy_movies["<strong>tidy-movies/ folder</strong>"] subgraph app["app.R file"] subgraph SubR["<strong>R/ folder</strong>"] devServer["devServer()"] dev_mod_scatter_server["dev_mod_scatter_server()"] devServer -.->|"<em>Calls</em>"|dev_mod_scatter_server devUI["devUI()"] dev_mod_vars_ui["dev_mod_vars_ui()"] dev_mod_scatter_ui["dev_mod_scatter_ui()"] devUI -.->|"<em>Calls</em>"|dev_mod_vars_ui & dev_mod_scatter_ui end end data[("tidy_movies.fst")] img[/"imdb.png"\] end launch ==> |"<strong><code>shinyAppDir()</code></strong>"|app scatter_plot -.->|"<em>Called from</em>"|dev_mod_scatter_server mod_var_input_server -.->|"<em>Called from</em>"|devServer %% utility functions style scatter_plot fill:#595959,color:#FFF,stroke:#333,stroke-width:1px,rx:25,ry:25 style display_type fill:#595959,color:#FFF,stroke:#333,stroke-width:1px,rx:25,ry:25 %% tidy-movies/ style tidy_movies fill:#e8f0f5,stroke:#333,stroke-width:1px,rx:3,ry:3 %% tidy-movies/R style SubR fill:#f7fafb,stroke:#333,stroke-width:1px,rx:3,ry:3 %% tidy-movies/R/ files style devUI stroke:#333,stroke-width:1px,rx:6,ry:6 style devServer stroke:#333,stroke-width:1px,rx:6,ry:6 style dev_mod_scatter_server color:#000,fill:#f5f5f5,stroke:#333,stroke-width:1px,rx:12,ry:12 style dev_mod_scatter_ui color:#000,fill:#f5f5f5,stroke:#333,stroke-width:1px,rx:12,ry:12 style dev_mod_vars_ui color:#000,fill:#f5f5f5,stroke:#333,stroke-width:1px,rx:12,ry:12 %% files style app fill:#f8f6e7,color:#000 style data fill:#f8f6e7,color:#000 style img fill:#f8f6e7,color:#000
inst/tidy-movies/
folder9.2.2 Launching tidy-movies
Finally, weβll launch the tidy_movies
data app with the app
argument in our standalone function. This conditional argument is similar to the app = "bslib"
option, but we use shinyAppDir()
to launch the app stored in inst/tidy-movies
(which we locate with system.file()
).
show/hide R/launch_app.R
#' Launch the Movies Review Application
#'
#' Starts the Movies Review Shiny application, which provides a customizable
#' scatter plot interface for analyzing movie data.
#'
#' @param app which app to run. Options are:
#' * `NULL` = the default app (`"movies"`)
#' * `"bslib"` = Alternative `bslib` layout
#' * `"ggp2"` = `ggplot2movies` (tidy) data app.
#' @param options arguments to pass to `options()`
#' @param run where to launch app:
#' * `p` = launch in viewer pane
#' * `b` = launch in external browser
#' * `w` = launch in window
#' @param ... arguments passed to UI
#'
#' @return A **Shiny application** object.
#'
#' @section Details:
#' The application uses:
#' - **UI**: Defined in [`movies_ui()`].
#' - **Server Logic**: Defined in [`movies_server()`].
#'
#' @seealso
#' - [`movies_ui()`] for the user interface.
#' - [`movies_server()`] for the server logic.
#'
#' @family **Standalone Application**
#'
#' @details
#' See the [ggplot2movies](https://github.com/hadley/ggplot2movies) package.
#'
#'
#' @examples
#' if (interactive()) {
#' launch_app()
#' }
#'
#' @export
#'
#' @import shiny
#'
<- function(app = NULL, options = list(), run = "p", ...) {
launch_app
if (interactive()) {
display_type(run = run)
}
if (is.null(app)) {
<- "movies"
app
}
if (app == "bslib") {
shinyApp(
ui = movies_ui(bslib = TRUE),
server = movies_server,
options = options
)else if (app == "ggp2") {
} shinyAppDir(
appDir = system.file("tidy-movies",
package = "sap"
),options = options
)else {
} shinyApp(
ui = movies_ui(...),
server = movies_server,
options = options
)
} }
After loading, documenting, and installing, weβll run the tidy ggplot2movies::movies
data app:
Ctrl/Cmd + Shift + L
Ctrl/Cmd + Shift + D
Ctrl/Cmd + Shift + B
launch_app(app = 'ggp2')
9.3 Quarto apps
Shiny apps can also be built inside Quarto documents, in which case we could also use the inst/
folder to store and load resources (images, CSS, etc.).
The inst/quarto/
folder contains a Quarto version of our movies app:
inst/quarto
βββ _quarto.yml
βββ index.qmd
βββ www
βββ quarto.png
βββ styles.scss
1 directory, 4 files
The _quarto.yml
file contains project metadata for the app10, and the www/
folder contains an image file and a CSS file.
title: "Quarto Movies App"
format:
html:
embed-resources: true
9.3.1 Shiny documents
In index.qmd
, we can specify server: shiny
in the YAML header to let Quarto know we want the document to be interactive:
---
title: Quarto Movies App
format:
html:
page-layout: full
embed-resources: true
theme:
- united
- www/styles.scss
server: shiny
---
The other options weβve included in our YAML header are page-layout
(for customizing the layout of each element), embed-resources
(to create a standalone HTML document), and theme
(weβre using a Bootstrap 5 theme with custom CSS).
To set up our Quarto/Shiny app, we should include a code chunk with context: setup
near the top of the document. We can use the image files in inst/quarto/www
by adding a call to addResourcePath()
in the setup
chunk:
```{r}
#| context: setup
library(sap)
library(thematic)
library(ragg)
addResourcePath(
prefix = 'quarto',
directoryPath = system.file('www', package = 'sap'))
options(shiny.useragg = TRUE)
thematic::thematic_set_theme(
theme = thematic::thematic_theme(
bg = "#070d35",
fg = "#FFFFFF",
sequential = NA,
accent = "#2ee3a4")) ```
- 1
- setup for HTML document
- 2
- packages (including our app-package)
- 3
- resources (including CSS)
- 4
- options (for images)
- 5
- theme from thematic
Note the context: setup
chunk includes options and themes (Iβm using the thematic
package to set a theme for the ggplot2
graph in our app).
Using page-layout: full
in the YAML header lets us use a variety of panel
options for each code chunk. For example, weβll place the variable input module in a code chunk with the input
option,11 the display module with the center
option,12 and the data/Quarto attribution in the fill
option.13
```{r}
#| panel: input
mod_var_input_ui("vars")
```
```{r}
#| panel: center
mod_scatter_display_ui("plot")
```
```{r}
#| panel: fill
tags$br()
tags$em(
"Built using ",
tags$a(
img(
src = "www/quarto.png",
height = 25,
width = 90,
style = "margin:10px 10px"
),
href = "https://quarto.org/docs/interactive/shiny/"
),
"and data from the ",
tags$a("Building web applications with Shiny",
href = "https://rstudio-education.github.io/shiny-course/"),
"tutorial."
) ```
- 1
-
Horizontal input panel
- 2
-
Center the graph display
- 3
- Data/Quarto attribute with hyperlinks across bottom of app
The context: setup
and panel
option code chunks will execute when the document is rendered. However, any code chunk with context: server
will execute when the document is served (not when it is rendered).14
```{r}
#| context: server
selected_vars <- mod_var_input_server("vars")
mod_scatter_display_server("plot", var_inputs = selected_vars)
```
These chunks are run in separate R sessions, meaning we cannot access variables created in the first chunk within the second and vice versa (similar to to the movies_ui()
, and movies_server.R()
).
To render our Quarto Shiny app, we can use the Run Document/Preview button or running the following commands in the Terminal:
quarto serve /<path>/<to>/sap/inst/quarto/index.qmd
We can also launch the quarto app using the following R commands:
::quarto_preview(
quartofile = system.file("quarto", "index.qmd",
package = "sap"),
render = "all",
browse = utils::browseURL,
watch = TRUE
)
9.3.2 Launching inst/quarto
To launch our Quarto application from inst/quarto
, weβll change the app
argument again in launch_app()
:
show/hide launch_app()
#' Launch the Movies Review Application
#'
#' Starts the Movies Review Shiny application, which provides a customizable
#' scatter plot interface for analyzing movie data.
#'
#' @param app which app to run. Options are:
#' * `NULL` = the default app (`"movies"`)
#' * `"bslib"` = Alternative `bslib` layout
#' * `"ggp2"` = `ggplot2movies` (tidy) data app.
#' * `"quarto"` = Quarto movies app.
#' @param options arguments to pass to `options()`
#' @param run where to launch app:
#' * `p` = launch in viewer pane
#' * `b` = launch in external browser
#' * `w` = launch in window
#' @param ... arguments passed to UI
#'
#' @return A **Shiny application** object.
#'
#' @section Details:
#' The application uses:
#' - **UI**: Defined in [`movies_ui()`].
#' - **Server Logic**: Defined in [`movies_server()`].
#'
#' @seealso
#' - [`movies_ui()`] for the user interface.
#' - [`movies_server()`] for the server logic.
#'
#' @family **Standalone Application**
#'
#' @details
#' See the [ggplot2movies](https://github.com/hadley/ggplot2movies) package.
#'
#'
#' @examples
#' if (interactive()) {
#' launch_app()
#' }
#'
#' @export
#'
#' @import shiny
#'
<- function(app, options = list(), run = "p", ...) {
launch_app
if (interactive()) {
display_type(run = run)
}
if (is.null(app)) {
<- "movies"
app
}
if (app == "bslib") {
shinyApp(
ui = movies_ui(bslib = TRUE),
server = movies_server,
options = options
)else if (app == "ggp2") {
} shinyAppDir(
appDir = system.file("tidy-movies",
package = "sap"
),options = options
)else if (app == "quarto") {
} ::quarto_preview(
quartosystem.file("quarto", "index.qmd",
package = "sap" ),
render = "all")
else {
} shinyApp(
ui = movies_ui(...),
server = movies_server,
options = options
)
} }
Now we can load, document, and build the package:
Ctrl/Cmd + Shift + L
Ctrl/Cmd + Shift + D
Ctrl/Cmd + Shift + B
Launching the application now just requires a single argument:
launch_app(app = "quarto")
9.4 Production
Finally, itβs also possible to have a folder dedicated for deploying a production version of our application from our app-package. I recommend naming this folder something like inst/prod/
or inst/deploy
, and it can contain a version of your application thatβs βfit for public consumption.β In inst/prod/app
Iβve created an app.R
file:
inst/
βββ prod/
βββ app
βββ app.R
2 directories, 1 file
9.4.1 prod/app/app.R
app.R
includes a call to launch_app()
with the app
and options
arguments:
show/hide prod/app/app.R
library(sap)
launch_app(app = "bslib", options = list(test.mode = FALSE))
Iβll use the "bslib"
version from above to differentiate it from the other applications in sap
.
9.4.2 Deploying inst/prod/
Back in the our app.R
file, weβll use shinyAppDir()
and system.file()
to return the app object from prod/app/app.R
:
show/hide app.R
::with_options(new = list(shiny.autoload.r = FALSE), code = {
withrif (!interactive()) {
sink(stderr(), type = "output")
tryCatch(
expr = {
library(sap)
},error = function(e) {
::load_all()
pkgload
}
)shinyAppDir(appDir = system.file("prod/app", package = "sap"))
else {
} ::load_all()
pkgload
}launch_app(options = list(test.mode = FALSE), run = 'p')
})
- 1
-
Set option to turn off
loadSupport()
- 2
-
Create shiny object from
prod/app
Ctrl/Cmd + Shift + L
Ctrl/Cmd + Shift + D
Ctrl/Cmd + Shift + B
To deploy the app, call rsconnect::deployApp()
in the console and supply an appName
:
::deployApp(appName = 'movie-reviews-prod') rsconnect
The deployment log will look something like this:
ββ Preparing for deployment βββββββββββββββββββββββββββββββββββββββββββββββββ
β Deploying "movie-reviews-prod" using "server: shinyapps.io / username: <username>"
βΉ Creating application on server...
β Created application with id 12711883
βΉ Bundling 39 files: .Rbuildignore, app.R, data/movies.rda, data/movies.RData,
data-raw/tidy_movies.R, DESCRIPTION, inst/tidy-data/app.R, inst/tidy-data/imdb.png,
inst/tidy-data/R/dev_mod_scatter.R, inst/tidy-data/R/dev_mod_vars.R,
inst/tidy-data/R/devServer.R, inst/tidy-data/R/devUI.R,
inst/tidy-data/tidy_movies.fst, inst/extdata/movies.fst, inst/prod/app/app.R,
inst/www/bootstrap.png, inst/www/shiny.png, man/display_type.Rd, β¦,
R/scatter_plot.R, and README.md
βΉ Capturing R dependencies with renv
β Found 69 dependencies
β Created 1,568,327b bundle
βΉ Uploading bundle...
β Uploaded bundle with id 9101312
ββ Deploying to server ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Waiting for task: 1457289827
building: Processing bundle: 9101312
building: Building image: 11074678
building: Fetching packages
building: Installing packages
building: Installing files
building: Pushing image: 11074678
deploying: Starting instances
success: Stopping old instances
ββ Deployment complete βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Successfully deployed to <https://<username>.shinyapps.io/movie-reviews-prod/>
You can see a deployed version of this application here
Recap
Launch app with the shinypak
package:
launch('09_inst')
This chapter had covered how to include external files and resources (i.e., what was previously stored in the www/
folder of a regular Shiny app project) in your app-package with addResourcePath()
and system.file()
.
Weβve also covered how to use the inst/
folder to include alternative files, development and production/deployment versions of your app. You can now launch the following applications from sap
:
Standard application with/without test mode
library(sap)
launch_app(options = list(test.mode = TRUE))
# or
launch_app(options = list(test.mode = FALSE))
inst/bslib
: an application with an alternative layout (with/without test mode)
library(sap)
launch_app(app = "bslib", options = list(test.mode = TRUE))
# or
launch_app(app = "bslib", options = list(test.mode = FALSE))
inst/tidy-data
: an application using a βdevelopmentβ dataset (with/without test mode)
library(sap)
launch_app(app = "ggp2", options = list(test.mode = TRUE))
# or
launch_app(app = "ggp2", options = list(test.mode = FALSE))
inst/prod
: An app.R
file for launching a βproductionβ version of our app.
library(sap)
::deployApp(appName = 'movie-reviews-prod') rsconnect
In the next section, weβre going to cover testing the code in a shiny app-package.
βThe
www/
folder is a special one for Shiny. Resources your app may link to, such as imagesβor in this case, scriptsβare placed in thewww/
folder. Shiny then knows to make these files available for access from the web browser.β - Shiny documentationβ©οΈThis is a common problem developers encounter when converting shiny app into app-packages. See this popular thread on Posit Community.β©οΈ
Read more about sub-directories to avoid in
inst/
in R Packages, 2ed.β©οΈThe key takeaway here is that the
inst/
subfolders and files are available unchanged in the installed version (with theinst/
folder omitted.).β©οΈYou can read more about adding external resources in the documentation for
addResourcePath()
.β©οΈAs the development of your application progresses, you can (and should) keep different versions of your application in separate Git branches. But Iβve also found using the
inst/
folder for those early stages of developing is helpful.β©οΈWe covered external data in Section 7.4.β©οΈ
We covered the
data-raw/
folder in the Data chapter, and you can read more about it here in R packages, 2edβ©οΈThis requires exporting
mod_var_input_server()
with@export
in theR/
folder.β©οΈRead more about the
_quarto.yml
configuration file in the Quarto documentation.β©οΈThis requires exporting
mod_var_input_ui()
with@export
in theR/
folder.β©οΈThis requires exporting
mod_scatter_display_ui()
with@export
in theR/
folder.β©οΈRead more about
page-layout
in the Quarto documentationβ©οΈThis requires exporting
mod_var_input_server()
andmod_scatter_display_server()
with@export
in theR/
folder.β©οΈ