# How to Share a Streamlit App — Community Cloud, Private Hosting, and Static Snapshots

Canonical: https://commareports.com/share-streamlit-app
Published: 2026-09-04

> Streamlit apps need a running Python process, so there is no file you can send. Community Cloud is public and sleeps when idle; self-hosting is a service to own. Plus the static snapshot pattern for when the audience only needs the findings.

# How to share a Streamlit app

The first thing to be clear about, because it explains everything else:
**there is no file.** A Streamlit app is a Python process. The browser runs a
thin client that talks to that process over a websocket, and every slider drag
re-executes your script server-side. Nothing about that can be flattened into
an `index.html` you attach to a message.

So "how do I share my Streamlit app" is really two different questions wearing
one coat.

## Question one: they need to interact

Then something has to run your Python. The options:

**Streamlit Community Cloud.** Free, connected to GitHub, deploys on push. The
trade-offs are the ones that matter for sharing: apps deployed from public
repos are publicly reachable, and apps sleep when idle — the first visitor
after a quiet period waits through a container start, a dependency load, and
your script's first full run. If your app queries a warehouse on startup, that
is a long, silent wait, and the person you sent the link to often assumes it
is broken.

**Self-hosting.** A container behind your own auth on Cloud Run, ECS, Fly, a
VM, whatever you already operate. Full control, private, no sleep. Also a
service with a deploy path, secrets, and an on-call implication, for what
started as one analyst's script.

**Snowflake / vendor-hosted Streamlit.** If your data platform offers it and
your readers are already in that platform, this is the least-friction path.
It only reaches people who are already inside.

Pick one of these when the interactivity *is* the point — when readers
genuinely change the parameter and look again.

## Question two: they need the findings

This is the far more common case, and the whole apparatus above is overkill
for it. Most people who ask for "access to the app" want to see what it
concluded, with the two charts, and say something about one of them.

For that, run the app's logic once and publish the output.

## The snapshot pattern

Your app already computes DataFrames and figures. Rendering them to a
self-contained page is a few lines, because pandas and every Python plotting
library emit HTML natively:

```python
import pandas as pd, plotly.express as px
from analysis import load_data, summarize      # your app's own functions

df = load_data()
summary = summarize(df)
fig = px.line(summary, x="week", y="conversion")

html = f"""<!doctype html><meta charset="utf-8">
<style>body{{font:15px/1.6 system-ui;margin:2rem auto;max-width:60rem}}
table{{border-collapse:collapse}}td,th{{border:1px solid #ddd;padding:.4rem .6rem}}</style>
<h1>Weekly conversion</h1>
{fig.to_html(full_html=False, include_plotlyjs="inline")}
{summary.to_html(index=False)}"""

open("snapshot.html", "w").write(html)
```

`include_plotlyjs="inline"` matters: it embeds the library rather than linking
a CDN, so the page has no runtime dependencies and renders identically for
everyone, forever. Same idea for
[Bokeh](/share-bokeh-plot), [Altair](/share-altair-chart) and
[matplotlib](/share-pandas-dataframe-html) — inline everything.

Then publish, and keep publishing to one id:

```bash
curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html snapshot.html \
        --arg title "Conversion — week of $(date +%F)" '{title: $title, html: $html}')"
```

Comma serves report HTML verbatim with scripts enabled, so the Plotly chart
stays interactive — hover, zoom, legend toggles all work. What is gone is the
server round-trip, which is precisely the part that made the app unshareable.

## What you gain by giving up the server

No cold start, no public repo, no container. A URL that opens instantly for a
reader with no Python and no account. Access is a setting on the report —
[private, team, domain-gated or link](/docs/sharing).

And a comment layer: someone highlights the anomalous week and pins "tracking
was broken here, ignore," and that thread stays attached as the weekly
revisions accumulate. The app never had anywhere to put that.

## When to keep the app

Keep it when readers really do move the sliders — parameter sweeps, what-if
tools, anything where the answer depends on a choice the reader makes. Deploy
it properly and send the link. Publish snapshots alongside it for the weekly
record, so the conclusions have a durable home even when the app is asleep.

## Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision
history.

**[Create your first report →](https://commareports.com/)**

### Related

- [Share a Gradio app](/share-gradio-app)
- [Share a Plotly HTML chart](/share-plotly-html)
- [Share a Jupyter notebook as HTML](/share-jupyter-notebook-html)
