Desktop DeployR

I'm going to be giving a talk this Thursday at my local R/Data Science Meetup about my method for deploying self contained desktop R applications. Since my original post on the subject (over 2 years ago!) I've made many of improvements thanks to the many useful comments I received and my own "dog-fooding".

So many in fact that the framework is a project in its own right, which I'm calling DesktopDeployR. This post will officially document the changes I've made and share the project to the greater R/Data Science community.

If you haven't already, I recommend reading my original post to understand the fundamentals of how such deployments are done.

For the impatient, the TL;DR summary is: on a Windows system, use R-Portable and Windows Scripting Host to launch a Shiny app in a user's default web browser.


  • System and R scripts for app launch are more separated from app specific code. Specifically, the framework's directory structure is now:

     +- app/
     |  +- library/ # <- private app library
     |  +- shiny/   # <- where shiny app files go
     |  +- app.R
     |  +- config.cfg
     |  +- packages.txt
     +- dist/       # <- the core framework
     |  +- R-Portable/
     |  +- script/
     +- log/
     +- appname.bat

    This means you can drop a pre-made Shiny application alongside the launch framework and it should work with minimal effort.

    Being app-agnostic also means that the the framework is not specific to Shiny apps. I have successfully tested it with RGtk and Tcl/Tk based apps as well. It is just a matter of putting the necessary code to start your app in app.R. For a Shiny app, this is simply the following line:

  • App launch is configurable via a JSON config file (shown above in the app/ folder). There are options to configure:

    • the path to an R installation, so that a system one can be specified instead of R-Portable, making the deployed app size smaller (if that's important to you).
    • the CRAN mirror to use for installing package dependencies
    • where error logs are stored - e.g. with the app in the log/ folder or in a user's home directory on the system.
  • Windows Scripting Host scripts are now written in Javascript, because it was a mistake to use VBScript, especially with regards to parsing JSON config files.

  • Primary app package dependencies are specified in a packages.txt file which is used to create a private package library when the app is first launched. This was inspired by requirements.txt files used to install a set of Python packages using pip.

    The private library is added to .libPaths() at launch, so modifying an Rprofile.site file is no longer necessary.

  • Primary app package dependencies are also "ensured", meaning if they change (i.e. new ones are added) they are installed into the private library the next time the app is launched.

  • There is a GUI progress bar displayed during launch that updates as primary package dependencies are loaded. This is useful feedback that the app is actually doing something, especially if there a many dependencies to load.

  • As before, you still need to download the version of R-Portable you need and install it into a template framework that you clone for each deployment. However, Since the app uses a private library for dependencies, the R-Portable install can stay and be launched "vanilla", which makes swapping it out (e.g. for upgrades) much easier.

  • Chrome Portable is no longer part of the framework. It behaved very inconsistently and would generate errors that I hadn't a clue how to debug. The current crop of browsers (IE10+ included) all work well with Shiny. This is also a moot point if you're deploying a non-Shiny app.


Now that the framework is more portable, I can also more easily open source it. If you want to give it a try with your own projects the GitHub repository is here. I'd also appreciate any feedback (or help) to make it better.

Happy DesktopDeployR-ing!