Changelog
Source:NEWS.md
shinyelectron (development version)
Breaking changes
shinyelectron now requires R 4.5.0 or newer, since it verifies downloaded runtimes with
tools::sha256sum(), which was added in R 4.5.0. The README andsitrep_electron_system()now report this minimum. Apps built with thesystemstrategy still accept R 4.4.0 or newer on the end user’s machine.Installer and artifact file names change. They now come from the slug and always include the architecture, as in
my-app-1.0.0-arm64.dmg,my-app-Setup-1.0.0-x64.exe, andmy-app-1.0.0-x86_64.AppImage, so building several architectures into onedist/no longer overwrites installers. Update release scripts that look for the old names.The installed app now carries the display name instead of the slug: the macOS app bundle and App menu, the Windows Start Menu shortcut and Apps & Features entry, and the installer window.
export()now also takes the display name fromapp.namein_shinyelectron.ymlwhen noapp_nameis given, as documented, instead of from the directory name. The slug, which is the app’s identity, keeps coming fromapp.slug, then theapp_nameargument, then the directory name, so installed copies keep updating. The Windows executable keeps the slug as well, and updates reuse the existing install folder, so pinned shortcuts and existing installs carry over. On macOS, reinstalling from the disk image leaves the old<slug>.appin Applications to delete by hand.export()now builds forbuild.platformsandbuild.architecturesin_shinyelectron.ymlwhen itsplatformandarcharguments are not given, for single apps and multi-app suites alike. Each argument overrides only its own list. Before, the lists had no effect: the build, the choice of icon, and the signing and Windows installer checks all used the current machine. Check the lists in your configuration files. Earlier versions ofwizard()suggestedmacand wrote it tobuild.platforms, so a file written with them on Windows or Linux may listplatforms: mac; change or removeplatformsthere.wizard()now leavesplatformsout unless you name some, so each build targets the machine it runs on. If you copied the Getting Started or Configuration Guide example that pairedruntime_strategy: "bundled"withplatforms: [mac, win], removeplatforms, since abundledorauto-downloadbuild stops when the targets name more than one platform or architecture. A list with no valid value means the current platform or architecture, and a value listed twice is built once.export()now checks the targets before converting anything. It stops when a target ismacand the build machine is not a Mac: macOS apps build only on macOS, and such an export used to report success without making an installer. Abundledorauto-downloadbuild for more than one target now stops before any files are copied, and an invalidplatformorarchargument stops the export even withbuild = FALSE.app_check()reports these problems too, andwizard()asks for a single platform when you choose thebundledorauto-downloadstrategy.
New features
New
lifecycle.startup_timeoutsets how long, in milliseconds, an app waits for its R, Python, or container server to start (default 180000, three minutes). R and Python apps used to give up after 60 seconds and container apps after 120. This timeout andlifecycle.shutdown_timeoutmust be whole numbers from 1000 to 2147483647; any other value warns and falls back to the default. Before, ashutdown_timeoutsuch as"10s"built an app that could not launch.installer.allow_to_change_installation_directory: trueadds a page to the Windows setup wizard where users choose the installation folder. It requiresinstaller.one_click: false; otherwise reading the configuration fails with an error.installer.per_machine: trueinstalls the Windows app for all users. Every install and update then needs administrator rights.Bundled R builds now leave out files that a running app does not use: the test suites (
tests/,testme/,tinytest/) of every embedded package, and the portable R’s own regression tests, PDF and HTML manuals, and news and FAQ files. Package examples, demos, NEWS files, and headers are kept, as are R’s license notices. Pruning is on by default; setdependencies.r.prune: falsein_shinyelectron.ymlto ship the runtime unchanged. A quoted"true"or"false"is read with a warning, and any other value stops the build before anything is downloaded.dependencies.r.local_packagesinstalls R packages that are not on a repository, such as in-house packages, into the R library of abundledbuild. List package source folders or.tar.gzsource tarballs relative to the app directory. Each package is built and installed with the bundled R after its dependencies, and the build stops unless it loads.New
app.description,app.author,app.homepage, andapp.copyrightsettings describe the app. They fill the generatedpackage.jsonand the installer metadata, and Help > About shows them, with buttons to visit the homepage or email the author.app.authortakes an npm-style"Name <email> (url)"string or a map withname,email, andurl, andapp.homepagemust be anhttp://orhttps://URL. On macOS, the App menu’s About panel shows the same name, version, copyright, description, and author. Straight double quotes in the app name, author, and copyright become typographic quotes in the installer metadata, and a$in the app name, description, author, or copyright, which the Windows installer cannot hold, stops a Windows build.With auto-updates enabled, Help > About offers Check for Updates on Windows and Linux. It reports that the app is up to date, offers to download a newer version, or explains why the check failed.
export()shows the app’s slug next to its display name and says whenapp.slugcould choose another.init_config()andwizard()write the slug into the new configuration, andinit_config()warns when a configuration it replaces gave a different slug.
Minor improvements and fixes
shinyelectron now imports rlang. cli builds
cli_abort()andcli_warn()on rlang but only suggests it. Without rlang installed, errors fromcli_abort()showed “there is no package called ‘rlang’” instead of their own message, and warnings fromcli_warn()became that same error, stopping operations meant to continue, such as a Node.js install whose checksum list could not be downloaded.The situation reports (
sitrep_shinyelectron()and friends) no longer report Node.js, npm or Python as missing when the withr package is not installed. withr is only a suggested dependency, and the probe used to fail without it.The Security Considerations guide gains a “Secrets and per-user credentials” section. It covers which environment variables and
.Renvironfiles reach an app’s R, Python, or container process, and how to give each user their own token without bundling it.Keys in
_shinyelectron.ymlthat shinyelectron does not recognize, such as a misspelledwidhtor a key placed in the wrong section, now trigger a warning of classshinyelectron_unknown_config_keythat names each one by its dotted path (for examplewindow.widht). They were previously ignored without notice.The top-level
loggingsection documented in the Configuration Guide now takes effect; itslog_dirandlog_levelwere previously ignored. If you copied the guide’s earlier example, drop itslog_dir: "/var/log/my-app"line:log_dirshould be an absolute path that the app’s user can write to, and without it logs go to the app’suserData/logsfolder.app.log_dirandapp.log_levelstill work. When both set a key to different values,loggingwins with a warning of classshinyelectron_logging_conflict.init_config()now suggests theloggingform.init_config()no longer suggestsnodejs.auto_install, which has no effect yet.App names and other settings that contain quotes or backslashes no longer break the generated app. Settings placed in JavaScript strings in
main.jsor in the splash and preloader page are now escaped, so a name like “Children’s Dashboard” or a Windowslog_dirsuch asC:\Users\me\logsworks, and the About and quit dialogs and the tray tooltip show&instead of&.App names and descriptions in a multi-app suite that contain
<!--followed by<script>no longer break the launcher page.Help > Documentation opens help URLs with query strings correctly instead of turning
&into&.Help > Documentation appears only when
menu.help_urlis set, instead of in every app with a link that opened nothing.R and Python apps whose UI takes several seconds to render no longer fail to start. The startup check used to request the app’s page, which ran the UI code on every attempt; it now requests a path the app does not serve, so the UI is rendered once, when the window loads it.
When an app does not start in time, only its own R or Python process or container is stopped, and the error screen stays up with its Retry and Quit buttons. For a container, the error names the container and its details show the container’s logs. Going back to the launcher while an app is still starting no longer leaves that start running, where it could later stop the next app’s process or container or replace the window with the abandoned app, and switching between container apps no longer shows the previous container’s shutdown messages.
An R or Python app killed by a signal while starting (a segfault, or the system running out of memory), or one that exits before its server answers, now shows the error at once instead of after the startup timeout.
Restarting to install a downloaded update now stops the app’s R or Python process (or its container) and waits for it to exit before the installer runs. If the update cannot be installed, a dialog asks you to restart the app. Pressing Esc in the Update Ready dialog now means Later.
Signed builds no longer fail when
_shinyelectron.ymlsetssigning.win.certificate_file. The certificate settings were written where electron-builder 26 no longer accepts them, so its configuration check stopped the build for every platform, macOS and Linux included. They now go underwin.signtoolOptions, where electron-builder 26 reads them. The certificate password still comes fromCSC_KEY_PASSWORDand is never written topackage.json.The Windows credential checks in
export()andapp_check()now follow electron-builder’s lookup order: the certificate fromsigning.win.certificate_file, thenWIN_CSC_LINK, thenCSC_LINK, and the password fromWIN_CSC_KEY_PASSWORD, thenCSC_KEY_PASSWORD. Setting only theWIN_CSC_*variables no longer draws a misleading warning, and aWIN_CSC_*variable that is set but empty now warns, because electron-builder stops there instead of falling back toCSC_*.A signed build now passes
signing.mac.team_idto electron-builder asAPPLE_TEAM_ID, the only place electron-builder reads the notarization team ID. Before, when the team ID was set only in_shinyelectron.yml, builds that notarize with an Apple ID failed with “APPLE_TEAM_ID env var needs to be set”. A team ID already set inAPPLE_TEAM_IDstill wins.export(sign = TRUE)andapp_check(sign = TRUE)now check the signing credentials even whensigning.signis off in_shinyelectron.yml. The macOS checks also follow electron-builder: an App Store Connect API key (APPLE_API_KEY,APPLE_API_KEY_ID,APPLE_API_ISSUER) orAPPLE_KEYCHAIN_PROFILEcounts as notarization credentials, a missing team ID is reported only when notarizing with an Apple ID, and each warning says whether notarization will fail or be skipped.Bundled R builds now install packages with the portable R’s own startup files. The install no longer runs a project
.Rprofileor.Renvironfrom the working directory, such as renv’s autoloader, and ignoresR_ENVIRONandR_PROFILEset for the calling R. A site profile chosen that way skipped the portable R’s macOS library fix-up, so installed binary packages could crash when loaded.~/.Renvironand~/.Rprofilestill apply.Python dependencies are now read in full from
pyproject.toml. In adependencieslist that spanned several lines, a]inside an entry, such as the extras in"uvicorn[standard]>=0.30", or in a comment ended the list, so the packages after it were not installed. Single-quoted entries are now read, commented-out entries are skipped, and only thedependenciesof the[project]table are used, so development tools listed in other tables, such as Hatch’s[tool.hatch.envs.*]environments, are no longer installed with the app. Apyproject.tomlwith no packages in that list now draws a warning.Python packages listed with the version in parentheses, as in
"shiny (>=1.0)", are now read asshinyfrompyproject.tomlandrequirements.txt. Poetry 2 writespyproject.tomlentries this way. They were read asshiny (, which pip rejects, so none of the app’s Python packages were installed.installer.one_click,installer.allow_to_change_installation_directory, andinstaller.per_machineare checked when the configuration is read. A quoted"true"or"false"(or"yes"or"no") is read as the matching value with a warning; any other value that is nottrueorfalsestops the build with an error that names the key.installer.license_fileno longer fails every build with electron-builder’s “unknown property ‘license’” error. The file is resolved relative to the app directory, copied into the build, and shown as the Windows installer’s license page. A UTF-8 text license gets a byte order mark in the copy so the installer shows characters such as the copyright sign correctly.app_check()now fails on configuration errors that stopexport()instead of listing them as warnings, and it checks thatinstaller.license_fileexists.Paths in
_shinyelectron.ymlare now resolved against the app directory (the suite root for a multi-app suite) as documented, not the working directory, soexport()finds them from anywhere. This coversicon,icons,splash.image,tray.icon,signing.win.certificate_file, and thepathandiconof eachappsentry; launcher icons are now copied into the build so the launcher can show them.~and absolute paths work. Theiconargument ofexport()stays relative to the working directory.The app icon now reaches every platform that can use it. The generated
package.jsonpointed Windows, macOS, and Linux atassets/icon.ico,assets/icon.icns, andassets/icon.png, but the build copies only the icon’s own file, so a platform whose file was missing quietly got the default Electron icon: a PNG icon, as the documentation recommends, reached Linux only, and an.icnsicon never reached Windows. Every platform now uses the copied file, which electron-builder converts from a PNG or.icnsicon as needed. An.icoicon serves Windows only. electron-builder also stops the build when the image is too small: a PNG needs at least 512x512 pixels for macOS and 256x256 for Windows, and Windows needs a 256x256 image in an.icnsor.icofile. A platform that cannot use the icon, because of its format or its size, now gets the default icon instead, andexport()names it in a warning before anything is built;app_check()reports it too. Atray.iconfile named like the copy, such asicon.png, is now copied under another name instead of replacing it.export()andapp_check()now warn about theiconsentries that an export leaves out. One export gives one app icon, theiconsentry for its first target platform, to every platform, so a different entry for another target platform is not used. Export each platform separately to give it its own icon.A configured splash image, tray icon, or launcher icon that does not exist now gives a warning naming the key and the path checked, instead of being skipped silently, and the build uses the default. A missing configured app icon stops
export(), as a missingiconargument does, and a missingsigning.win.certificate_filewarns when a Windows build is signed.app_check()checks these files the same way and reports a missing icon as an error.The system tray icon is no longer blank when
tray.iconis not set and the app icon is not a PNG. The tray looked for anicon.pngthat only a PNG app icon provides; it now loads the app icon itself, such as an.icofile on Windows. Where Electron cannot read the file (an.icnsfile, or an.icofile on macOS or Linux), or when no icon is set, the tray shows a built-in icon of a window outline instead.export()warns about a tray icon that a target platform cannot read, with a warning of classshinyelectron_tray_icon_unsupportedthat suggests settingtray.iconto a PNG.With
updates.auto_downloadon, the update notification now says the new version is downloading, instead of asking the user to click to download.An
app_namewith no ASCII letters or digits, such as one written only in Chinese characters, no longer stopsexport()late in the build; the slug comes from the directory name instead. When no slug can be derived, orapp.slugis invalid,export()now stops before converting the app, andshow_config()no longer fails on a non-ASCIIapp.name.export(),build_electron_app(),init_config(), andshow_config()now name the app after its folder when the app directory is a relative path such as"."or"..". The app was named"."or"..", andexport()andbuild_electron_app()stopped because they could not derive an app slug. Whenappdiris the path of a symbolic link,app_check(),init_config(), andwizard()now take the slug from the link’s name, asexport()does, instead of from the folder it points to.app_check()also uses the link’s name in its report, andwizard()offers it as the default app name.
shinyelectron 0.2.1
CRAN release: 2026-08-07
Examples for functions that install a runtime, launch an app, or clear the cache now run only in interactive sessions.
The Download Prebuilt Demos guide moved from a bundled vignette to the package website, and outdated external documentation links were refreshed.
wizard()now requires theappdirargument instead of defaulting to the working directory.
shinyelectron 0.2.0
This release grows shinyelectron from an R shinylive exporter into a general Shiny-to-desktop toolkit, adding Python apps, five runtime strategies, and multi-app suites.
Breaking changes
-
app_typenow takes only"r-shiny","py-shiny", orNULL(autodetected), and shinylive is aruntime_strategyrather than an app type. The old"r-shinylive"and"py-shinylive"values still work with a deprecation warning and will be removed in a future release.
New features
- Python Shiny apps are supported alongside R.
app_typeautodetects"r-shiny"or"py-shiny"fromappdir, soexport(appdir, destdir)works with no other arguments. -
runtime_strategyselects how an app runs, and all five strategies work with both languages:shinylive(the default; compiled to WebAssembly and run offline in the browser),bundled(embeds a portable R or Python runtime),system(uses an installed interpreter),auto-download(fetches the runtime on first launch), andcontainer(runs in Docker or Podman). - Multi-app suites bundle several apps into one Electron shell with a launcher. An
appsarray in_shinyelectron.ymllists them, and each app can set its ownruntime_strategy. -
export()andbuild_electron_app()gain asignargument for macOS signing and notarization and Windows Authenticode, driven by the usualCSC_*andAPPLE_*environment variables. -
enable_auto_updates(),disable_auto_updates(), andcheck_auto_update_status()manage electron-updater configuration. -
install_r_portable(),install_python_standalone(), andinstall_nodejs()download and cache portable runtimes, andcache_dir(),cache_info(), andcache_remove()inspect and prune the cache. -
dependencies.r.version,dependencies.python.version, anddependencies.electron.versionpin the versions a build uses; each acceptsnull,"latest", or an exact version. - App dependencies are detected automatically for native, bundled, and container builds, from
library()andrequire()calls for R andrequirements.txtorpyproject.tomlfor Python. - A configurable lifecycle splash and preloader report startup progress, and a system tray and application menu are set through
_shinyelectron.yml. - The Electron shell streams the renderer console (webR, Pyodide, and Shiny output) into the app log, so browser-side messages and errors appear alongside the main-process logs.
-
app_check()validates an app before building,wizard()generates a config interactively,show_config()prints the merged configuration, andavailable_examples()andexample_app()browse the bundled demos. -
app_dependencies()reports the R or Python packages a Shiny app or multi-app suite uses, which helps install an app’s dependencies before a shinylive build. - Apps can supply a Posit
_brand.ymlfor theming. - Prebuilt demo installers are published for every strategy and platform, listed in the new Download Prebuilt Demos article.
Minor improvements and fixes
- The
runtime_strategyargument overrides a suite’sbuild.runtime_strategyfor apps that set no per-app strategy, so a suite built asshinylivereally is shinylive rather than falling back to the config default. - A
_brand.ymlthat names palette colors (for exampleprimary: plum) resolves those references before theming the shell. - Error screens allow selecting and copying the message and log details.
- Building with the shinylive strategy checks that the app’s R packages are installed and names any that are missing, since
shinylive::export()compiles the WebAssembly bundle from installed packages. -
build_electron_app()refuses to overwrite protected directories such as~,/, andR.home(). -
convert_shiny_to_shinylive()removes its temporary copy on every exit path. -
export()cleans up partial output when a build fails, so a retry no longer needsoverwrite = TRUE, for single apps and multi-app suites alike. -
export()no longer aborts or deletes a finished build when arun_afteroropen_afterstep fails; those steps now only warn. -
init_config()escapes app names so the generated YAML round-trips, andbuild.typemay be omitted and autodetected. -
run_electron_app()reports the real exit code and stderr on failure and returnsNULLwhen interrupted. -
sitrep_shinyelectron()also checks the Python shinylive CLI and shiny package. - Directory copying keeps consistent cross-platform semantics on Windows.
- Python subprocesses spawn without
LD_LIBRARY_PATH, fixing a LinuxNo module named shinyliveerror. - Portable runtimes extract with the system
taron macOS and Linux and bsdtar on Windows, handling archives R’s internal tar cannot read. - Native apps bind to an OS-assigned free port to avoid collisions, and native startup failures surface in the lifecycle splash.
- The
systemstrategy checks for R >= 4.4.0 or Python >= 3.9.0 and fails with an actionable message. - Invalid configuration values warn and fall back to defaults instead of aborting later in the build.
- Configuration keys that were never read (
splash.width,splash.height,preloader.enabled,lifecycle.splash_min_duration) are removed, andmenu.templateaccepts only"default"and"minimal". - Downloaded runtimes are verified against upstream SHA-256 checksums before extraction.
- Vignettes cover getting started, configuration, runtime strategies, multi-app suites, code signing, containers, security, and auto-updates.
shinyelectron 0.1.0
- Initial release with
r-shinylivesupport. - Export R Shiny apps as standalone Electron desktop applications via WebR.
- Cross-platform builds for macOS, Windows, and Linux.
- Node.js local installation and management.
- Configuration via
_shinyelectron.yml. - Automatic updates via
electron-updater.