Skip to content

Commit 895df2e

Browse files
committed
Add Quarto vignette (WIP)
1 parent 6d75a97 commit 895df2e

File tree

4 files changed

+217
-0
lines changed

4 files changed

+217
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ docs
77
converted_shiny_app*/*
88
*_cache/*
99
converted_shiny_apps.qmd
10+
inst/doc

DESCRIPTION

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,8 @@ License: AGPL (>= 3)
1818
Encoding: UTF-8
1919
Roxygen: list(markdown = TRUE)
2020
RoxygenNote: 7.3.2
21+
Suggests:
22+
knitr,
23+
rmarkdown,
24+
quarto
25+
VignetteBuilder: quarto

vignettes/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.html
2+
*.R

vignettes/behind-the-scenes.qmd

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
---
2+
title: "From Server-side to Browser-based Shiny Apps and Back Again"
3+
subtitle: "Understanding Shiny to Shinylive Conversion and Source Extraction"
4+
author: "James Joseph Balamuta"
5+
vignette: >
6+
%\VignetteIndexEntry{behind-the-scenes}
7+
%\VignetteEngine{quarto::html}
8+
%\VignetteEncoding{UTF-8}
9+
---
10+
11+
[Shinylive][slexplain] represents a paradigm shift in how Shiny applications
12+
are deployed and executed. Instead of running on a **computational** server,
13+
these applications execute entirely within a web browser after being downloaded.
14+
This vignette explores the transformation process from a traditional Shiny
15+
application to a Shinylive application and explains how tools like [`peeky`][peekygh]
16+
can extract the source code from these browser-based applications.
17+
18+
## The Traditional Shiny Model
19+
20+
In a traditional Shiny application:
21+
22+
1. Source code resides on a **computational** server
23+
2. R and/or Python are installed and running on the server
24+
3. Users interact with the app through their browser, which communicates and
25+
processes the interaction on the server.
26+
4. App code remains **private** and **inaccessible** to end users
27+
28+
For example, consider a template for an R Shiny application:
29+
30+
```r
31+
# Traditional Shiny app structure
32+
# app.R or (ui.R/server.R)
33+
library(shiny)
34+
35+
ui <- fluidPage(
36+
# UI elements
37+
)
38+
39+
server <- function(input, output, session) {
40+
# Server logic
41+
}
42+
43+
shinyApp(ui, server)
44+
```
45+
46+
Once deployed, the server executes the application code and sends the results
47+
back to the user's browser. This code is **not** accessible to the user since
48+
it runs on the server's R process.
49+
50+
## The Shinylive Transformation
51+
52+
One of the key features of Shinylive is the ability to convert traditional Shiny
53+
applications to run entirely in the browser. This transformation involves
54+
arguably three key steps: Code Preparation, Conversion Process, and Browser
55+
Deployment.
56+
57+
### Step 1: Code Preparation
58+
59+
The first step in converting to Shinylive involves preparing your Shiny
60+
application code. The core application logic remains largely unchanged, but
61+
there are some key considerations:
62+
63+
- All dependencies must be available in WebAssembly format
64+
- Check if the R package is in the [webR package repository][webrpkg] (mobile intensive)
65+
- See if the Python package is apart of the [built-in Pyodide packages][pyodidepkg] or
66+
has a **pure Python** implementation that can be used directly from PyPI.
67+
- File paths need to be adjusted for browser context
68+
- External resources must be properly bundled
69+
70+
### Step 2: Conversion Process
71+
72+
The conversion to Shinylive is automated by the
73+
74+
1. **File Bundling**: All application files are collected and bundled together:
75+
- R/Python source code
76+
- Data files
77+
- Static assets (images, CSS, etc.)
78+
79+
2. **Metadata Generation**: A `app.json` file is created containing:
80+
```json
81+
[
82+
{
83+
"name": "app.R",
84+
"content": "library(shiny)\n...",
85+
"type": "text"
86+
},
87+
{
88+
"name": "data.csv",
89+
"content": "col1,col2\n...",
90+
"type": "text"
91+
}
92+
]
93+
```
94+
95+
3. **Runtime Preparation**:
96+
- For R: WebR environment is configured
97+
- For Python: Pyodide environment is set up
98+
99+
### Step 3: Browser Deployment
100+
101+
The converted application now runs entirely in the browser:
102+
103+
1. WebR/Pyodide runtime initializes
104+
2. Application files are loaded from `app.json`
105+
3. UI renders and connects to a local runtime
106+
4. All computation happens client-side
107+
108+
## Source Code Transparency
109+
110+
Unlike traditional Shiny applications, Shinylive apps are inherently transparent. This transparency is a fundamental characteristic due to several factors:
111+
112+
1. **Client-Side Execution**: All code must be available in the browser
113+
2. **Bundled Resources**: All files are packaged in accessible formats
114+
3. **No Server Privacy**: No server-side code protection exists
115+
116+
## Extracting Source Code with `peeky`
117+
118+
The `peeky` package leverages this transparency to extract source code from
119+
Shinylive applications. Here's how it works:
120+
121+
### Detection
122+
123+
TODO: Clarify
124+
125+
```r
126+
# URL of the Shinylive application
127+
url <- ""
128+
129+
# Auto-detect and handle both standalone and Quarto-embedded apps
130+
peeky::peek_shinylive_app(url)
131+
```
132+
133+
### Content Retrieval
134+
135+
TODO: Clarify
136+
137+
1. Downloads the webpage or app.json
138+
2. Identifies Shinylive components
139+
3. Extracts embedded code and resources
140+
141+
### File Reconstruction
142+
143+
By default, extracted content is reconstructed into runnable applications that
144+
have the directory structure of a standalone app with all of its components.
145+
If the application is embedded in a Quarto document, the extracted content can
146+
consist of one or more Shiny applications and, thus, is reconstructed into a
147+
into subdirectories, e.g. `app_1`, `app_2`, etc. Or, the content can be
148+
reconstructed into a new Quarto document containing just the applications.
149+
150+
This can be done by specifying the `output_format` argument in
151+
`peek_quarto_shinylive_app()`:
152+
153+
```r
154+
# Extract to directory structure
155+
peeky::peek_quarto_shinylive_app(url, output_format = "app-dir")
156+
157+
# Or create a new Quarto document
158+
peeky::peek_quarto_shinylive_app(url, output_format = "quarto")
159+
```
160+
161+
## Security Implications
162+
163+
This transparency has important implications for developers:
164+
165+
1. **No Code Privacy**: All source code is accessible to users
166+
2. **Data Visibility**: Bundled datasets are accessible
167+
3. **API Keys**: Never include sensitive credentials
168+
4. **Business Logic**: Proprietary algorithms are visible
169+
170+
## Best Practices
171+
172+
When developing Shinylive applications:
173+
174+
1. **Assume Transparency**: Design with the understanding that code is visible
175+
2. **Handle Sensitive Data**: Process sensitive data server-side if needed
176+
3. **License Clearly**: Include clear licensing terms
177+
4. **Consider Hybrid Approaches**: Use traditional Shiny for sensitive components
178+
and offload non-sensitive parts to Shinylive.
179+
180+
## Conclusion
181+
182+
The transformation from traditional Shiny to Shinylive represents a fundamental
183+
shift in how web applications are delivered. While this brings advantages in
184+
deployment and accessibility, it also requires developers to embrace
185+
transparency and adjust their development practices accordingly. Tools like
186+
`peeky` help demonstrate this transparency and can assist in understanding
187+
how Shinylive applications work.
188+
189+
## References
190+
191+
1. [Shinylive overview][slexplain]
192+
2. [webR Documentation][webr]
193+
- [webR Package Repository][webrpkg]
194+
3. [Pyodide Documentation][pyodide]
195+
- [Pyodide built-in packages][pyodidepkg]
196+
4. [Quarto Shinylive Extension][qsl]
197+
5. [Shiny Standalone webR Demo][protoslr]
198+
199+
[quarto]: https://quarto.org
200+
[slexplain]: https://shiny.posit.co/py/docs/shinylive.html
201+
[qsl]: https://github.com/quarto-ext/shinylive
202+
[webr]: https://docs.r-wasm.org/webr/latest/
203+
[webrpkg]: https://repos.r-wasm.org
204+
[pyodide]: https://pyodide.org/en/stable/
205+
[pyodidepkg]: https://pyodide.org/en/stable/usage/packages-in-pyodide.html
206+
[peeksl]: https://github.com/coatless-tutorials/peeking-at-an-r-shinylive-app-source-code
207+
[wasm]: https://webassembly.org/
208+
[peekygh]: https://github.com/coatless-rpkg/peeky
209+
[protoslr]: https://github.com/georgestagg/shiny-standalone-webr-demo

0 commit comments

Comments
 (0)