### Run make all-dev for one-time setup Source: https://github.com/streamlit/streamlit/blob/develop/CONTRIBUTING.md One-time setup that creates and manages the virtual environment and dependencies. Run this before starting development. ```bash make all-dev ``` -------------------------------- ### Colored CLI output for skill statuses Source: https://github.com/streamlit/streamlit/wiki/pull-requests/15116/tech-spec Example of the expected colored output when reporting skill installation status per target path. Uses Click's secho() and style() with green for installed, blue for up to date, and yellow for skipped due to conflicts. Paths are cyan and arrows match the header color. ```text ✓ Installed: (green, bold) → .agents/skills/developing-with-streamlit (green arrow, cyan path) ● Up to date: (blue, bold) → .claude/skills/developing-with-streamlit (blue arrow, cyan path) ⚠ Skipped due to conflicts: (yellow, bold) → .agents/skills/developing-with-streamlit (yellow arrow) ``` -------------------------------- ### Run a Streamlit App Programmatically Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-06-14-app-run-method/product-spec.md Example of initializing an st.App and starting it with the run() method. Positional arguments passed to the script are forwarded to the app via sys.argv. ```python import sys import streamlit as st app = st.App("dashboard.py") if __name__ == "__main__": app.run() # `python app.py --date 2026-06-14 extra` -> dashboard.py sees # sys.argv == ["app.py", "--date", "2026-06-14", "extra"] ``` -------------------------------- ### Usage example for st.grid Source: https://github.com/streamlit/streamlit/wiki/pull-requests/15185/tech-spec Example showing how to initialize a grid and add content using a container. ```python grid = st.grid(4) with grid.container(): st.metric(...) st.caption(...) ``` -------------------------------- ### GET /_stcore/agent/app manifest response (JSONC) Source: https://github.com/streamlit/streamlit/wiki/pull-requests/16843/2026-08-28-agent-interface-opus5-product-spec Example manifest returned by the GET /_stcore/agent/app endpoint, showing the app's name, description, pages, inputs, and other metadata. This is available before any script has run for the caller. ```jsonc { "name": "Sales Dashboard", "description": "Revenue and pipeline metrics by region, refreshed nightly.", "pages": [{ "title": "Overview", "path": "/" }, { "title": "Reports", "path": "/reports" }], "inputs": [ { "name": "country", "type": "selectbox", "label": "Country", "schema": { "type": "string", "enum": ["Japan", "United States", "Germany"] } }, { "name": "refresh", "type": "button", "label": "Refresh data", "schema": { "type": "boolean" }, "destructive": false } ], "inputs_are_complete": false, "streamlit_version": "1.63.0", "document_format_version": 1 } ``` -------------------------------- ### Install and verify Streamlit Source: https://github.com/streamlit/streamlit/blob/develop/README.md Use pip to install the Streamlit package and run the hello command to verify the installation in your browser. ```bash $ pip install streamlit $ streamlit hello ``` -------------------------------- ### Install Node.js with nvm Source: https://github.com/streamlit/streamlit/blob/develop/CONTRIBUTING.md Install the latest supported Node.js version using nvm, after installing nvm via the linked instructions. ```bash # Install node nvm install node ``` -------------------------------- ### Start the frontend development server Source: https://github.com/streamlit/streamlit/blob/develop/frontend/README.md Commands to start the Streamlit frontend development server. Run either `yarn start` or `make frontend-dev` from the frontend directory. ```bash yarn start ``` ```bash make frontend-dev ``` -------------------------------- ### Testing plan description example Source: https://github.com/streamlit/streamlit/blob/develop/wiki/pull-requests.md Example of how to describe testing by listing test files and what they cover. This is used in the PR template checklist. ```markdown - `lib/tests/streamlit/elements/plotly_chart_test.py` — Tests height parameter - `e2e_playwright/st_plotly_chart_test.py` — Visual regression tests for height ``` -------------------------------- ### Build frontend with make frontend Source: https://github.com/streamlit/streamlit/blob/develop/CONTRIBUTING.md Builds the frontend. Run this after the one-time setup. ```bash make frontend ``` -------------------------------- ### Install protoc 26.1 from GitHub release and run make protobuf Source: https://github.com/streamlit/streamlit/blob/develop/CONTRIBUTING.md Downloads and installs a specific protoc release from GitHub when Homebrew has no matching formula. Use the asset for your OS and architecture (osx-aarch_64, osx-x86_64, linux-x86_64, or linux-aarch_64). /usr/local/bin must precede Homebrew's protoc on PATH. ```bash PROTOC_VERSION=26.1 # copy from action.yml PROTOC_ZIP="protoc-${PROTOC_VERSION}-osx-aarch_64.zip" curl -fOL "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/${PROTOC_ZIP}" sudo unzip -o "$PROTOC_ZIP" -d /usr/local bin/protoc sudo unzip -o "$PROTOC_ZIP" -d /usr/local 'include/*' rm "$PROTOC_ZIP" which protoc # should be /usr/local/bin/protoc make protobuf ``` -------------------------------- ### Option C: Usage examples for combined and single-layer handlers Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-04-20-exception-handler/product-spec.md Usage examples for Option C, showing how to configure both HTTP and script handlers via a tuple, or use a simple callable or mapping for single-layer handling. ```python # Both layers app = st.App( "main.py", exception_handlers=( {404: not_found_handler}, # HTTP layer sentry_sdk.capture_exception, # Script layer ), ) # Script only (simple callable) app = st.App("main.py", exception_handlers=sentry_sdk.capture_exception) # HTTP only (mapping, existing behavior) app = st.App("main.py", exception_handlers={404: not_found_handler}) ``` -------------------------------- ### Migration Example to culori Source: https://github.com/streamlit/streamlit/wiki/pull-requests/15150/tech-spec Example of using culori for color parsing, mixing, and alpha manipulation. ```typescript import { parse, formatRgb, interpolate, oklch } from "culori" // Parse any CSS color const color = parse("oklch(0.7 0.15 30)") // Mix in perceptually uniform space const mixer = interpolate(["red", "blue"], "oklch") const mixed = mixer(0.5) // Perceptually uniform midpoint // Set alpha const withAlpha = { ...color, alpha: 0.5 } // Output as CSS formatRgb(withAlpha) // "rgba(237, 118, 101, 0.5)" ``` -------------------------------- ### Windows workflow: install and test commands Source: https://github.com/streamlit/streamlit/wiki/pull-requests/16715/implementation-plan Run these commands in the Windows workflow after checking out the code and setting up Python. Copies the README into the lib directory, installs pytest and the editable lib package, then runs the meta-skill discovery test with the `-o addopts=` flag to drop the `--cov=streamlit` option from `lib/pyproject.toml`. ```text Copy-Item README.md lib/README.md python -m pip install pytest python -m pip install -e lib python -m pytest lib/tests/streamlit/web/meta_skill_discover_test.py -o addopts= -q ``` -------------------------------- ### Set up base environment on Ubuntu Source: https://github.com/streamlit/streamlit/blob/develop/CONTRIBUTING.md Install essential packages, Node.js via nvm, Corepack, uv, and optionally GitHub CLI and ripgrep on Ubuntu. ```bash # Install some essentials $ sudo apt-get update $ sudo apt-get install -y sudo make build-essential curl git rsync unzip protobuf-compiler # Set frontend dependencies: $ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash $ source ~/.bashrc $ nvm install node $ corepack enable # Install uv for Python $ curl -LsSf https://astral.sh/uv/install.sh | sh # (Recommended) Install GitHub CLI - used by AI agents for PR and issue management # See https://cli.github.com/ for installation instructions # (Recommended) Install ripgrep - used by AI agents for fast log/code search $ sudo apt-get install -y ripgrep ``` -------------------------------- ### Streamlit Skills CLI Commands Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-05-11-streamlit-skills-cli/product-spec.md The CLI interface for the Streamlit Skills Installer. The default command performs an interactive project install. The --global flag installs the meta skill from GitHub to the user's global agent skills directories instead of project-local bundled skills. The --yes flag skips prompts and confirms installation. ```bash streamlit skills ``` ```bash streamlit skills --global ``` ```bash streamlit skills --yes ``` ```bash streamlit skills --global --yes ``` -------------------------------- ### Install minimum dependencies with uv pip install --no-config Source: https://github.com/streamlit/streamlit/wiki/pull-requests/15968/tech-spec Install minimum runtime dependencies with project config disabled so the pandas override cannot replace the minimum. Use --force-reinstall to ensure the minimum versions are installed. ```bash uv pip install --no-config \ -r scripts/assets/min-constraints-gen.txt \ --force-reinstall ``` -------------------------------- ### Example: Call Microsoft Graph with access token Source: https://github.com/streamlit/streamlit/blob/develop/specs/2025-11-19-auth-oidc-tokens/product-spec.md Assumes `expose_tokens = "access"` so `st.user.tokens.access` exists. After `st.login()`, if the user is authenticated, it makes an authenticated GET request to an API and displays the JSON response. ```python import streamlit as st import requests st.login() if st.user: api_url = "https://api.example.com/me" resp = requests.get( api_url, headers={"Authorization": f"Bearer {st.user.tokens.access}"} ) st.json(resp.json()) ``` -------------------------------- ### Option B: Usage examples for script and HTTP errors Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-04-20-exception-handler/product-spec.md Usage examples for Option B, showing how to configure script-only or HTTP-only error handling with the unified exception_handlers parameter. Cannot configure both simultaneously. ```python # Script errors only app = st.App("main.py", exception_handlers=sentry_sdk.capture_exception) # HTTP errors only (existing behavior) app = st.App("main.py", exception_handlers={404: not_found_handler}) ``` -------------------------------- ### Set up base environment on macOS Source: https://github.com/streamlit/streamlit/blob/develop/CONTRIBUTING.md Install required tools on macOS: Apple developer tools, Homebrew, the Protobuf compiler, and optionally GitHub CLI and ripgrep. ```bash # Some Apple dev tools (developer.apple.com/downloads) $ xcode-select --install # Install Homebrew $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # Install the Protobuf compiler $ brew install protobuf # (Recommended) Install GitHub CLI - used by AI agents for PR and issue management $ brew install gh # (Recommended) Install ripgrep - used by AI agents for fast log/code search $ brew install ripgrep ``` -------------------------------- ### Install versioned protobuf@33 and run make protobuf Source: https://github.com/streamlit/streamlit/blob/develop/CONTRIBUTING.md Installs a versioned Homebrew protobuf formula matching the locked Python protobuf minor version (e.g. protobuf@33 for protobuf 6.33.x) and regenerates protobuf modules. The PATH export is session-scoped; a later `make protobuf` in a new shell will pick Homebrew's unversioned protoc again unless the PATH is persisted. ```bash brew install protobuf@33 export PATH="$(brew --prefix protobuf@33)/bin:$PATH" make protobuf ``` -------------------------------- ### Install Streamlit skills with streamlit skills Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-05-11-streamlit-skills-cli/product-spec.md Installs Streamlit's AI-agent skills. In project mode (default), it symlinks bundled skills from the active Streamlit environment. In global mode, it fetches the developing-with-streamlit meta skill from the streamlit/agent-skills repository and installs it to ~/.agents/skills/ and ~/.claude/skills/ when Claude Code is detected. ```bash streamlit skills ``` -------------------------------- ### Start dev server with make frontend-dev Source: https://github.com/streamlit/streamlit/blob/develop/CONTRIBUTING.md Starts the dev server with hot-reloading. Defaults to port 3000 instead of 8501; can be changed with `VITE_PORT` (or `PORT`). Set `DEV_SERVER_BACKEND_URL` to point at a different backend. ```bash make frontend-dev ``` -------------------------------- ### Install meta skill via npx skills Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-05-11-streamlit-skills-cli/product-spec.md Alternative cross-agent installer using npx skills (vercel/skills). Supports Claude Code, Cursor, Copilot, Gemini CLI, Codex, and others. The -g flag installs globally; -s specifies the skill name. Requires Node.js. ```bash npx skills add streamlit/agent-skills -s developing-with-streamlit -g ``` -------------------------------- ### Basic App.run() usage Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-06-14-app-run-method/product-spec.md A simple example of using the App.run() method to launch a Streamlit dashboard script. ```python import streamlit as st app = st.App("dashboard.py") if __name__ == "__main__": app.run() ``` -------------------------------- ### Example JSON snapshot of a Streamlit app page Source: https://github.com/streamlit/streamlit/wiki/pull-requests/16843/2026-09-06-agent-app-interface-opus5-2-product-spec Shows the full snapshot structure with a page, elements, and actions. The example includes a selectbox, button, metric, dataframe, and expander, demonstrating the conventions described above. ```json { "schema_version": 1, "session_id": "s_7f3a", "status": "ready", "observed_at": "2026-09-06T10:00:00Z", "page": {"url_path": "", "title": "Regional revenue", "icon": ":material/payments:"}, "pages": [ {"url_path": "", "title": "Regional revenue", "icon": ":material/payments:"}, {"url_path": "reports", "title": "Reports"} ], "query_params": {}, "tree": { "type": "root", "children": [ { "type": "main", "children": [ {"type": "title", "props": {"body": "Regional revenue"}}, {"type": "caption", "props": { "body": "Net revenue excludes refunds. Periods are UTC. Source: finance ledger."}}, { "key": "region", "type": "selectbox", "props": { "label": "Region", "options": ["All", "Europe", "AMER", "APAC"], "help": "Customer billing region; All includes every region.", "disabled": false }, "value": "All" }, { "key": "$$ID-8f2c9a1d4b6e7f30-None", "type": "button", "props": {"label": "Refresh data", "type": "secondary", "disabled": false} }, {"type": "metric", "props": {"label": "Net revenue", "value": "€1.2M", "delta": "+8%"}}, { "type": "dataframe", "props": {"column_config": {"month": {"label": "Month"}}}, "data": { "columns": [{"name": "month", "type": "string"}, {"name": "revenue", "type": "number"}], "row_count": 24, "column_count": 2, "preview": {"truncated": true, "rows": [{"month": "2026-01", "revenue": 120000}]}, "url": "/media/4f1c8ab27d9e5306.arrow" } }, { "type": "expander", "props": { "label": "How net revenue is calculated", "icon": ":material/info:", "expanded": false }, "children": [ {"type": "markdown", "props": { "body": "Gross invoiced amounts minus refunds and credit notes, converted to EUR at the invoice-date rate."}} } ] } ] }, {"type": "sidebar", "children": []}, {"type": "event", "children": []}, {"type": "bottom", "children": []} ] }, "actions": [ {"key": "region", "kind": "value"}, {"key": "$$ID-8f2c9a1d4b6e7f30-None", "kind": "trigger"} ], "limitations": [] } ``` -------------------------------- ### Search input implementation Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-06-29-text-input-types/product-spec.md Example of using the search input type to capture a user query. ```python import streamlit as st query = st.text_input("Search products", type="search") results = search(query) if query else [] st.write(results) ``` -------------------------------- ### RST output directive example Source: https://github.com/streamlit/streamlit/blob/develop/lib/streamlit/AGENTS.md Shows the RST directive for the output of a docstring example. Use this to display the app URL and set the iframe height. ```rst .. output:: https://doc-example.streamlit.app height: 200px ``` -------------------------------- ### SafeSessionState race condition example Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-03-05-parallel-fragments/tech-spec.md An example demonstrating how compound operations like read-modify-write are not atomic in SafeSessionState because the lock is released between operations. ```python @st.fragment(parallel=True) def increment(): # Thread A reads counter=5, releases lock val = st.session_state["counter"] # Thread B reads counter=5, releases lock st.session_state["counter"] = val + 1 # Both threads write 6 — lost update ``` -------------------------------- ### Global Install Directory Structure Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-05-11-streamlit-skills-cli/product-spec.md The directory structure of the developing-with-streamlit meta skill that is installed globally. It contains a SKILL.md file with meta skill instructions and a scripts/discover.py script that locates the project's bundled skills at runtime. ```text developing-with-streamlit/ ├── SKILL.md # Meta skill instructions └── scripts/ └── discover.py # Locates project's bundled skills ``` -------------------------------- ### App document Markdown example Source: https://github.com/streamlit/streamlit/wiki/pull-requests/16843/2026-08-28-agent-interface-opus5-product-spec Example of the app document format. It renders an app's output as Markdown with fenced blocks using st: info strings for inputs, metrics, charts, and dataframes. Charts are summarized with resource URLs, and dataframes show schema, shape, and a head. ```markdown # Sales Dashboard page: Overview (of Overview, Reports, Settings) · status: ready ## Filters ```st:inputs selectbox key=country label="Country" value="Japan" options=["Japan", "United States", "Germany"] date_input key=range label="Date range" value=["2026-01-01", "2026-06-30"] button key=refresh label="Refresh data" ``` ## Revenue Revenue grew **12%** year over year, driven by APAC. ```st:metric label="Revenue" value="¥12.4M" delta="+12%" ``` ```st:chart key=revenue-chart type=vega-lite mark=line x=month (temporal) y=revenue (quantitative) color=region (nominal) series=["APAC", "EMEA", "AMER"] points=72 x-range=2026-01..2026-06 y-range=0.8M..2.4M spec=/_stcore/agent/resource/ab12cd ``` ```st:dataframe key=top-accounts columns=[account (str), region (str), revenue (int)] rows=1240 showing=5 | account | region | revenue | | ------- | ------ | ------- | | Acme | APAC | 412000 | | Globex | APAC | 388000 | data=/_stcore/agent/resource/ef34gh ``` ``` -------------------------------- ### Run reproduction app with uv Source: https://github.com/streamlit/streamlit/wiki/issues/12065/investigation Runs the reproduction app for an installed Streamlit package using uv. ```bash uv run streamlit run agent-wiki/issues/12065/repro_app.py ``` -------------------------------- ### Branch naming examples Source: https://github.com/streamlit/streamlit/blob/develop/wiki/pull-requests.md Examples of branch names following the {type}/{brief-description} format in kebab-case. Types include feature, fix, refactor, chore, and docs. Names should be descriptive and specific (3-8 words), avoiding ticket/issue numbers. ```text feature/add-height-parameter-plotly-charts fix/dataframe-memory-leak-large-datasets refactor/element-width-height-logic chore/update-react-dependencies ``` -------------------------------- ### st.App with app metadata Source: https://github.com/streamlit/streamlit/wiki/pull-requests/16843/2026-09-06-agent-app-interface-gpt-sol-2-product-spec Python example of creating an st.App with static title and description metadata, used when the companion authoring slice is available. ```python app = st.App( "dashboard.py", app_title="Revenue explorer", app_description="Explore net revenue by billing region and quarter, in EUR.", ) ``` -------------------------------- ### Interactive Flow Prompt Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-05-11-streamlit-skills-cli/product-spec.md The interactive flow of the Streamlit Skills Installer. After running the command, the user is prompted to select an install mode: Project (recommended) or Global. The default choice is Project, indicated by [p]. ```text $ streamlit skills Streamlit Skills Installer Install mode: [p] Project (recommended) - skills available in this project only [g] Global - discovery skill available in all projects (requires network) Choice [p]: _ ``` -------------------------------- ### AI Reasoning Disclosure Example Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-02-21-compact-expander-status/product-spec.md Using a compact expander to show AI reasoning steps. ```python import streamlit as st # Compact thinking indicator with st.expander("Thought for 4 seconds", type="compact", icon=":material/psychology:"): st.write("Let me think about this problem step by step.") st.write("First, I need to understand what the user is asking for...") st.write("Here's my answer: The solution is 42.") ``` -------------------------------- ### Empty required selectbox example Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-08-18-required-widgets/product-spec.md Example of a required selectbox that starts empty by passing index=None. With required=True, an empty commit is blocked and an error is shown, but the widget still returns the empty default on initial render. ```python st.selectbox("Country", countries, index=None, required=True) ``` -------------------------------- ### Set up base environment on Rocky Linux / RHEL / Fedora Source: https://github.com/streamlit/streamlit/blob/develop/CONTRIBUTING.md Install essential packages, Node.js via nvm, Corepack, uv, and optionally GitHub CLI and ripgrep on Rocky Linux, RHEL, or Fedora. ```bash # Install some essentials $ sudo dnf install -y make gcc-c++ curl git rsync unzip protobuf-compiler # Set frontend dependencies: $ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash $ source ~/.bashrc $ nvm install node $ corepack enable # Install uv for Python $ curl -LsSf https://astral.sh/uv/install.sh | sh # (Recommended) Install GitHub CLI - used by AI agents for PR and issue management # See https://cli.github.com/ for installation instructions # (Recommended) Install ripgrep - used by AI agents for fast log/code search $ sudo dnf install -y ripgrep ``` -------------------------------- ### st.number_input with value=None and required=True Source: https://github.com/streamlit/streamlit/wiki/pull-requests/17023/implementation-plan Example of an empty required number_input field. Starts at min (or 0/0.0) and commits None when empty. ```python st.number_input("Amount", value=None, required=True) ``` -------------------------------- ### TOML configuration for browser.command Source: https://github.com/streamlit/streamlit/wiki/pull-requests/16761/implementation-plan Example TOML configuration setting the browser command to 'chrome'. ```toml [browser] command = "chrome" ``` -------------------------------- ### st.iframe height modes usage examples Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-03-13-st-iframe/product-spec.md Python examples showing how st.iframe auto-sizes to content for HTML strings and uses a fallback height for URLs. The first two calls demonstrate content-based sizing, while the last two show the default 400px fallback and an explicit height override. ```python # HTML auto-sizes to content st.iframe("

Short content

") # → small iframe st.iframe("
..." + "x" * 1000 + "
") # → taller iframe # URLs use sensible fallback st.iframe("https://example.com") # → 400px default st.iframe("https://example.com", height=600) # → explicit override ``` -------------------------------- ### Example 1: Prefix matching for autocomplete Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-03-25-selectbox-filter-mode/product-spec.md Uses filter_mode="prefix" in st.selectbox to filter countries by prefix, showing only options that start with the typed text. Typing "Aus" displays "Australia" and "Austria". ```python import streamlit as st # Countries sorted alphabetically countries = ["Argentina", "Armenia", "Australia", "Austria", ...] selected = st.selectbox( "Select Country", countries, filter_mode="prefix", ) # Typing "Aus" shows "Australia" and "Austria", not "Belarus" ``` -------------------------------- ### Windows layout planted on Ubuntu for filesystem tests Source: https://github.com/streamlit/streamlit/wiki/pull-requests/16715/implementation-plan Simulate a Windows Python installation on a POSIX system by planting python.exe and Lib/site-packages. Use monkeypatch.setattr(discover_mod.os, "name", "nt") to make the probe treat the OS as Windows. ```text /python.exe /Lib/site-packages/streamlit/... ``` -------------------------------- ### st.App callable entrypoint example Source: https://github.com/streamlit/streamlit/wiki/pull-requests/16333/implementation-plan Shows how to use st.App with a callable entrypoint. The callable must be synchronous and zero-argument. The source file of the callable is used as the app's filesystem anchor for config, secrets, pages, and other paths. The same module works with both `streamlit run app.py` and `uv run app.py`. ```python import streamlit as st def main() -> None: st.title("My app") app = st.App(main) if __name__ == "__main__": app.run() ``` -------------------------------- ### Cache Warming API Example Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-04-08-cache-background-refresh/product-spec.md Proposed API to pre-populate cache entries. Not included in the MVP; can be achieved by calling cached functions at startup or with custom initialization logic. ```python fetch_stock_prices.warm("AAPL", "GOOGL", "MSFT") ``` -------------------------------- ### Run load test with default settings Source: https://github.com/streamlit/streamlit/blob/develop/e2e_playwright/load_testing/README.md Runs the load test with default settings (5 sessions, all scenarios) using the make command. ```bash # Run with default settings (5 sessions, all scenarios) make run-e2e-test e2e_playwright/load_testing/test_load.py ``` -------------------------------- ### Prefer Enums Over Booleans: Example of st.text_input type parameter Source: https://github.com/streamlit/streamlit/blob/develop/specs/AGENTS.md Shows a bad example using a boolean for password and a good example using string enums for type, allowing easy expansion to email and tel. The exception is disabled=True/False, which is acceptable. ```python # Bad: Boolean limits expansion st.text_input("Password", password=True) # What if we want "email" type later? Another boolean? # Good: Enum allows expansion st.text_input("Password", type="password") st.text_input("Email", type="email") # Easy to add later st.text_input("Phone", type="tel") # And again ``` -------------------------------- ### Basic resizable columns Source: https://github.com/streamlit/streamlit/wiki/pull-requests/16556/resizable-columns-product-spec Basic example of resizable columns with three equal-width columns. Users can drag borders to resize adjacent columns. ```python import streamlit as st col1, col2, col3 = st.columns(3, resizable=True) with col1: st.header("Column 1") st.write("Drag the border to resize →") with col2: st.header("Column 2") st.write("Content here") with col3: st.header("Column 3") st.write("More content") ``` -------------------------------- ### Equivalent launcher modes Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-06-14-app-run-method/product-spec.md Comparison of different ways to launch a Streamlit application, including the new App.run() method. ```bash python app.py # new: App.run() on the existing `app` object uv run app.py # new: App.run() (the primary motivating use case) streamlit run app.py # unchanged: AST discovery finds `app` uvicorn app:app # unchanged: external ASGI server ``` -------------------------------- ### Commit message examples Source: https://github.com/streamlit/streamlit/blob/develop/wiki/pull-requests.md Example commit messages following the imperative verb format. Each message is concise and describes the change directly. ```text Add height parameter to plotly charts Fix memory leak in dataframe scrolling Refactor layout config validation logic ``` -------------------------------- ### Example Commands for Running Load Tests Source: https://github.com/streamlit/streamlit/blob/develop/e2e_playwright/load_testing/README.md Commands to run load tests with different scenarios and session counts. Use PYTEST_ADDOPTS to pass browser and session options. The -k flag filters scenarios by name. High session counts require significant system resources. ```bash # Run only the simple app scenario with 10 sessions (from repo root) PYTEST_ADDOPTS='--browser=chromium --num-sessions=10 -k simple_app' \ make run-e2e-test e2e_playwright/load_testing/test_load.py ``` ```bash # Run dataframe and widget scenarios with 25 sessions PYTEST_ADDOPTS='--browser=chromium --num-sessions=25 -k "dataframe_app or widget_heavy_app"' \ make run-e2e-test e2e_playwright/load_testing/test_load.py ``` ```bash # Run all scenarios with 50 sessions PYTEST_ADDOPTS='--browser=chromium --num-sessions=50' \ make run-e2e-test e2e_playwright/load_testing/test_load.py ``` -------------------------------- ### Fragment referencing an outside container Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-06-03-outside-container-writes/tech-spec.md An example demonstrating a fragment attempting to write to a container defined in the main script scope. ```python outside = st.container() @st.fragment def my_fragment(): outside.button("Click me") outside.write("Status: ok") ``` -------------------------------- ### Usage of st.tabs with key and on_change, and .open property Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-01-14-dynamic-tabs-expander/product-spec.md Shows how to create tabs with key and on_change="rerun", access the .open property on each tab, read the active tab label from session state, and note that non-container elements like st.button return None for .open. ```python tabs = st.tabs(["A", "B", "C"], key="my_tabs", on_change="rerun") # Each tab has .open property tabs[0].open # True if "A" is active, False otherwise tabs[1].open # True if "B" is active, False otherwise # Also accessible via session state st.session_state.my_tabs # Returns "A", "B", or "C" (active tab label) # Note: Other elements also have .open but it returns None button = st.button("Click") button.open # Always None (not a tab/expander/popover) ``` -------------------------------- ### Disable Export App-Wide Example Source: https://github.com/streamlit/streamlit/blob/develop/specs/2025-12-03-dataframe-disable-export/product-spec.md Example showing how to disable data export for all dataframes in an app by setting the config option and then displaying a dataframe. ```toml # .streamlit/config.toml [client] disableDataExport = true ``` ```python import pandas as pd import streamlit as st df = pd.DataFrame({"Name": ["Alice", "Bob"], "Salary": [100000, 120000]}) # Export is disabled for all dataframes st.dataframe(df) ``` -------------------------------- ### App.run() with configuration overrides Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-06-14-app-run-method/product-spec.md Using the config parameter to pin server settings like port and address programmatically. ```python if __name__ == "__main__": # Self-contained launcher that pins its own server settings, # with no config.toml or env vars required. app.run(config={"server.port": 8502, "server.address": "0.0.0.0"}) ``` -------------------------------- ### Future DuckDB relation adapter example Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-05-07-dataframe-lazy-load/product-spec.md Example of passing a DuckDB relation to `st.dataframe` for lazy rendering. Marked as a future Phase 3+ adapter. ```python # Future: DuckDB relation adapter (Phase 3+) rel = duckdb.sql("SELECT * FROM 'logs/*.parquet'") st.dataframe(rel) ``` -------------------------------- ### st.image with alt parameter examples Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-09-14-element-alt-text/product-spec.md Shows usage of alt for st.image with various argument types: string, list of strings, and list with None. Includes decorative alt="" and caption/alt distinction. Use for images where alt text is required for accessibility. ```python st.image("sunrise.jpg", alt="Sunrise over a mountain ridge") st.image("divider.svg", alt="") # decorative — st.image / st.pyplot only # caption is visible context; alt describes the visual. Never the same string. st.image( "chart.png", caption="Figure 1: Monthly active users, 2024", alt="Line chart of monthly active users rising from 12k in January to 48k in December", ) # exactly one alt per image, as with caption; use None to skip one on purpose st.image(["cat.png", "dog.png"], alt=["Orange tabby on a windowsill", "Black labrador"]) st.image(["logo.png", "chart.png"], alt=[None, "Revenue by quarter, up 12%"]) ``` -------------------------------- ### Tree structure with multiple fragments and main script Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-06-03-outside-container-writes/tech-spec.md Shows the resulting element tree when two fragments write to an outside container. Each fragment gets a stable wrapper slot between main-script elements, and the wrapper's internal cursor resets on rerun. ```text outside_container ├── "Header" (main script, index 0) ├── [fragment_a_wrapper] (index 1, stable across reruns) │ ├── button │ └── text ├── [fragment_b_wrapper] (index 2, stable across reruns) │ └── chart └── "Footer" (main script, index 3) ``` -------------------------------- ### Option 1: st.image with alt parameter Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-09-14-element-alt-text/product-spec.md Preferred option. Uses the short, familiar term 'alt' as the parameter name, matching HTML, React, and markdown conventions. The example shows how to provide alternative text for an image. ```python st.image("chart.png", alt="Line chart of monthly revenue") ``` -------------------------------- ### Gallery of cards with badges and link buttons Source: https://github.com/streamlit/streamlit/wiki/pull-requests/16613/alternative-opus-spec/product-spec Example showing a model registry gallery: creates three columns, each with a card containing badges, a summary, and a link button. Uses height="stretch" and horizontal container for badges. ```python import streamlit as st st.title("Model registry") for column, model in zip(st.columns(3), models): with column.card(model.name, model.preview_url, height="stretch"): with st.container(horizontal=True): st.badge(model.task, icon=":material/category:") st.badge(model.license) st.write(model.summary) st.link_button("Open", model.url, width="stretch") ``` -------------------------------- ### Enable Corepack for yarn Source: https://github.com/streamlit/streamlit/blob/develop/CONTRIBUTING.md Enable Corepack, which manages package managers like yarn. May require `brew install corepack` depending on how Node was installed. ```bash corepack enable ``` -------------------------------- ### Bad PR description example Source: https://github.com/streamlit/streamlit/blob/develop/wiki/pull-requests.md Example of a bad PR description that lists obvious changes, which should be omitted. Most of these are obvious from the code; only the parameter addition and deprecation are impactful/non-obvious. ```markdown > - Added `height` parameter to signature > - Updated layout config dataclass > - Added validation for height values > - Added unit tests > - Updated type hints ``` -------------------------------- ### Option 2: st.image with alt_text parameter Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-09-14-element-alt-text/product-spec.md Alternative option using the more explicit 'alt_text' name. This is longer and somewhat redundant, but is more explicit for authors unfamiliar with HTML. The example shows the same image with the alternative text parameter named 'alt_text'. ```python st.image("chart.png", alt_text="Line chart of monthly revenue") ``` -------------------------------- ### RST code-block example for docstring Source: https://github.com/streamlit/streamlit/blob/develop/lib/streamlit/AGENTS.md Shows the RST directive for a Python code block in a docstring example. Use this to present executable code with a filename label. ```rst .. code-block:: python :filename: streamlit_app.py import streamlit as st ``` -------------------------------- ### Test 1 - App.__init__ assigns config._main_script_path Source: https://github.com/streamlit/streamlit/wiki/pull-requests/15218/implementation-plan Two tests verifying that App.__init__ sets config._main_script_path when unset, and does not overwrite it when already set (e.g., by `streamlit run`). The first test creates a script in a temp directory and asserts the path is set to the resolved script path. The second test pre-sets the path to a CLI entry script and ensures it remains unchanged. ```python def test_init_sets_main_script_path_when_unset( self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: """App.__init__ should set config._main_script_path so script-level config.toml is discoverable under direct uvicorn launches.""" from streamlit import config monkeypatch.setattr(config, "_main_script_path", None) script = tmp_path / "app.py" script.write_text("import streamlit as st\n") monkeypatch.chdir(tmp_path) App("app.py") assert config._main_script_path == str(script.resolve()) ``` ```python def test_init_does_not_overwrite_main_script_path_when_set( self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: """App.__init__ must not clobber a value already set by `streamlit run`.""" from streamlit import config cli_script = tmp_path / "cli_entry.py" cli_script.touch() monkeypatch.setattr(config, "_main_script_path", str(cli_script)) App("dashboard/app.py") assert config._main_script_path == str(cli_script) ``` -------------------------------- ### Install uv with curl Source: https://github.com/streamlit/streamlit/blob/develop/CONTRIBUTING.md Installs uv, the Python dependency and virtual environment manager used by Streamlit. Requires a uv version allowed by `[tool.uv].required-version` in `pyproject.toml`. ```bash curl -LsSf https://astral.sh/uv/install.sh | sh ``` -------------------------------- ### E2E: Example usage of icon parameter Source: https://github.com/streamlit/streamlit/wiki/pull-requests/16418/implementation-plan Example usage of the icon parameter in st_heading.py for E2E tests, covering material icon, emoji, and material icon with divider. ```python st.title("Title with icon param", icon=":material/star:") st.header("Header with emoji icon", icon="🚀", divider="blue") st.subheader("Subheader with icon", icon=":material/bolt:") ``` -------------------------------- ### QW-1: Configure primaryForegroundColor, primaryHoverColor, primaryActiveColor Source: https://github.com/streamlit/streamlit/wiki/references/2026-08-11-theming-gaps-and-recommendations TOML configuration to fix on-primary foreground contrast issues. Sets text/icon color on primary surfaces and optional explicit hover/active background colors. ```toml primaryForegroundColor = "#111827" # text/icon color on primary surfaces primaryHoverColor = "#EAB308" # optional explicit hover bg primaryActiveColor = "#CA8A04" # optional explicit active bg ``` -------------------------------- ### Add parallel worker check to switch_page in execution_control.py Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-03-05-parallel-fragments/tech-spec.md Adds a call to _check_not_parallel_worker("st.switch_page") at the start of switch_page to prevent page navigation during parallel fragment execution, while allowing it during sequential reruns. ```python def switch_page(page: str | Path | Page, ...) -> NoReturn: ctx = get_script_run_ctx() if ctx: _check_not_parallel_worker("st.switch_page") # ... existing implementation ``` -------------------------------- ### Snowpark DataFrame example Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-05-07-dataframe-lazy-load/product-spec.md Example of passing a Snowpark DataFrame to `st.dataframe` for auto-lazy rendering. Requires a native lazy adapter with known row count and stable range access. ```python from snowflake.snowpark.functions import col orders = session.table("orders").filter(col("status") == "OPEN") st.dataframe(orders) ``` -------------------------------- ### Format frontend code with make frontend-format Source: https://github.com/streamlit/streamlit/blob/develop/CONTRIBUTING.md Formats JavaScript/TypeScript code using oxfmt. ```bash make frontend-format ``` -------------------------------- ### Run load tests and compare metrics Source: https://github.com/streamlit/streamlit/wiki/pull-requests/14553/starlette-optimization-plan-opus Use the existing load test infrastructure to benchmark optimizations. Run either the e2e test or the load test with a specific scenario and session count, then compare the listed key metrics against the Tornado baseline. ```bash # Run load test for specific scenario: make run-e2e-test st_command_test.py # or cd e2e_playwright/load_testing && uv run pytest test_load.py -k simple_app --num-sessions=80 # Compare key metrics: # - memory_rss_mb_peak # - memory_rss_mb_avg # - initial_load_time_ms.p50 # - initial_load_time_ms.p95 # - rerun_time_ms.p50 # - rerun_time_ms.p99 # - thread_count_max ``` -------------------------------- ### st.paginator wrapper example Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-03-22-st-pagination/product-spec.md Example usage of the proposed `st.paginator` wrapper that iterates over paginated items. This approach handles slicing automatically but is less flexible and only works with iterable data. ```python for item in st.paginator(orig_list, group_every=5, start_at_page=3): st.write(item) ``` -------------------------------- ### Polars lazy dataframe example Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-05-07-dataframe-lazy-load/product-spec.md Example of passing a Polars LazyFrame to `st.dataframe` for auto-lazy rendering. Requires a native lazy adapter with known row count and stable range access. ```python import polars as pl import streamlit as st events = pl.scan_parquet("s3://bucket/events/*.parquet") st.dataframe(events) ``` -------------------------------- ### Run autofix and check Source: https://github.com/streamlit/streamlit/wiki/pull-requests/16662/implementation-plan Commands to run the autofix and check steps for the project. This is part of the final implementation step. ```bash make autofix make check ``` -------------------------------- ### Example 3: Contains matching Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-03-25-selectbox-filter-mode/product-spec.md Uses filter_mode="contains" in st.selectbox to perform case-insensitive substring matching. Typing "example" shows all @example.com addresses. ```python import streamlit as st # Search anywhere in the string emails = ["alice@example.com", "bob@company.com", "carol@example.com"] selected = st.selectbox( "Select email", emails, filter_mode="contains", ) # Typing "example" shows all @example.com addresses ``` -------------------------------- ### Verification Commands from frontend/ Source: https://github.com/streamlit/streamlit/wiki/references/2026-09-03-improving-frontend-linting Run these commands from the frontend/ directory. The fast gate (yarn oxlint) must stay green in every PR. Full lint includes oxlint and per-workspace eslint with --max-warnings 0. Targeted tests are for files you touched. The optional command prints which testing-library rules are active. ```bash # Fast gate (must stay green in every PR) yarn oxlint # Full lint (oxlint + per-workspace eslint --max-warnings 0) yarn lint # Targeted tests for files you touched yarn test lib/src/components/path/Component.test.tsx # Optional: print which testing-library rules are actually active yarn exec eslint --print-config lib/src/components/widgets/Button/Button.test.tsx | less ``` -------------------------------- ### Responsive gallery with st.grid("auto") Source: https://github.com/streamlit/streamlit/wiki/pull-requests/15185/product-spec Creates a responsive gallery using `st.grid("auto", min_column_width=72, gap="xsmall")`. The grid creates as many columns as fit with no explicit max, useful for galleries. ```python import streamlit as st items = ["Apple", "Lemon", "Grape", "Kiwi", "Peach", "Cherry", "Coconut", "Pineapple"] with st.grid("auto", min_column_width=72, gap="xsmall"): for item in items: st.button(item, key=f"item-{item}", width="stretch") ``` -------------------------------- ### Run targeted verification tests and documentation command Source: https://github.com/streamlit/streamlit/wiki/pull-requests/17016/implementation-plan Use this command sequence to verify the implementation. It runs specific tests for errors, session state, element policies, and metrics, then builds the docs for the session state page, followed by 'make check'. ```bash uv run pytest \ lib/tests/streamlit/errors_test.py \ lib/tests/streamlit/runtime/state/session_state_test.py \ lib/tests/streamlit/elements/element_policies_test.py \ lib/tests/streamlit/runtime/metrics_util_test.py uv run streamlit docs st.session_state make check ``` -------------------------------- ### Static data inside function (bad example) Source: https://github.com/streamlit/streamlit/blob/develop/frontend/AGENTS.md Avoid recreating static data on every call. This example shows the anti-pattern of defining a map inside a function, which wastes memory and CPU. ```tsx // ❌ Recreated every call function getAlignment(config: AlignmentConfig) { const alignmentMap = { /* same data */ } return alignmentMap[config.alignment] } ``` -------------------------------- ### Enable static file serving in config.toml Source: https://github.com/streamlit/streamlit/blob/develop/specs/2026-03-13-st-iframe/product-spec.md Configuration to enable static file serving, allowing relative URLs like /app/static/... to serve files from the ./static directory. ```toml [server] enableStaticServing = true ``` -------------------------------- ### Module-level static data structure (good example) Source: https://github.com/streamlit/streamlit/blob/develop/frontend/AGENTS.md Define static lookup maps at module level to avoid recreation on every call. This example shows the recommended approach with a constant ALIGNMENT_MAP. ```tsx // ✅ Module-level - created once const ALIGNMENT_MAP: Record = { [Alignment.LEFT]: "left", [Alignment.CENTER]: "center", // ... } as const function getAlignment(config: AlignmentConfig) { return ALIGNMENT_MAP[config.alignment] } ``` -------------------------------- ### Example configurations for auth.logout_params Source: https://github.com/streamlit/streamlit/wiki/pull-requests/16297/implementation-plan Examples of configuring logout_params in secrets.toml for AWS Cognito, MS Entra, and custom providers. These configurations demonstrate how to rename parameters, drop defaults, and inject user claims. ```toml # AWS Cognito (rename post_logout_redirect_uri -> redirect_uri, drop id_token_hint) [auth] logout_params = { redirect_uri = "{post_logout_redirect_uri}", post_logout_redirect_uri = "", id_token_hint = "" } # MS Entra (experimental) [auth] logout_params = { logout_hint = "{email}" } # Custom provider [auth] logout_params = { returnTo = "{post_logout_redirect_uri}", post_logout_redirect_uri = "", id_token_hint = "", audience = "{sub}", federated = "true" } ```