@stlite/react
@stlite/react provides React bindings for running Streamlit entirely in the browser with Stlite. It connects the Pyodide-backed kernel to the Streamlit UI.
Installation
Section titled “Installation”npm install @stlite/react1. Configuration (Vite)
Section titled “1. Configuration (Vite)”Update vite.config.ts to add the helper plugin so some assets are bundled correctly.
Import stliteReactPlugin from @stlite/react/vite-plugin.
// vite.config.tsimport { defineConfig } from "vite";import react from "@vitejs/plugin-react";import stliteReactPlugin from "@stlite/react/vite-plugin";
export default defineConfig({ plugins: [react(), stliteReactPlugin()],});2. Implementation
Section titled “2. Implementation”Create a kernel, pass the bundled wheel URLs, and render the app.
import { StliteAppWithToast, createKernel } from "@stlite/react";import { wheelUrls } from "@stlite/react/vite-utils";
const kernel = createKernel({ entrypoint: "app.py", files: { "app.py": { data: `import streamlit as st
st.title("Hello, Stlite!")st.write("This app runs entirely in your browser.")
name = st.text_input("Your name")if name: st.write(f"Hello, {name}!")`, }, }, requirements: [], prebuiltPackageNames: [], archives: [], wheelUrls,});
export function App() { return <StliteAppWithToast kernel={kernel} />;}Examples
Section titled “Examples”Multiple Apps
Section titled “Multiple Apps”You can run multiple Stlite apps on the same page by creating separate kernel instances.
import { StliteAppWithToast, createKernel } from "@stlite/react";import { wheelUrls } from "@stlite/react/vite-utils";
const kernel1 = createKernel({ entrypoint: "app.py", files: { "app.py": { data: `import streamlit as st
st.write("Hello, stlite!")st.write("App 1")
if "counter" not in st.session_state: st.session_state.counter = 0
if st.button("Increment counter"): st.session_state.counter += 1
st.write(f"Counter: {st.session_state.counter}")`, }, }, requirements: [], prebuiltPackageNames: [], archives: [], wheelUrls,});const kernel2 = createKernel({ entrypoint: "app.py", files: { "app.py": { data: `import streamlit as st
st.write("Hello, stlite!")st.write("App 2")
if "counter" not in st.session_state: st.session_state.counter = 0
if st.button("Increment counter"): st.session_state.counter += 1
st.write(f"Counter: {st.session_state.counter}")`, }, }, requirements: [], prebuiltPackageNames: [], archives: [], wheelUrls,});
export function App() { return ( <div style={{ width: "100%", height: "100%", display: "flex", gap: 16 }}> <div style={{ position: "relative", flex: 1 }}> <StliteAppWithToast kernel={kernel1} disableDocumentStyles /> </div> <div style={{ position: "relative", flex: 1 }}> <StliteAppWithToast kernel={kernel2} disableDocumentStyles /> </div> </div> );}Shared Worker Mode
Section titled “Shared Worker Mode”When running multiple apps, you can enable SharedWorker mode to reduce memory usage. In this mode, all apps share a single Pyodide worker instead of each having their own.
import { StliteAppWithToast, createKernel } from "@stlite/react";import { wheelUrls } from "@stlite/react/vite-utils";
// Create kernels with sharedWorker: true to share a single worker between apps.// This reduces memory usage when running multiple apps on the same page.// Note: SharedWorker shares the Python runtime, but each app has its own// independent session state. Data is NOT shared between apps.// Note: SharedWorker is not supported in all browsers (e.g., Chrome Android).const kernel1 = createKernel({ entrypoint: "app.py", files: { "app.py": { data: `import streamlit as st
st.write("Hello, stlite!")st.write("Shared Worker App 1")
if "counter" not in st.session_state: st.session_state.counter = 0
if st.button("Increment counter"): st.session_state.counter += 1
st.write(f"Counter: {st.session_state.counter}")`, }, }, requirements: [], prebuiltPackageNames: [], archives: [], wheelUrls, sharedWorker: true,});const kernel2 = createKernel({ entrypoint: "app.py", files: { "app.py": { data: `import streamlit as st
st.write("Hello, stlite!")st.write("Shared Worker App 2")
if "counter" not in st.session_state: st.session_state.counter = 0
if st.button("Increment counter"): st.session_state.counter += 1
st.write(f"Counter: {st.session_state.counter}")`, }, }, requirements: [], prebuiltPackageNames: [], archives: [], wheelUrls, sharedWorker: true,});
export function App() { return ( <div style={{ width: "100%", height: "100%", display: "flex", gap: 16 }}> <div style={{ position: "relative", flex: 1 }}> <StliteAppWithToast kernel={kernel1} disableDocumentStyles /> </div> <div style={{ position: "relative", flex: 1 }}> <StliteAppWithToast kernel={kernel2} disableDocumentStyles /> </div> </div> );}Components
Section titled “Components”<StliteAppWithToast />
Section titled “<StliteAppWithToast />”A wrapper around <StliteApp /> that includes toast notifications for:
- Loading progress
- Errors
- Module auto-loading
Props:
kernel:StliteKernel- The kernel instance created withcreateKernel.disableDocumentStyles:boolean(optional, default:false) - Whether to disable global document styles.disableProgressToasts:boolean(optional)disableErrorToasts:boolean(optional)disableModuleAutoLoadToasts:boolean(optional)
<StliteApp />
Section titled “<StliteApp />”The core component that renders the Streamlit app UI. It does not show any toast notifications.
Props:
kernel:StliteKernel- The kernel instance.disableDocumentStyles:boolean(optional, default:false) - Whether to disable global document styles.
API Reference
Section titled “API Reference”createKernel(options)
Section titled “createKernel(options)”Creates a new StliteKernel instance.
Key Options:
entrypoint:string- The main Python file to run.files:Record<string, FileContent>- Virtual file system contents.requirements:string[]- Python packages to install via micropip.wheelUrls:WheelUrls- Wheel URLs from@stlite/react/vite-utils.sharedWorker:boolean(optional) - Enable SharedWorker mode for reduced memory when running multiple apps.
See the StliteKernelOptions in @stlite/browser documentation for the complete list of options.