# Stlite: Running Streamlit Applications in the Browser

> Stlite adapts Streamlit to Pyodide and WebAssembly so Python applications can run entirely in a browser. It fits browser editors, embedded data tools, and static delivery, while browser package compatibility remains a defining constraint.

**whitphx/stlite** — Streamlit-Lite; In-browser Streamlit 🎈🚀

- Repository: https://github.com/whitphx/stlite
- Website: https://edit.share.stlite.net
- Stars: 1,677 · Forks: 89
- Language: TypeScript
- License: Apache-2.0
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/whitphx-stlite

## Why Stlite moves Streamlit into the browser

Stlite addresses a specific deployment problem: running a Streamlit data application without a conventional Python web server behind it. The project adapts Streamlit to Pyodide, whose Python runtime is compiled to WebAssembly and executes in a web browser. That makes it relevant to browser-based editors, educational tools, interactive demonstrations, static sites, and applications where computation should remain on the client.

The intended audience includes Python developers who already use Streamlit and frontend developers who want an interactive Python application inside an existing page. The repository also exposes separate packages for React integration, desktop applications, and Cloudflare deployment. Based on the repository layout, Stlite is a distribution platform around an embedded Streamlit runtime rather than only a hosted editor.

That boundary matters. A conventional Streamlit application commonly assumes a Python environment, installed packages, server-side resources, and access to external services. Stlite changes the execution environment to the browser. Any evaluation therefore has to account for Pyodide package availability, WebAssembly assets, browser memory, and the absence of a separate Python application server in the documented browser examples.

## The Stlite browser mount pipeline

The browser package exposes two documented entry paths. The `<streamlit-app>` custom element contains Python source directly. Stlite recognizes that element after the module script and stylesheet have loaded, then launches the application defined inside it. For code held elsewhere, `mount()` accepts a source string and a target DOM element. The README describes the custom-element interface as a wrapper around `mount()`.

The basic data flow starts with HTML or frontend code supplying the app source. Stlite launches its browser runtime, and Streamlit processes the Python program. Calls such as `st.text_input()` and `st.write()` are then presented through the Streamlit interface in the page. The example contains no separate browser-to-Python service. The browser owns the Python runtime and application state for the loaded environment.

For a fuller application, the `files` option maps virtual paths to file contents. One path can be `streamlit_app.py`, while another can provide a data file or `.streamlit/config.toml`. The object form of `mount()` accepts `requirements`, `entrypoint`, `files`, and `streamlitConfig`. These inputs define a small Streamlit project layout inside the browser runtime without requiring a conventional project directory on a Python server.

## A first Stlite app from the documented CDN assets

For a first use, the README's shortest integration loads `@stlite/browser` assets from jsDelivr and places a simple Streamlit app inside `<streamlit-app>`. This path does not require a repository clone, so it offers a direct way to inspect the browser execution model. Save the following as an HTML page and open it in a browser. The page should contain a text input and an initial `Hello, world` greeting. After entering a name, the app writes `Hello,` followed by that value.

```html
<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@stlite/browser@0.85.1/build/stlite.css" />
    <script type="module" src="https://cdn.jsdelivr.net/npm/@stlite/browser@0.85.1/build/stlite.js"></script>
  </head>
  <body>
    <streamlit-app>
      import streamlit as st
      name = st.text_input('Your name')
      st.write("Hello,", name or "world")
    </streamlit-app>
  </body>
</html>
```

This example uses `@stlite/browser` version `0.85.1` exactly as shown in the README. It documents the API shape rather than establishing compatibility with the newer release versions listed for other Stlite packages. A production integration should inspect the documentation for the selected browser package and align its script, stylesheet, and package version.

## Mounting multi-file Stlite apps and requirements

The `mount()` API is preferable when an app needs named files, dependencies, or Streamlit configuration. It bypasses the custom-element wrapper and exposes the runtime inputs directly. The following documented example mounts `streamlit_app.py`, requests `matplotlib`, selects that file as the entrypoint, and supplies a client configuration value. The application generates an array and renders a histogram after the user changes a slider.

```js
mount(
  {
    requirements: ["matplotlib"],
    entrypoint: "streamlit_app.py",
    files: {
      "streamlit_app.py": `
import streamlit as st
import matplotlib.pyplot as plt
import numpy as np

size = st.slider("Sample size", 100, 1000)
arr = np.random.normal(1, 1, size=size)
fig, ax = plt.subplots()
ax.hist(arr, bins=20)
st.pyplot(fig)
`,
    },
    streamlitConfig: {
      "client.toolbarMode": "viewer",
    },
  },
  document.getElementById("root"),
);
```

The target DOM element must exist before `mount()` runs. The function must also be imported from the `@stlite/browser` module URL, while `stlite.css` is loaded through a `<link>` element. There is one JavaScript-specific trap in this form. A backtick inside the Python source can conflict with the JavaScript template literal used to carry that source. The README says to escape those backticks with a preceding backslash. The `<streamlit-app>` interface avoids this particular conflict because the Python source is not placed in a JavaScript template literal.

## Stlite desktop, React, and Cloudflare packages

Stlite extends beyond an HTML CDN example. The repository points to `@stlite/desktop` for desktop applications and `@stlite/react` for React integration. It also publishes `@stlite/cloudflare`. Recent release information lists versions for all three packages, confirming that Stlite is distributed through separate integration packages rather than one browser-only artifact.

The practical difference is the application shell. `@stlite/desktop` is intended to wrap Stlite as a desktop application. `@stlite/react` serves developers embedding the runtime in a React application. `@stlite/cloudflare` targets a Cloudflare deployment context. The root README links to package-specific documentation instead of reproducing their setup instructions, so this review does not invent installation commands or configuration keys for those interfaces.

A real alternative is conventional Streamlit deployed behind a Python server. In that approach, the browser receives the interface while a server owns the Python environment and executes the code. Stlite puts the Python runtime in the browser through Pyodide and WebAssembly. The choice is architectural. Stlite can remove a Python application server from a suitable workflow, but it also transfers runtime and package constraints to the client. A Cloudflare deployment does not erase that client-side execution distinction.

## Pyodide constraints, maintenance, and upgrade costs

The main limitation is package compatibility. A package named in `requirements` is not automatically equivalent to the same package installed in a normal CPython environment. Pyodide packages must work with its Python and WebAssembly environment, and a dependency on unavailable native components may prevent installation. The README demonstrates `matplotlib`, but it does not claim that every Pyodide package or arbitrary native library is supported.

Browser resource use is another constraint. Pyodide, WebAssembly modules, downloaded wheels, Streamlit itself, and application data all use client-side resources. The README does not document load-time measurements, memory ceilings, or persistence guarantees, so none can be asserted here. The term serverless also should not be read as proof of server-secret handling or access-control isolation. The documented examples execute Python in the browser.

Source development has explicit toolchain requirements. `package.json` specifies Node.js `>=22` and Yarn `4.13.0`. `pyproject.toml` requires `uv>=0.9.17`, includes `pyodide-build==0.37.0`, and states that Python must be `>=3.14` because the exact version must match Pyodide Python. These conditions make repository development more involved than loading the CDN example. The last push was on 2026-10-15, and releases of the React, desktop, and Cloudflare packages were published on 2026-10-10. Because the repository contains independently versioned packages, an upgrade requires checking the selected package documentation and `CHANGELOG.md`, rather than assuming that all Stlite versions move together.

The repository uses the `Apache-2.0` license, with its text stored in `LICENSE`. That identifier does not by itself settle whether a particular deployment satisfies every distribution obligation. An organization embedding or redistributing Stlite should inspect that file and the terms of the Streamlit and Pyodide components used by the selected integration.

## Conclusion

Adopt Stlite when an application must execute client-side and its Python packages and browser resources fit the Pyodide environment. Do not treat it as a drop-in replacement for every server-hosted Streamlit deployment without checking package availability, native assets, browser resource demands, and the intended integration package. The first concrete evaluation should mount the smallest representative app through `@stlite/browser`, then confirm that its dependencies, files, and Streamlit configuration behave as required.

## FAQ

### What is Stlite used for?

Stlite runs Streamlit applications entirely in a web browser using Pyodide and WebAssembly. The README positions it for browser-based data applications and documents integrations for ordinary web pages, React, desktop, and Cloudflare.

### How do I use Stlite on a web page?

Load `@stlite/browser` JavaScript and CSS, then place Python code inside a `<streamlit-app>` element. For more control, import `mount()` and pass the app source, files, requirements, entrypoint, and Streamlit configuration to a DOM element.

### Can Stlite install Python dependencies?

The documented API accepts a `requirements` list, and its multi-file example requests `matplotlib`. Package installation still takes place within Pyodide, so the README's example does not imply support for every Python dependency.

### Does Stlite require a Python application server?

The browser examples execute Streamlit in the page through Pyodide and WebAssembly. Stlite also publishes desktop and Cloudflare packages, which provide different application shells around that runtime model.

### What limitations should I check before using Stlite?

Check whether required packages and native components are available through Pyodide. The README does not document browser memory limits, persistence guarantees, or compatibility with arbitrary CPython packages, so those points require verification in the target browser application.

## Sources

- [License: Apache-2.0](https://github.com/whitphx/stlite/blob/main/LICENSE)
- [Project website](https://edit.share.stlite.net)
- [README](https://github.com/whitphx/stlite/blob/main/README.md)
- [Releases](https://github.com/whitphx/stlite/releases)
- [whitphx/stlite on GitHub](https://github.com/whitphx/stlite)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/whitphx-stlite
