Shiny for Python Deploy: How to Host Your App For Free on GitHub Pages

By:
Dario Radečić
October 9, 2023

When it comes to deploying Shiny for Python applications, you have options - some of which are entirely free. If you have been a developer for some time, you know free deployment isn't always a given, especially when working with newer, more demanding tech stacks. Luckily, <a href="https://pages.github.com/" target="_blank" rel="noopener">GitHub pages</a> allow you to handle Shiny for Python deploy with a couple of simple steps, leaving your wallet intact.

Today you'll learn how to go through a Shiny for Python deployment process with GitHub pages, what are some things you need to be aware of, and how to make sure the entire process goes error-free. Let's dive in!
<blockquote>Make sure your dashboard looks amazing before deploying it - <a href="https://appsilon.com/shiny-for-python-scss/" target="_blank" rel="noopener">This SCSS guide in Shiny for Python will teach you how</a>.</blockquote>
Table of contents:
<ul><li><a href="#why-github-pages">Why GitHub Pages for Shiny for Python Deployment</a></li><li><a href="#first-deploy">Your First GitHub Pages Deployment</a></li><li><a href="#shiny-deploy">Shiny for Python Deploy on GitHub Pages</a></li><li><a href="#summary">Summing up Shiny for Python Deploy</a></li></ul>
Note: This article was written with <a href="https://github.com/posit-dev/py-shiny/releases" target="_blank" rel="noopener">Shiny for Python version 0.3</a>.

<hr />

<h2 id="why-github-pages">Why GitHub Pages for Shiny for Python Deployment</h2>
The first question you'll likely have is - Why choose GitHub pages over any other hosting platform? We'll provide some concrete reasons below.

<img class="size-full wp-image-19670" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae67ebfe7465b4b8f480_a150e14c_1-3.webp" alt="Image 1 - GitHub Pages" width="1641" height="1401" /> Image 1 - GitHub Pages

First and foremost, <b>GitHub pages are free</b> as long as you want to deploy your website/app from a public GitHub repo. We've made the mistake of creating a private repo for the purpose of this article and had to convert it to public in order to continue (or pay a monthly/yearly subscription).

Then there's <b>interface familiarity</b>. If you're a developer or data scientist, it's highly likely you've worked with GitHub in the past. The thing is, you already know what it does, and how the user interface behaves, so the learning curve is almost non-existent.

And finally, GitHub allows you to add a <b>custom domain</b> to your website/app deployed through GitHub Pages. This will give a professional and unique feel to your app, and the only hassle is setting up CNAME records (which takes a couple of seconds). If you don't want or need a custom domain, GitHub pages will automatically assign one for you in the format of <code>https://username.github.io/repository-name</code>.

That's only a handful of reasons, but all of them are bulletproof.

But how do you actually go about deploying Shiny for Python app to GitHub pages? That's what you'll learn later in the article, but first, let's make a dummy deployment to ensure you get the concepts right.
<h2 id="first-deploy">Your First GitHub Pages Deployment</h2>
This section will walk you through the process of deploying a dummy <code>index.html</code> to GitHub pages. If you're already familiar with the deployment steps, feel free to skip this section.

First things first, <b>create a new public GitHub repository</b>. We've created a private one by accident and had to make it public later. If you also have a private repository, convert it to public by going into repository <i>Settings</i>, scrolling down to <i>Danger Zone</i>, and clicking on the <i>Change visibility</i> button.

<img class="size-full wp-image-19672" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae6806cc67965bded7ba_a29d2afd_2-2.webp" alt="Image 2 - Creating a GitHub repository" width="2027" height="1259" /> Image 2 - Creating a GitHub repository

Once you have the repository, create a <code>index.html</code> file in the root and write some dummy HTML code. We've included a <code>h1</code> title. This is needed just to verify the deployment works:

<img class="size-full wp-image-19674" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae69e5217dd71dd6bc78_27adab90_3-2.webp" alt="Image 3 - Creating a dummy index.html file" width="1078" height="376" /> Image 3 - Creating a dummy index.html file

This is how your repository root page should look after creating the HTML file:
<div class="mceTemp"></div>

<img class="size-full wp-image-19676" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae695b337fa9cdade3dd_224d36e7_4-2.webp" alt="Image 4 - Repository contents" width="1559" height="484" /> Image 4 - Repository contents

To configure the deployment via GitHub pages, click on repository <i>Settings</i> and select <i>Pages</i> from the left sidebar.

Make sure your options match the ones you see below and click on the <i>Save</i> button:

<img class="size-full wp-image-19678" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae6a849aa4fb70c8b827_17068bad_5-2.webp" alt="Image 5 - Configuring GitHub Pages build" width="1793" height="889" /> Image 5 - Configuring GitHub Pages build

Now give it a couple of seconds to actually deploy your code, and then navigate to the following URL:
<pre>https://username.github.io/repository-name</pre>
Of course, swap <code>username</code> and <code>repository-name</code> with the values matching your case. For us, the final URL is:
<pre>https://darioradecic.github.io/shiny-for-python-page</pre>
Here's what you should see once you open your URL:

<img class="size-full wp-image-19680" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae6b7f844f0151b3af32_267dfa05_6-2.webp" alt="Image 6 - Testing GitHub Pages deployment" width="1561" height="1012" /> Image 6 - Testing GitHub Pages deployment

Yup - the deployment works. Let's now switch to Shiny for Python and see how to deploy it to GitHub pages.
<h2 id="shiny-deploy">Shiny for Python Deploy on GitHub Pages</h2>
The tricky part about Shiny apps is that they're not static, and GitHub pages work only on static pages. Luckily, <a href="https://shiny.posit.co/py/docs/shinylive.html" target="_blank" rel="noopener">Shinylive</a> is here to save the day. It will essentially allow you to run Shiny for Python apps without a Python server.

But first, let's create a Shiny for Python app.
<h3>Creating a Shiny for Python App</h3>
Create a new Python file named <code>app.py</code> and paste the following code inside it:
<pre><code class="language-python">from shiny import ui, render, App
import numpy as np
import matplotlib.pyplot as plt
<br>
app_ui = ui.page_fluid(
   ui.layout_sidebar(
       ui.panel_sidebar(
           ui.h2("Page Charts"),
           ui.hr(),
           ui.input_slider(id="slider", label="Number of bins:", min=5, max=25, value=15)
       ),
       ui.panel_main(
           ui.output_plot(id="histogram")
       )
   )
)
<br>def server(input, output, session):
   @output
   @render.plot
   def histogram():
       x = 100 + np.random.randn(500)
       plt.title("A histogram", size=20)
       plt.hist(x=x, bins=input.slider(), color="grey", ec="black")
<br>
<br>app = App(ui=app_ui, server=server) </code></pre>
This app allows users to change the number of bins in a histogram which is then automatically rerendered as soon as the change happens. You can run the app by executing the following shell command:
<pre><code class="language-bash">shiny run app.py</code></pre>
Here's what you'll see when you open it up:

<img class="size-full wp-image-19682" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae6b227b18adf5cdf670_6feca868_7-1.webp" alt="Image 7 - Running a Shiny for Python app locally" width="1351" height="941" /> Image 7 - Running a Shiny for Python app locally

That's your Shiny app - now, let's make it static with Shinylive.
<h3>Exporting and Serving a Static Site Locally</h3>
Shiny for Python allows you to use Shinylive - an experimental mode in which applications can run entirely in a web browser, eliminating the need for a separate server running Python. Keep in mind that this feature is experimental, and will likely change in the future.

The first step to getting started with Shinylive is to install it. Run this line from the terminal:
<pre><code class="language-bash">pip install shinylive</code></pre>
Once installed, generating a static Shiny for Python app is just a matter of a couple of additional commands.

The first one is here for precaution since some users can have trouble with Shinylive due to caching:
<pre><code class="langauge-bash">shiny static-assets remove</code></pre>
<img class="size-full wp-image-19684" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae6c12c4dca380d3ea8b_66b60ed6_8-1.webp" alt="Image 8 - Removing static assets" width="1674" height="916" /> Image 8 - Removing static assets

Once static assets are removed, you can export the Shiny application. We've cloned the GitHub repository and removed the <code>index.html</code> file. Our <code>app.py</code> is located in the folder named <code>src_shiny_app</code>. <b>The static app must be stored in a folder named <code>docs</code></b>. It's a requirement made by GitHub pages, so keep it in mind.

The following command exports the Shiny for Python application from the <code>src_shiny_app</code> directory to a folder named <code>docs</code>:
<pre><code class="language-bash">shinylive export src_shiny_app docs</code></pre>
Make sure to tweak the command so it works with your folder structure. Once done, here's what you should see:

<img class="size-full wp-image-19686" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae6de5217dd71dd6bf71_5f02c11b_9-1.webp" alt="Image 9 - Exporting a static Shiny for Python app" width="1674" height="916" /> Image 9 - Exporting a static Shiny for Python app

And now to test if the static app works correctly, you can run the following command to launch it locally:
<pre><code class="language-bash">python -m http.server --directory docs --bind localhost 8008</code></pre>
<img class="size-full wp-image-19688" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae6d0a1858e6d4e8b1ae_35203f23_10-1.webp" alt="Image 10 - Running a static Shiny for Python app locally" width="1674" height="916" /> Image 10 - Running a static Shiny for Python app locally

This will launch a web server with your app running on port 8008:

<img class="size-full wp-image-19690" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae6edb9f11d130cd8168_6b0be811_11-1.webp" alt="Image 11 - Running a static Shiny for Python app locally (2)" width="1651" height="1059" /> Image 11 - Running a static Shiny for Python app locally (2)

Neat - the app works when exposed from a static directory, which means we have everything needed to tackle deployment.
<h3>Deploying Shiny for Python App to GitHub Pages</h3>
Once you've made all the changes, you can simply make a commit and push the changes to the remote repository. Here are the commands:
<pre><code class="language-bash">git add .
git commit -m "App push"
git push -u origin main</code></pre>
Within seconds, you'll get a similar-looking terminal screen:

<img class="size-full wp-image-19692" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae6e67eac46f1bcf5956_6a6790f2_12-1.webp" alt="Image 12 - Pushing changes to a remote repository" width="1674" height="916" /> Image 12 - Pushing changes to a remote repository

If you refresh your GitHub repo page, you'll see two new folders added - <code>docs</code> which contains the static app, and <code>src_shiny_app</code> which contains the Python scripts. The latter is irrelevant here since all deployment tasks are handled from the <code>docs</code> folder, but it's always a good idea to keep track of the source Python code:

<img class="size-full wp-image-19694" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae6fc83b172710140035_9c112644_13-1.webp" alt="Image 13 - Contents of a GitHub repository" width="1563" height="653" /> Image 13 - Contents of a GitHub repository

Almost at the end! The next step is to change the build and deployment options for GitHub Pages. Head over to repo <i>Settings</i>, choose <i>Pages</i> from the left sidebar, and make sure that the deployment goes from the <code>/docs</code> folder. Once done, click on "Save":

<img class="size-full wp-image-19696" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae7074fe971f03850aa0_edb020dc_14-1.webp" alt="Image 14 - Changing the build directory" width="1496" height="910" /> Image 14 - Changing the build directory

This will trigger action for building and deploying your app. You can see it in the <i>Actions</i> tab:

<img class="size-full wp-image-19698" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae72fd4d9514e7a7ef0d_a3a7c9e0_15.webp" alt="Image 15 - GitHub actions pipeline" width="1251" height="838" /> Image 15 - GitHub actions pipeline

As soon as you get all green checkmarks, it means your app is deployed. Click on the link provided to test it out:

<img class="size-full wp-image-19700" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae72584db909e84b8858_45230e87_16.webp" alt="Image 16 - Deployed Shiny for Python application" width="1937" height="1611" /> Image 16 - Deployed Shiny for Python application

Judging by the URL, it seems like the deployment worked like a charm!

Shinylive allows you to take your app a step further and modify the code on the go. Simply append <code>/edit</code> to your application's URL and you'll get this window:

<img class="size-full wp-image-19702" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7ae73c5697a6609bab22d_4250d054_17.webp" alt="Image 17 - Deployed Shiny for Python application (2)" width="1937" height="1611" /> Image 17 - Deployed Shiny for Python application (2)

You can see your code on the left and the rendered dashboard on the right. You can make any changes to the code, hit the "Run" button, and see how it affects the end product.

<hr />

<h2 id="summary">Summing up Shiny for Python Deploy</h2>
To be perfectly honest, we think deploying Shiny for Python apps with GitHub pages is one of the simplest - if not the simplest - ways to get your app out on the web. It costs you absolutely nothing, provided that you're okay with your application code being visible to the entire world.

There are still many deployment options in Shiny for Python, so stay tuned to the Appsilon blog to learn all of them!

<i>What's your favorite way of deploying Shiny applications? Either R or Python.</i> Please let us know in the comment section below.
<blockquote>Is R Shiny better than Shiny for Python? <a href="https://appsilon.com/r-shiny-vs-shiny-for-python/" target="_blank" rel="noopener">Read our detailed comparison and find out</a>.</blockquote>


Have questions or insights?

Engage with experts, share ideas and take your data journey to the next level!
Explore Possibilities

Share Your Data Goals with Us

From advanced analytics to platform development and pharma consulting, we craft solutions tailored to your needs.

Talk to our Experts
shiny
python
shiny dashboards
deploy shiny apps
tutorials
shiny for python