Agent-almanac deploy-shiny-app
git clone https://github.com/pjt222/agent-almanac
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/caveman/skills/deploy-shiny-app" ~/.claude/skills/pjt222-agent-almanac-deploy-shiny-app-42f9d5 && rm -rf "$T"
i18n/caveman/skills/deploy-shiny-app/SKILL.mdDeploy Shiny App
Deploy a Shiny application to shinyapps.io, Posit Connect, or a Docker container.
When to Use
- Publishing a Shiny app for external or internal users
- Moving from local development to a hosted environment
- Containerizing a Shiny app for Kubernetes or Docker deployment
- Setting up automated deployment pipelines
Inputs
- Required: Path to the Shiny application
- Required: Deployment target (shinyapps.io, Posit Connect, or Docker)
- Optional: Account name and token (for shinyapps.io/Connect)
- Optional: Instance size preference
- Optional: Custom domain or URL path
Procedure
Step 1: Prepare the Application
Ensure the app is self-contained and deployable:
# Check for missing dependencies rsconnect::appDependencies("path/to/app") # For golem apps, ensure DESCRIPTION lists all Imports devtools::check() # Verify the app runs cleanly shiny::runApp("path/to/app")
Verify these files exist:
(orapp.R
+ui.R
)server.R
(recommended for reproducible deployments)renv.lock
does NOT call.Rprofile
in productionmcptools::mcp_session()
Expected: App runs locally without errors and all dependencies are captured.
On failure: If
appDependencies() reports missing packages, install them and update renv.lock. If the app uses system libraries (e.g., gdal, curl), note them for the Docker path.
Step 2a: Deploy to shinyapps.io
# One-time account setup rsconnect::setAccountInfo( name = "your-account", token = Sys.getenv("SHINYAPPS_TOKEN"), secret = Sys.getenv("SHINYAPPS_SECRET") ) # Deploy rsconnect::deployApp( appDir = "path/to/app", appName = "my-app", appTitle = "My Application", account = "your-account", forceUpdate = TRUE )
Store credentials in
.Renviron (never in code):
# .Renviron SHINYAPPS_TOKEN=your_token_here SHINYAPPS_SECRET=your_secret_here
Expected: App deployed and accessible at
https://your-account.shinyapps.io/my-app/.
On failure: If authentication fails, regenerate tokens at shinyapps.io dashboard > Account > Tokens. If package installation fails on the server, check that all packages are available on CRAN — shinyapps.io cannot install from GitHub by default.
Step 2b: Deploy to Posit Connect
# Register server (one-time) rsconnect::addServer( url = "https://connect.example.com", name = "production" ) # Authenticate (one-time) rsconnect::connectApiUser( account = "your-username", server = "production", apiKey = Sys.getenv("CONNECT_API_KEY") ) # Deploy rsconnect::deployApp( appDir = "path/to/app", appName = "my-app", server = "production", account = "your-username" )
Expected: App deployed and accessible on the Posit Connect instance.
On failure: If the server rejects the connection, verify the API key and server URL. If packages fail to install, check that Connect has access to the required repositories (CRAN, internal CRAN-like repos).
Step 2c: Deploy with Docker
Create a
Dockerfile:
FROM rocker/shiny-verse:4.4.0 # Install system dependencies RUN apt-get update && apt-get install -y \ libcurl4-openssl-dev \ libssl-dev \ libxml2-dev \ && rm -rf /var/lib/apt/lists/* # Install R packages RUN R -e "install.packages(c('shiny', 'bslib', 'DT', 'plotly'))" # Copy app COPY . /srv/shiny-server/myapp/ # Configure Shiny Server COPY shiny-server.conf /etc/shiny-server/shiny-server.conf # Expose port EXPOSE 3838 # Run CMD ["/usr/bin/shiny-server"]
Create
shiny-server.conf:
run_as shiny; server { listen 3838; location / { site_dir /srv/shiny-server/myapp; log_dir /var/log/shiny-server; directory_index on; } }
Build and run:
docker build -t myapp:latest . docker run -p 3838:3838 myapp:latest
Expected: App accessible at
http://localhost:3838.
On failure: If the build fails on package installation, add missing system libraries to the
apt-get install line. If the app doesn't load, check Shiny Server logs: docker exec <container> cat /var/log/shiny-server/*.log.
Step 3: Verify Deployment
# Check the deployed URL responds response <- httr::GET("https://your-app-url/") httr::status_code(response) # Should be 200 # For Docker response <- httr::GET("http://localhost:3838/") httr::status_code(response)
Manual verification checklist:
- App loads without errors
- All interactive elements respond
- Data connections work in the deployed environment
- Authentication/authorization works (if applicable)
Expected: App responds with HTTP 200 and all features work.
On failure: Check server logs for the specific deployment platform. Common issues: environment variables not set in production, database connections using localhost instead of production URLs, or file paths that only exist locally.
Step 4: Configure Monitoring (Optional)
shinyapps.io
Monitor via the dashboard at
https://www.shinyapps.io/admin/#/applications.
Posit Connect
# Check deployment status via API connectapi::connect( server = "https://connect.example.com", api_key = Sys.getenv("CONNECT_API_KEY") )
Docker
Add health check to Dockerfile:
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \ CMD curl -f http://localhost:3838/ || exit 1
Expected: Monitoring configured for the deployment target.
On failure: If health checks fail intermittently, increase timeout values. Shiny apps can be slow to respond during initial load.
Validation
- App deploys without errors
- Deployed URL responds with HTTP 200
- All interactive features work in production
- Environment variables/secrets are configured (not hardcoded)
- Credentials stored in
or CI secrets, not in code.Renviron - renv.lock committed for reproducible dependency resolution
Common Pitfalls
- Hardcoded file paths: Replace absolute paths with
(for package data) or environment variables (for external resources).system.file() - Development-only dependencies: Don't deploy
that loads.Rprofile
ormcptools::mcp_session()
. Use conditional loading or separate profiles.devtools - Missing system libraries in Docker: R packages like sf, curl, and xml2 need system libraries. Add them to the Dockerfile's
.apt-get install - CRAN-only packages on shinyapps.io: shinyapps.io only installs from CRAN by default. GitHub-only packages need the
package and explicit installation in the deployment.remotes - Forgotten environment variables: Database credentials, API keys, and other secrets must be configured in the deployment environment separately from code.
Related Skills
— create app structure before deploymentscaffold-shiny-app
— detailed Docker configuration for R projectscreate-r-dockerfile
— multi-container setups for Shiny with databasessetup-docker-compose
— CI/CD including automated deploymentsetup-github-actions-ci
— performance tuning before deploying to productionoptimize-shiny-performance