<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Shiny on TanHo.ca</title><link>https://tanho.ca/tags/shiny/</link><description>Recent content in Shiny on TanHo.ca</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright> © 2026 Tan Ho. Unless otherwise specified, content is licensed with [CC-BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).</copyright><lastBuildDate>Fri, 02 Oct 2026 14:22:39 -0400</lastBuildDate><atom:link href="https://tanho.ca/tags/shiny/index.xml" rel="self" type="application/rss+xml"/><item><title>Data Science Hangout</title><link>https://tanho.ca/posts/talks/2025-10_dshangout/</link><pubDate>Thu, 23 Oct 2025 00:00:00 +0000</pubDate><guid>https://tanho.ca/posts/talks/2025-10_dshangout/</guid><description>&#10;&lt;h2 class="relative group"&gt;Recording&#10; &lt;div id="recording" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#recording" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;&#10;&#9;&#9;&#9;&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/Eqlh3iE1BiU?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;&#10;&#9;&#9;&lt;/div&gt;&#10;&#10;</description><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://tanho.ca/posts/talks/2025-10_dshangout/featured.png"/></item><item><title>Adventures In Scaling Shiny: Lessons Learned Building DynastyProcess</title><link>https://tanho.ca/posts/talks/2024-10_shinyprod2024_scaling/</link><pubDate>Thu, 10 Oct 2024 00:00:00 +0000</pubDate><guid>https://tanho.ca/posts/talks/2024-10_shinyprod2024_scaling/</guid><description>&#10;&lt;h2 class="relative group"&gt;Recording&#10; &lt;div id="recording" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#recording" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;&#10;&#9;&#9;&#9;&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/zb3umo3Ka2g?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;&#10;&#9;&#9;&lt;/div&gt;&#10;&#10;&#10;&lt;h2 class="relative group"&gt;Materials&#10; &lt;div id="materials" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#materials" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Repo: &lt;a href="https://github.com/tanho63/talk_shinyprod2024_scaling" target="_blank" rel="noreferrer"&gt;https://github.com/tanho63/talk_shinyprod2024_scaling&lt;/a&gt;&lt;/p&gt;&#10;</description><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://tanho.ca/posts/talks/2024-10_shinyprod2024_scaling/featured.png"/></item><item><title>Effective Logging Strategies</title><link>https://tanho.ca/posts/talks/2023-10_shinyprod2023_logging/</link><pubDate>Fri, 13 Oct 2023 00:00:00 +0000</pubDate><guid>https://tanho.ca/posts/talks/2023-10_shinyprod2023_logging/</guid><description>&#10;&lt;h2 class="relative group"&gt;Recording&#10; &lt;div id="recording" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#recording" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;&#10;&#9;&#9;&#9;&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/wbUXrK_YWfI?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;&#10;&#9;&#9;&lt;/div&gt;&#10;&#10;&#10;&lt;h2 class="relative group"&gt;Materials&#10; &lt;div id="materials" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#materials" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Repo: &lt;a href="https://github.com/tanho63/talk_shinyprod2023_logging" target="_blank" rel="noreferrer"&gt;https://github.com/tanho63/talk_shinyprod2023_logging&lt;/a&gt;&lt;/p&gt;&#10;</description><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://tanho.ca/posts/talks/2023-10_shinyprod2023_logging/featured.jpg"/></item><item><title>Debugging Shiny Apps</title><link>https://tanho.ca/posts/talks/2023-03_shinyconf2023_debugging/</link><pubDate>Fri, 17 Mar 2023 00:00:00 +0000</pubDate><guid>https://tanho.ca/posts/talks/2023-03_shinyconf2023_debugging/</guid><description>&#10;&lt;h2 class="relative group"&gt;Recording&#10; &lt;div id="recording" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#recording" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;&#10;&#9;&#9;&#9;&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/x764Y1qz_iQ?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;&#10;&#9;&#9;&lt;/div&gt;&#10;&#10;&#10;&lt;h2 class="relative group"&gt;Materials&#10; &lt;div id="materials" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#materials" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;&lt;a href="https://github.com/tanho63/talk_shinyconf2023_debugging" target="_blank" rel="noreferrer"&gt;https://github.com/tanho63/talk_shinyconf2023_debugging&lt;/a&gt;&lt;/p&gt;&#10;</description><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://tanho.ca/posts/talks/2023-03_shinyconf2023_debugging/featured.png"/></item><item><title>Setting Up Your Own Shiny Server</title><link>https://tanho.ca/posts/talks/2021-10_tantorials_shiny-server/</link><pubDate>Mon, 11 Oct 2021 00:00:00 +0000</pubDate><guid>https://tanho.ca/posts/talks/2021-10_tantorials_shiny-server/</guid><description>&#10;&lt;h2 class="relative group"&gt;Recording&#10; &lt;div id="recording" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#recording" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;&#10;&#9;&#9;&#9;&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/JL4T0qfqY7k?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;&#10;&#9;&#9;&lt;/div&gt;&#10;&#10;</description><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://tanho.ca/posts/talks/2021-10_tantorials_shiny-server/featured.jpg"/></item><item><title>DSLC Slack: Changing Window Titles in Shiny</title><link>https://tanho.ca/posts/2020-10-22_shinywindowtitles/</link><pubDate>Tue, 20 Oct 2020 00:00:00 +0000</pubDate><guid>https://tanho.ca/posts/2020-10-22_shinywindowtitles/</guid><description>&lt;div class="flex px-4 py-3 rounded-md bg-primary-100 dark:bg-primary-900"&gt;&#10; &lt;span class="text-primary-400 ltr:pr-3 rtl:pl-3 flex items-center"&gt;&#10; &lt;span class="relative block icon"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"&gt;&lt;path fill="currentColor" d="M256 32C114.6 32 .0272 125.1 .0272 240c0 49.63 21.35 94.98 56.97 130.7c-12.5 50.37-54.27 95.27-54.77 95.77c-2.25 2.25-2.875 5.734-1.5 8.734C1.979 478.2 4.75 480 8 480c66.25 0 115.1-31.76 140.6-51.39C181.2 440.9 217.6 448 256 448c141.4 0 255.1-93.13 255.1-208S397.4 32 256 32z"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;/span&gt;&#10; &lt;/span&gt;&#10; &lt;span class="dark:text-neutral-300"&gt;I greatly enjoy the DSLC Slack Community (&lt;a href="https://dslc.io/join" target="_blank"&gt;&#10; dslc.io/join&lt;/a&gt;),&#10;and spend a fair bit of time answering questions! This post is part of a &lt;a href="https://tanho.ca/tags/dslc-slack"&gt;&#10; series&lt;/a&gt;&#10;where I curate some interesting questions and/or answers that I’ve come across there.&lt;/span&gt;&#10;&lt;/div&gt;&#10;&#10;&#10;&lt;h2 class="relative group"&gt;&lt;code&gt;Dhiraj&lt;/code&gt; asks:&#10; &lt;div id="dhiraj-asks" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#dhiraj-asks" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;blockquote&gt;&lt;p&gt;I have a shiny application which uses the navbarPage() layout. The app has multiple tabPanels with their own titles. Is it possible to have the windowTitle of the navbarPage dynamic to show the titles of the tabPanels ?&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 class="relative group"&gt;Answer&#10; &lt;div id="answer" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#answer" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Here&amp;rsquo;s a minimal example of the Shiny and JS code you&amp;rsquo;ll need:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-r" data-lang="r"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shiny&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tidyverse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;custom_js&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Shiny.addCustomMessageHandler(&amp;#34;handler_windowtitle&amp;#34;, switch_window_title );&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;function switch_window_title(message){&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; document.title = message;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ui&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nf"&gt;navbarPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;navbarpage&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;displayed_tab&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;custom_js&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;tabPanel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;StrangePlanet&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;tabPanel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;DarthVader&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;observeEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;displayed_tab&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;sendCustomMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;handler_windowtitle&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;displayed_tab&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;shinyApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;If you give navbarPage an ID, it&amp;rsquo;ll create an &lt;code&gt;input&lt;/code&gt; variable that can be accessed as &lt;code&gt;input${id}&lt;/code&gt;, returning the value argument of the tabPanel. In this case, tabPanel returns the &lt;code&gt;title&lt;/code&gt; argument as the default value - you can specify something else if you prefer.&lt;/p&gt;&#10;&lt;p&gt;In a production app, I&amp;rsquo;d also move the JS into a separate JS file (stored in www) and use &lt;code&gt;includeJS()&lt;/code&gt; instead of using the &lt;code&gt;tags$script&lt;/code&gt; method.&lt;/p&gt;&#10;</description><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://tanho.ca/posts/2020-10-22_shinywindowtitles/featured.jpg"/></item><item><title>DSLC Slack: Explaining Shiny to Your IT Team</title><link>https://tanho.ca/posts/2020-10-15_explaining-shiny/</link><pubDate>Thu, 15 Oct 2020 00:00:00 +0000</pubDate><guid>https://tanho.ca/posts/2020-10-15_explaining-shiny/</guid><description>&lt;div class="flex px-4 py-3 rounded-md bg-primary-100 dark:bg-primary-900"&gt;&#10; &lt;span class="text-primary-400 ltr:pr-3 rtl:pl-3 flex items-center"&gt;&#10; &lt;span class="relative block icon"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"&gt;&lt;path fill="currentColor" d="M256 32C114.6 32 .0272 125.1 .0272 240c0 49.63 21.35 94.98 56.97 130.7c-12.5 50.37-54.27 95.27-54.77 95.77c-2.25 2.25-2.875 5.734-1.5 8.734C1.979 478.2 4.75 480 8 480c66.25 0 115.1-31.76 140.6-51.39C181.2 440.9 217.6 448 256 448c141.4 0 255.1-93.13 255.1-208S397.4 32 256 32z"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;/span&gt;&#10; &lt;/span&gt;&#10; &lt;span class="dark:text-neutral-300"&gt;I greatly enjoy the DSLC Slack Community (&lt;a href="https://dslc.io/join" target="_blank"&gt;&#10; dslc.io/join&lt;/a&gt;),&#10;and spend a fair bit of time answering questions! This post is part of a &lt;a href="https://tanho.ca/tags/dslc-slack"&gt;&#10; series&lt;/a&gt;&#10;where I curate some interesting questions and/or answers that I’ve come across there.&lt;/span&gt;&#10;&lt;/div&gt;&#10;&#10;&#10;&lt;h2 class="relative group"&gt;&lt;code&gt;Piranha&lt;/code&gt; asks:&#10; &lt;div id="piranha-asks" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#piranha-asks" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;blockquote&gt;&lt;p&gt;Hello,&#10;This might be bit of a stretch&amp;hellip;. I could use a bit of help in prepping for some upcoming conversations with the head of my company&amp;rsquo;s IT/Security.&lt;/p&gt;&#10;&lt;p&gt;I am trying to get IT support for Shiny (currently IT supports Tableau).&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Question&lt;/strong&gt;: Is there any kind of high level summary of this Admin Guide document?&#10;&lt;a href="https://docs.rstudio.com/shiny-server/" target="_blank" rel="noreferrer"&gt;https://docs.rstudio.com/shiny-server/&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;More specifically, I want to summarize the official document into about a 3-5 slide presentation. Topics that I want to include:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;What is Shiny? (3-5 bullet points, in language that a &amp;ldquo;traditional&amp;rdquo; IT person will understand)&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;How to think about security and authentication for both the Shiny Server free and Pro.&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;How to think about Dockerizing an application.&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;I attempted to summarize the official docs into a 3-5 slide PowerPoint (ugh, yes, PowerPoint!), but am really struggling. This is a massive document and I am not an IT person!&lt;br&gt;&#10;Any pointers would be really helpful.&lt;br&gt;&#10;Thanks!&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 class="relative group"&gt;Answer (by me)&#10; &lt;div id="answer-by-me" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#answer-by-me" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;I don&amp;rsquo;t know if I have a document to point you at, but I would suggest a mental&#10;model where you separate Shiny the app (the app.R file and all of the things&#10;included in it) from the ways you deploy Shiny. Writing out some of my personal&#10;thoughts on it:&lt;/p&gt;&#10;&lt;p&gt;Shiny (the app):&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;is an R package that allows you to write UI (client-side) and server-side&#10;logic in R, which can be implemented quickly (from a code-writing perspective)&#10;and powerfully (leverages all of the modelling/data-wrangling packages and&#10;abilities of R).&lt;/li&gt;&#10;&lt;li&gt;has an architecture consisting of a client (the browser) and a server (an&#10;R process). The two are connected by a&#10;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" target="_blank" rel="noreferrer"&gt;websocket&lt;/a&gt;&#10;that receives state changes from the client, such as new values for input controls,&#10;and distributes state changes from the server, such as new output values.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Shiny is not self-contained because it relies on R and other libraries (Shiny,&#10;as well as whatever else you use in the app) that are installed onto the server.&#10;Docker is one of the best ways to handle this, because it creates a container that&#10;holds an installation of R and all of the relevant packages, and can be version-locked&#10;to ensure stability. Once a Shiny app has been dockerized, it can be turned over&#10;to a devops team to deploy, and the devops team does not have to know R or Shiny&#10;in order to use the app.&lt;/p&gt;&#10;&lt;p&gt;This allows for a division of expertise:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;the data scientist makes the app, and makes sure the docker container builds&#10;and works as intended&lt;/li&gt;&#10;&lt;li&gt;the devops engineer can take care of the details with deploying and securing&#10;the apps, by controlling/restricting access to the container itself rather than&#10;forcing the data scientist to worry about it inside the app.&lt;/li&gt;&#10;&lt;li&gt;Both the data scientist and the devops engineer should responsible for&#10;performance:&#10;&lt;ul&gt;&#10;&lt;li&gt;data scientist by improving the code for efficiency&lt;/li&gt;&#10;&lt;li&gt;engineer by supplying the containers with the right amount of processing&#10;power/memory/load-balancing&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;A dedicated devops person can pretty easily deploy a docker container into an&#10;existing app/microservices system, if such already exists.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;At the other end of the spectrum, &lt;a href="http://shinyapps.io/" target="_blank" rel="noreferrer"&gt;shinyapps.io&lt;/a&gt; and RS&#10;Connect are solutions that RStudio provides to help data teams who want this&#10;sort of devops process but don&amp;rsquo;t want to have the work done in house. They&amp;rsquo;ll&#10;manage the servers for you and make it very easy for R users to just upload all&#10;of the app data and configs, and they&amp;rsquo;ll manage deployment, performance and&#10;authentication for you.&lt;/p&gt;&#10;&lt;p&gt;I&amp;rsquo;m a data generalist for a small team, and manage the full stack from data&#10;import/wrangle/model to app dev to app deploy. I wouldn&amp;rsquo;t necessarily recommend&#10;that path if your team is large enough - let devops be devops and data scientists&#10;be data scientists where possible!&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Some followup questions&#10; &lt;div id="some-followup-questions" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#some-followup-questions" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;blockquote&gt;&lt;p&gt;In a discussion earlier this week, a person from IT asked me &amp;ldquo;I dont know R,&#10;can you tell me how Shiny connects to the user&amp;rsquo;s browser?&amp;rdquo; I didn&amp;rsquo;t know much&#10;about WebSocket technology at the time, so my response was: &amp;ldquo;Shiny comes with&#10;its own webserver, but a common practice is to use nginx webserver in front of&#10;the shiny app&amp;rdquo;.&lt;/p&gt;&#10;&lt;p&gt;Now that I know a bit more&amp;hellip;would it be accurate to some something along these&#10;lines: &amp;ldquo;Shiny uses WebSocket technology to create a 2-way communication between&#10;the server and the browser. This allows the data scientist to leverage the full&#10;data-processing and analytical capabilities of R. In our current process, we need&#10;to do processing/analysis in one tool (e.g. SAS, R) and visualization/sharing&#10;in Tableau/Excel - creating lots of inefficiencies. Using Shiny, we can fine-tune&#10;and scale our analysis to exactly what is needed by the client and serve that&#10;via a Shiny dashboard.&amp;rdquo;&lt;/p&gt;&#10;&lt;p&gt;Furthermore, &amp;ldquo;From the data science team&amp;rsquo;s perspective, this is our &lt;strong&gt;ask&lt;/strong&gt;.&#10;We need the ability to deliver interactive analysis to our clients at scale.&#10;Can you help us do that in a secure way? We&amp;rsquo;ll build the Shiny app and dockerize&#10;it. We need help from IT to provide secure access by clients&amp;rdquo;.&lt;/p&gt;&#10;&lt;/blockquote&gt;&lt;p&gt;and response:&lt;/p&gt;&#10;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;Shiny uses WebSocket technology to create a 2-way communication between the server and the browser&lt;/code&gt;&lt;/p&gt;&#10;&lt;/blockquote&gt;&lt;p&gt;I cribbed that chunk from here:&#10;&lt;a href="https://community.rstudio.com/t/is-there-any-equivalent-of-web-sockets-in-shiny-world/17908" target="_blank" rel="noreferrer"&gt;https://community.rstudio.com/t/is-there-any-equivalent-of-web-sockets-in-shiny-world/17908&lt;/a&gt;.&#10;If you&amp;rsquo;re hoping to communicate how Shiny works to an IT person, I would use the&#10;wording as described rather than paraphrasing it too much - receives state&#10;changes from client and distributes state changes from server is high-level&#10;enough for most IT people to understand - and you lose something by abstracting&#10;beyond that.&lt;/p&gt;&#10;&lt;blockquote&gt;&lt;p&gt;Using Shiny, we can fine-tune and scale our analysis to exactly what is needed&#10;by the client and serve that via a Shiny dashboard&lt;/p&gt;&#10;&lt;/blockquote&gt;&lt;p&gt;I&amp;rsquo;d change this to say that it allows you to use the same R code that you use to&#10;process and generate the data right in the app, which allows you to package the&#10;&amp;ldquo;business logic&amp;rdquo; right into the app for immediate interactive analyses. I&amp;rsquo;m not&#10;familiar with your team and the ask - but identifying the docker container as&#10;the handoff point where IT helps deploy the app and serve it securely and&#10;effectively to clients is a good start. That lets IT do the security bit.&lt;/p&gt;&#10;</description><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://tanho.ca/posts/2020-10-15_explaining-shiny/featured.jpg"/></item></channel></rss>