Skip the guide and deploy the sample app
Deploy a Shiny for Python app to Connect Cloud
In this guide, you deploy a Shiny for Python app to Connect Cloud and get a URL you can share. You can deploy from GitHub, from Positron or VS Code, or from the command line. The sample app is a restaurant tipping dashboard with filters, value boxes, a data table, and charts.

The source code is available in the examples-shiny-python repository.
Getting started
Whichever method you choose, you need the following:
A Connect Cloud account.
A Shiny for Python app. This guide uses the sample app. Its main file (Connect Cloud calls it the primary file) is
app.py. It also has a data file atdata/tips.csvand a style sheet namedstyles.css.A
requirements.txtfile that lists the Python packages you use, in the same folder asapp.py. The sample app needs the following packages:requirements.txt
faicons shiny shinywidgets plotly pandas ridgeplot
Save this file as app.py.
app.py
import faicons as fa
import plotly.express as px
import pandas as pd
# Load data and compute static values
from shiny import reactive, render
from shiny.express import input, ui
from shinywidgets import render_plotly
tips = pd.read_csv("data/tips.csv")
ui.include_css("styles.css")
bill_rng = (min(tips.total_bill), max(tips.total_bill))
# Add page title and sidebar
ui.page_opts(title="Restaurant tipping", fillable=True)
with ui.sidebar(open="desktop"):
ui.input_slider(
"total_bill",
"Bill amount",
min=bill_rng[0],
max=bill_rng[1],
value=bill_rng,
pre="$",
)
ui.input_checkbox_group(
"time",
"Food service",
["Lunch", "Dinner"],
selected=["Lunch", "Dinner"],
inline=True,
)
ui.input_action_button("reset", "Reset filter")
# Add main content
ICONS = {
"user": fa.icon_svg("user", "regular"),
"wallet": fa.icon_svg("wallet"),
"currency-dollar": fa.icon_svg("dollar-sign"),
"ellipsis": fa.icon_svg("ellipsis"),
}
with ui.layout_columns(fill=False):
with ui.value_box(showcase=ICONS["user"]):
"Total tippers"
@render.express
def total_tippers():
tips_data().shape[0]
with ui.value_box(showcase=ICONS["wallet"]):
"Average tip"
@render.express
def average_tip():
d = tips_data()
if d.shape[0] > 0:
perc = d.tip / d.total_bill
f"{perc.mean():.1%}"
with ui.value_box(showcase=ICONS["currency-dollar"]):
"Average bill"
@render.express
def average_bill():
d = tips_data()
if d.shape[0] > 0:
bill = d.total_bill.mean()
f"${bill:.2f}"
with ui.layout_columns(col_widths=[6, 6, 12]):
with ui.card(full_screen=True):
ui.card_header("Tips data")
@render.data_frame
def table():
return render.DataGrid(tips_data())
with ui.card(full_screen=True):
with ui.card_header(class_="d-flex justify-content-between align-items-center"):
"Total bill vs tip"
with ui.popover(title="Add a color variable", placement="top"):
ICONS["ellipsis"]
ui.input_radio_buttons(
"scatter_color",
None,
["none", "sex", "smoker", "day", "time"],
inline=True,
)
@render_plotly
def scatterplot():
color = input.scatter_color()
return px.scatter(
tips_data(),
x="total_bill",
y="tip",
color=None if color == "none" else color,
trendline="lowess",
)
with ui.card(full_screen=True):
with ui.card_header(class_="d-flex justify-content-between align-items-center"):
"Tip percentages"
with ui.popover(title="Add a color variable"):
ICONS["ellipsis"]
ui.input_radio_buttons(
"tip_perc_y",
"Split by:",
["sex", "smoker", "day", "time"],
selected="day",
inline=True,
)
@render_plotly
def tip_perc():
from ridgeplot import ridgeplot
dat = tips_data()
dat["percent"] = dat.tip / dat.total_bill
yvar = input.tip_perc_y()
uvals = dat[yvar].unique()
samples = [[dat.percent[dat[yvar] == val]] for val in uvals]
plt = ridgeplot(
samples=samples,
labels=uvals,
bandwidth=0.01,
colorscale="viridis",
colormode="row-index",
)
plt.update_layout(
legend=dict(
orientation="h", yanchor="bottom", y=1.02, xanchor="center", x=0.5
)
)
return plt
# --------------------------------------------------------
# Reactive calculations and effects
# --------------------------------------------------------
@reactive.calc
def tips_data():
bill = input.total_bill()
idx1 = tips.total_bill.between(bill[0], bill[1])
idx2 = tips.time.isin(input.time())
return tips[idx1 & idx2]
@reactive.effect
@reactive.event(input.reset)
def _():
ui.update_slider("total_bill", value=bill_rng)
ui.update_checkbox_group("time", selected=["Lunch", "Dinner"])Save this file as styles.css.
styles.css
:root {
--bslib-sidebar-main-bg: #f8f8f8;
}
.popover {
--bs-popover-header-bg: #222;
--bs-popover-header-color: #fff;
}
.popover .btn-close {
filter: var(--bs-btn-close-white-filter);
}Get data/tips.csv from the sample repository.
To preview the app before you deploy, install the dependencies and run it from the folder that contains app.py:
Terminal
pip install -r requirements.txt
shiny runChoose a deployment method
| Method | When to use it | Jump to |
|---|---|---|
| GitHub | Your code is on GitHub and you want it to update when you push (public repositories only on free accounts) | Deploy from GitHub |
| Posit Publisher | You work in Positron or VS Code and do not use GitHub | Deploy from Positron or VS Code |
| rsconnect-python | You want to deploy from a terminal or automate deployments | Deploy from the command line |
For more on how these methods differ, see Publishing.
Deploy from GitHub
Use this method when your app’s code is in a GitHub repository and you want changes you push to publish automatically. On a free account, your repository must be public, so anyone can see your code.
- Commit
app.py,styles.css,data/tips.csv, andrequirements.txt, then push your app to a GitHub repository. - Sign in to Connect Cloud.
- Click Publish at the top of your Home page. If this is your first time publishing, Connect Cloud prompts you to install the GitHub App, which lets Connect Cloud read your repository.
- Select Shiny.
- Select your repository.
- Check that Branch is the branch that has your content, usually
main. - Select
app.pyas the Primary file. - Leave Automatically publish on push on if you want Connect Cloud to update what you published each time you push to this branch. Turn it off to update only when you choose.
- Click Publish.
- Result: Connect Cloud shows a log of the install steps while it deploys. When it finishes, your app is live at an address like
https://[content-id].share.connect.posit.cloud, where[content-id]is a unique identifier that Connect Cloud picks. You can set a custom name to change the URL. - Update or redeploy: Commit and push to the connected branch and Connect Cloud republishes automatically. If you turned off automatic publishing, click Republish on the content’s card on your Home page. See Republishing.
For all options, see Publish from GitHub.
Deploy from Positron or VS Code
Use this method when you work in Positron or VS Code and want to publish your app directly. Positron includes the Posit Publisher extension. In VS Code, install it from the marketplace first.
- Open your project folder in Positron, or in VS Code with Posit Publisher installed.
- Click the Posit Publisher icon in the Activity Bar.
- Next to CREDENTIALS, click + and select Posit Connect Cloud. A credential is a saved connection to your Connect Cloud account. Your browser opens.
- In your browser, check that the Authorize Access code matches the code in Positron or VS Code. Then click Continue and Authorize.
- Return to Positron or VS Code and accept or change the name for this credential. Do this once.
- Click the + next to Deployments. If Posit Publisher asks which file to publish, select
app.py. - Enter a title for your content, then select the credential you just added.
- Under PROJECT FILES, check that the list includes
app.py,styles.css,data/tips.csv, andrequirements.txt. Connect Cloud uploads only the files in this list. - Click Deploy Your Project.
- Result: A success message appears in the lower right of Positron or VS Code. Click View Content in the extension to open the app on Connect Cloud. Its address has the form
https://[content-id].share.connect.posit.cloud, where[content-id]is unique to your app. - Update or redeploy: Save your changes, open Posit Publisher, select the previous deployment, and click Deploy Your Project again. Keep the
.positfolder in your project. It remembers which Connect Cloud content this project publishes to, so the next deploy updates the same content instead of creating a new one.
For the configuration file, multiple deployments per project, and troubleshooting, see Publish from your IDE.
Deploy from the command line
Use this method to deploy from a terminal or to automate deployments, for example, from a script. It requires rsconnect-python version 1.31.0 or higher.
Install the
rsconnect-pythoncommand-line tool.Terminal
pip install rsconnect-pythonAdd your Connect Cloud account. Replace
<YOUR_ACCOUNT_HERE>with your account name from your account page. Your browser opens for you to authorize access.Terminal
rsconnect add --connect-cloud \ --account "<YOUR_ACCOUNT_HERE>" \ --name cloudDeploy the folder that contains
app.py,styles.css,data/tips.csv, andrequirements.txt.Terminal
rsconnect deploy shiny . --name cloud
- Result: The command prints the URL of your content. Open the URL to see the content’s page on Connect Cloud. Add
--quietto print only the URL. - Update or redeploy: Run the same
rsconnect deploycommand again. The directory remembers where you deployed, so you can omit--name.
For noninteractive credentials, examples for automated builds, and other options, see Publish from your console or terminal.
After you deploy
Common things to set up next. They work the same however you deployed your app:
- Passwords and API keys: Store them as secret variables, not in your code. Add them under Variables in content settings, or during publishing. Read them with
os.getenv("NAME"). - Access and sharing: Control who can view your app in Sharing.
- Scheduling: On paid plans, schedule your app to republish at set times, for example, to refresh data each day.
- Custom name and domain: Change the app’s URL with a custom name or a custom domain.
- Upload size limit: The upload size limit applies when you upload your project files from your editor or the command line.
Troubleshooting
- Missing package error: Add the package to
requirements.txtand republish. Make sure the file is in the same directory asapp.py. - Missing data file: Commit the files to the repository, or include them under PROJECT FILES in Posit Publisher. Keep
tips.csvin thedatafolder. Connect Cloud can use only the files you deploy with the app. - Repository not listed: Confirm that the GitHub App has access to it.
- The deploy command stops before uploading: The folder you are deploying needs a
requirements.txtfile. See Create a requirements.txt file.
If your deployment still fails, read the log that Connect Cloud shows while it deploys and look for the first error. You can also try Error Assist, which gives guidance based on your log output.