APMSign in

>Agent Skill

@sverzijl/streamlit

skilldevelopment

When working with Streamlit web apps, data dashboards, ML/AI app UIs, interactive Python visualizations, or building data science applications with Python

pythongittesting
apm::install
$apm install @sverzijl/streamlit
apm::skill.md
---
name: streamlit
description: When working with Streamlit web apps, data dashboards, ML/AI app UIs, interactive Python visualizations, or building data science applications with Python
---

# Streamlit Skill

Comprehensive assistance with streamlit development, generated from official documentation.

## When to Use This Skill

This skill should be triggered when:
- Working with streamlit
- Asking about streamlit features or APIs
- Implementing streamlit solutions
- Debugging streamlit code
- Learning streamlit best practices

## Quick Reference

### Common Patterns

**Pattern 1:** Automate your tests with CI One of the key benefits of app testing is that tests can be automated using Continuous Integration (CI). By running tests automatically during development, you can validate that changes to your app don't break existing functionality. You can verify app code as you commit, catch bugs early, and prevent accidental breaks before deployment. There are many popular CI tools, including GitHub Actions, Jenkins, GitLab CI, Azure DevOps, and Circle CI. Streamlit app testing will integrate easily with any of them similar to any other Python tests. GitHub Actions Since many Streamlit apps (and all Community Cloud apps) are built in GitHub, this page uses examples from GitHub Actions. For more information about GitHub Actions, see: Quickstart for GitHub Actions GitHub Actions: About continuous integration GitHub Actions: Build & test Python Streamlit App Action Streamlit App Action provides an easy way to add automated testing to your app repository in GitHub. It also includes basic smoke testing for each page of your app without you writing any test code. To install Streamlit App Action, add a workflow .yml file to your repository's .github/workflows/ folder. For example: # .github/workflows/streamlit-app.yml name: Streamlit app on: push: branches: ["main"] pull_request: branches: ["main"] permissions: contents: read jobs: streamlit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.11" - uses: streamlit/streamlit-app-action@v0.0.3 with: app-path: streamlit_app.py Let's take a look in more detail at what this action workflow is doing. Triggering the workflow on: push: branches: ["main"] pull_request: branches: ["main"] This workflow will be triggered and execute tests on pull requests targeting the main branch, as well as any new commits pushed to the main branch. Note that it will also execute the tests on subsequent commits to any open pull requests. See GitHub Actions: Triggering a workflow for more information and examples. Setting up the test environment jobs: streamlit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.11" The workflow has a streamlit job that executes a series of steps. The job runs on a Docker container with the ubuntu-latest image. actions/checkout@v4 checks out the current repository code from GitHub and copies the code to the job environment. actions/setup-python@v5 installs Python version 3.11. Running the app tests - uses: streamlit/streamlit-app-action@v0.0.3 with: app-path: streamlit_app.py Streamlit App Action does the following: Install pytest and install any dependencies specified in requirements.txt. Run the built-in app smoke tests. Run any other Python tests found in the repository. starTipIf your app doesn't include requirements.txt in the repository root directory, you will need to add a step to install dependencies with your chosen package manager before running Streamlit App Action. The built-in smoke tests have the following behavior: Run the app specified at app-path as an AppTest. Validate that it completes successfully and does not result in an uncaught exception. Do the same for any additional pages/ of the app relative to app-path. If you want to run Streamlit App Action without the smoke tests, you can set skip-smoke: true. Linting your app code Linting is the automated checking of source code for programmatic and stylistic errors. This is done by using a lint tool (otherwise known as a linter). Linting is important to reduce errors and improve the overall quality of your code, especially for repositories with multiple developers or public repositories. You can add automated linting with Ruff by passing ruff: true to Streamlit App Action. - uses: streamlit/streamlit-app-action@v0.0.3 with: app-path: streamlit_app.py ruff: true starTipYou may want to add a pre-commit hook like ruff-pre-commit in your local development environment to fix linting errors before they get to CI. Viewing results If tests fail, the CI workflow will fail and you will see the results in GitHub. Console logs are available by clicking into the workflow run as described here. For higher-level test results, you can use pytest-results-action. You can combine this with Streamlit App Action as follows: # ... setup as above ... - uses: streamlit/streamlit-app-action@v0.0.3 with: app-path: streamlit_app.py # Add pytest-args to output junit xml pytest-args: -v --junit-xml=test-results.xml - if: always() uses: pmeier/pytest-results-action@v0.6.0 with: path: test-results.xml summary: true display-options: fEX Writing your own actions The above is just provided as an example. Streamlit App Action is a quick way to get started. Once you learn the basics of your CI tool of choice, it's easy to build and customize your own automated workflows. This is a great way to improve your overall productivity as a developer and the quality of your apps. Working example As a final working example example, take a look at our streamlit/llm-examples Actions, defined in this workflow file.arrow_backPrevious: Beyond the basicsarrow_forwardNext: ExampleforumStill have questions?Our forums are full of helpful information and Streamlit experts.

```
.yml
```

**Pattern 2:** config.toml config.toml is an optional file you can define for your working directory or global development environment. When config.toml is defined both globally and in your working directory, Streamlit combines the configuration options and gives precedence to the working-directory configuration. Additionally, you can use environment variables and command-line options to override additional configuration options. For more information, see Configuration options. File location To define your configuration locally or per-project, add .streamlit/config.toml to your working directory. Your working directory is wherever you call streamlit run. If you haven't previously created the .streamlit directory, you will need to add it. To define your configuration globally, you must first locate your global .streamlit directory. Streamlit adds this hidden directory to your OS user profile during installation. For MacOS/Linux, this will be ~/.streamlit/config.toml. For Windows, this will be %userprofile%/.streamlit/config.toml. File format config.toml is a TOML file. Example [client] showErrorDetails = "none" [theme] primaryColor = "#F63366" backgroundColor = "black" Available configuration options Below are all the sections and options you can have in your .streamlit/config.toml file. To see all configurations, use the following command in your terminal or CLI: streamlit config show Global [global] # By default, Streamlit displays a warning when a user sets both a widget # default value in the function defining the widget and a widget value via # the widget's key in `st.session_state`. # # If you'd like to turn off this warning, set this to True. # # Default: false disableWidgetStateDuplicationWarning = false # If True, will show a warning when you run a Streamlit-enabled script # via "python my_script.py". # # Default: true showWarningOnDirectExecution = true Logger [logger] # Level of logging for Streamlit's internal logger: "error", "warning", # "info", or "debug". # # Default: "info" level = "info" # String format for logging messages. If logger.datetimeFormat is set, # logger messages will default to `%(asctime)s.%(msecs)03d %(message)s`. # # See Python's documentation for available attributes: # https://docs.python.org/3/library/logging.html#formatter-objects # # Default: "%(asctime)s %(message)s" messageFormat = "%(asctime)s %(message)s" Client [client] # Controls whether uncaught app exceptions and deprecation warnings # are displayed in the browser. This can be one of the following: # # - "full" : In the browser, Streamlit displays app deprecation # warnings and exceptions, including exception types, # exception messages, and associated tracebacks. # - "stacktrace" : In the browser, Streamlit displays exceptions, # including exception types, generic exception messages, # and associated tracebacks. Deprecation warnings and # full exception messages will only print to the # console. # - "type" : In the browser, Streamlit displays exception types and # generic exception messages. Deprecation warnings, full # exception messages, and associated tracebacks only # print to the console. # - "none" : In the browser, Streamlit displays generic exception # messages. Deprecation warnings, full exception # messages, associated tracebacks, and exception types # will only print to the console. # - True : This is deprecated. Streamlit displays "full" # error details. # - False : This is deprecated. Streamlit displays "stacktrace" # error details. # # Default: "full" showErrorDetails = "full" # Change the visibility of items in the toolbar, options menu, # and settings dialog (top right of the app). # # Allowed values: # - "auto" : Show the developer options if the app is accessed through # localhost or through Streamlit Community Cloud as a developer. # Hide them otherwise. # - "developer" : Show the developer options. # - "viewer" : Hide the developer options. # - "minimal" : Show only options set externally (e.g. through # Streamlit Community Cloud) or through st.set_page_config. # If there are no options left, hide the menu. # # Default: "auto" toolbarMode = "auto" # Controls whether to display the default sidebar page navigation in a # multi-page app. This only applies when app's pages are defined by the # `pages/` directory. # # Default: true showSidebarNavigation = true Runner [runner] # Allows you to type a variable or string by itself in a single line of # Python code to write it to the app. # # Default: true magicEnabled = true # Handle script rerun requests immediately, rather than waiting for # script execution to reach a yield point. # # This makes Streamlit much more responsive to user interaction, but it # can lead to race conditions in apps that mutate session_state data # outside of explicit session_state assignment statements. # # Default: true fastReruns = true # Raise an exception after adding unserializable data to Session State. # # Some execution environments may require serializing all data in Session # State, so it may be useful to detect incompatibility during development, # or when the execution environment will stop supporting it in the future. # # Default: false enforceSerializableSessionState = false # Adjust how certain 'options' widgets like radio, selectbox, and # multiselect coerce Enum members. # # This is useful when the Enum class gets re-defined during a script # re-run. For more information, check out the docs: # https://docs.streamlit.io/develop/concepts/design/custom-classes#enums # # Allowed values: # - "off" : Disables Enum coercion. # - "nameOnly" : Enum classes can be coerced if their member names match. # - "nameAndValue" : Enum classes can be coerced if their member names AND # member values match. # # Default: "nameOnly" enumCoercion = "nameOnly" Server [server] # List of directories to watch for changes. # # By default, Streamlit watches files in the current working directory # and its subdirectories. Use this option to specify additional # directories to watch. Paths must be absolute. # # Default: [] folderWatchList = [] # List of directories to ignore for changes. # # By default, Streamlit watches files in the current working directory # and its subdirectories. Use this option to specify exceptions within # watched directories. Paths can be absolute or relative to the current # working directory. # # Example: ['/home/user1/env', 'relative/path/to/folder'] # # Default: [] folderWatchBlacklist = [] # Change the type of file watcher used by Streamlit, or turn it off # completely. # # Allowed values: # - "auto" : Streamlit will attempt to use the watchdog module, and # falls back to polling if watchdog isn't available. # - "watchdog" : Force Streamlit to use the watchdog module. # - "poll" : Force Streamlit to always use polling. # - "none" : Streamlit will not watch files. # # Default: "auto" fileWatcherType = "auto" # Symmetric key used to produce signed cookies. If deploying on multiple # replicas, this should be set to the same value across all replicas to ensure # they all share the same secret. # # Default: randomly generated secret key. cookieSecret = "a-random-key-appears-here" # If false, will attempt to open a browser window on start. # # Default: false unless (1) we are on a Linux box where DISPLAY is unset, or # (2) we are running in the Streamlit Atom plugin. headless = false # Whether to show a terminal prompt for the user's email address when # they run Streamlit (locally) for the first time. If you set # `server.headless=True`, Streamlit will not show this prompt. # # Default: true showEmailPrompt = true # Automatically rerun script when the file is modified on disk. # # Default: false runOnSave = false # The address where the server will listen for client and browser # connections. # # Use this if you want to bind the server to a specific address. # If set, the server will only be accessible from this address, and not from # any aliases (like localhost). # # Default: (unset) address = # The port where the server will listen for browser connections. # # Default: 8501 port = 8501 # The base path for the URL where Streamlit should be served from. # # Default: "" baseUrlPath = "" # Enables support for Cross-Origin Resource Sharing (CORS) protection, # for added security. # # If XSRF protection is enabled and CORS protection is disabled at the # same time, Streamlit will enable them both instead. # # Default: true enableCORS = true # Allowed list of origins. # # If CORS protection is enabled (`server.enableCORS=True`), use this # option to set a list of allowed origins that the Streamlit server will # accept traffic from. # # This config option does nothing if CORS protection is disabled. # # Example: ['http://example.com', 'https://streamlit.io'] # # Default: [] corsAllowedOrigins = [] # Enables support for Cross-Site Request Forgery (XSRF) protection, for # added security. # # If XSRF protection is enabled and CORS protection is disabled at the # same time, Streamlit will enable them both instead. # # Default: true enableXsrfProtection = true # Max size, in megabytes, for files uploaded with the file_uploader. # # Default: 200 maxUploadSize = 200 # Max size, in megabytes, of messages that can be sent via the WebSocket # connection. # # Default: 200 maxMessageSize = 200 # Enables support for websocket compression. # # Default: false enableWebsocketCompression = false # The interval (in seconds) at which the server pings the client to keep # the websocket connection alive. # # The default value should work for most deployments. However, if you're # experiencing frequent disconnections in certain proxy setups (e.g., # "Connection error" messages), you may want to try adjusting this value. # # Note: When you set this option, Streamlit automatically sets the ping # timeout to match this interval. For Tornado >=6.5, a value less than 30 # may cause connection issues. websocketPingInterval = # Enable serving files from a `static` directory in the running app's # directory. # # Default: false enableStaticServing = false # TTL in seconds for sessions whose websockets have been disconnected. # # The server may choose to clean up session state, uploaded files, etc # for a given session with no active websocket connection at any point # after this time has passed. # # Default: 120 disconnectedSessionTTL = 120 # Server certificate file for connecting via HTTPS. # Must be set at the same time as "server.sslKeyFile". # # ['DO NOT USE THIS OPTION IN A PRODUCTION ENVIRONMENT. It has not gone through # security audits or performance tests. For the production environment, we # recommend performing SSL termination by the load balancer or the reverse # proxy.'] sslCertFile = # Cryptographic key file for connecting via HTTPS. # Must be set at the same time as "server.sslCertFile". # # ['DO NOT USE THIS OPTION IN A PRODUCTION ENVIRONMENT. It has not gone through # security audits or performance tests. For the production environment, we # recommend performing SSL termination by the load balancer or the reverse # proxy.'] sslKeyFile = Browser [browser] # Internet address where users should point their browsers in order to # connect to the app. Can be IP address or DNS name and path. # # This is used to: # - Set the correct URL for CORS and XSRF protection purposes. # - Show the URL on the terminal # - Open the browser # # Default: "localhost" serverAddress = "localhost" # Whether to send usage statistics to Streamlit. # # Default: true gatherUsageStats = true # Port where users should point their browsers in order to connect to the # app. # # This is used to: # - Set the correct URL for XSRF protection purposes. # - Show the URL on the terminal (part of `streamlit run`). # - Open the browser automatically (part of `streamlit run`). # # This option is for advanced use cases. To change the port of your app, use # `server.Port` instead. # # Default: whatever value is set in server.port. serverPort = 8501 Mapbox [mapbox] # If you'd like to show maps using Mapbox rather than Carto, use this # to pass the Mapbox API token. # # THIS IS DEPRECATED. # # Instead of this, you should use either the MAPBOX_API_KEY environment variable or PyDeck's `api_keys` argument. # # This option will be removed on or after 2026-05-01. # # Default: "" token = "" Theme [theme] # The preset Streamlit theme that your custom theme inherits from. # # This can be one of the following: "light" or "dark". base = # Primary accent color. primaryColor = # Background color of the app. backgroundColor = # Background color used for most interactive widgets. secondaryBackgroundColor = # Color used for almost all text. textColor = # Red color used in the basic color palette. # # By default, this is #ff4b4b for the light theme and #ff2b2b for the # dark theme. # # If `redColor` is provided, and `redBackgroundColor` isn't, then # `redBackgroundColor` will be derived from `redColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. redColor = # Orange color used in the basic color palette. # # By default, this is #ffa421 for the light theme and #ff8700 for the # dark theme. # # If `orangeColor` is provided, and `orangeBackgroundColor` isn't, then # `orangeBackgroundColor` will be derived from `orangeColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. orangeColor = # Yellow color used in the basic color palette. # # By default, this is #faca2b for the light theme and #ffe312 for the # dark theme. # # If `yellowColor` is provided, and `yellowBackgroundColor` isn't, then # `yellowBackgroundColor` will be derived from `yellowColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. yellowColor = # Blue color used in the basic color palette. # # By default, this is #1c83e1 for the light theme and #0068c9 for the # dark theme. # # If a `blueColor` is provided, and `blueBackgroundColor` isn't, then # `blueBackgroundColor` will be derived from `blueColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. blueColor = # Green color used in the basic color palette. # # By default, this is #21c354 for the light theme and #09ab3b for the # dark theme. # # If `greenColor` is provided, and `greenBackgroundColor` isn't, then # `greenBackgroundColor` will be derived from `greenColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. greenColor = # Violet color used in the basic color palette. # # By default, this is #803df5 for both the light and dark themes. # # If a `violetColor` is provided, and `violetBackgroundColor` isn't, then # `violetBackgroundColor` will be derived from `violetColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. violetColor = # Gray color used in the basic color palette. # # By default, this is #a3a8b8 for the light theme and #555867 for the # dark theme. # # If `grayColor` is provided, and `grayBackgroundColor` isn't, then # `grayBackgroundColor` will be derived from `grayColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. grayColor = # Red background color used in the basic color palette. # # If `redColor` is provided, this defaults to `redColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #ff2b2b with 10% opacity for light theme and # #ff6c6c with 20% opacity for dark theme. redBackgroundColor = # Orange background color used for the basic color palette. # # If `orangeColor` is provided, this defaults to `orangeColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #ffa421 with 10% opacity for the light theme and # #ff8700 with 20% opacity for the dark theme. orangeBackgroundColor = # Yellow background color used for the basic color palette. # # If `yellowColor` is provided, this defaults to `yellowColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #ffff12 with 10% opacity for the light theme and # #ffff12 with 20% opacity for the dark theme. yellowBackgroundColor = # Blue background color used for the basic color palette. # # If `blueColor` is provided, this defaults to `blueColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #1c83ff with 10% opacity for the light theme and # #3d9df3 with 20% opacity for the dark theme. blueBackgroundColor = # Green background color used for the basic color palette. # # If `greenColor` is provided, this defaults to `greenColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #21c354 with 10% opacity for the light theme and # #3dd56d with 20% opacity for the dark theme. greenBackgroundColor = # Violet background color used for the basic color palette. # # If `violetColor` is provided, this defaults to `violetColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #9a5dff with 10% opacity for light theme and # #9a5dff with 20% opacity for dark theme. violetBackgroundColor = # Gray background color used for the basic color palette. # # If `grayColor` is provided, this defaults to `grayColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #31333f with 10% opacity for the light theme and # #808495 with 20% opacity for the dark theme. grayBackgroundColor = # Red text color used for the basic color palette. # # If `redColor` is provided, this defaults to `redColor`, darkened by 15% # for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #bd4043 for the light theme and #ff6c6c for the dark # theme. redTextColor = # Orange text color used for the basic color palette. # # If `orangeColor` is provided, this defaults to `orangeColor`, darkened # by 15% for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #e2660c for the light theme and #ffbd45 for the dark # theme. orangeTextColor = # Yellow text color used for the basic color palette. # # If `yellowColor` is provided, this defaults to `yellowColor`, darkened # by 15% for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #926c05 for the light theme and #ffffc2 for the dark # theme. yellowTextColor = # Blue text color used for the basic color palette. # # If `blueColor` is provided, this defaults to `blueColor`, darkened by # 15% for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #0054a3 for the light theme and #3d9df3 for the dark # theme. blueTextColor = # Green text color used for the basic color palette. # # If `greenColor` is provided, this defaults to `greenColor`, darkened by # 15% for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #158237 for the light theme and #5ce488 for the dark # theme. greenTextColor = # Violet text color used for the basic color palette. # # If `violetColor` is provided, this defaults to `violetColor`, darkened # by 15% for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #583f84 for the light theme and #b27eff for the dark # theme. violetTextColor = # Gray text color used for the basic color palette. # # If `grayColor` is provided, this defaults to `grayColor`, darkened by # 15% for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #31333f with 60% opacity for the light theme and # #fafafa with 60% opacity for the dark theme. grayTextColor = # Color used for all links. linkColor = # Whether or not links should be displayed with an underline. linkUnderline = # Background color used for code blocks. codeBackgroundColor = # The font family for all text, except code blocks. # # This can be one of the following: # - "sans-serif" # - "serif" # - "monospace" # - The `family` value for a custom font table under [[theme.fontFaces]] # - A comma-separated list of these (as a single string) to specify # fallbacks # # For example, you can use the following: # # font = "cool-font, fallback-cool-font, sans-serif" font = # An array of fonts to use in your app. # # Each font in the array is a table (dictionary) that can have the # following attributes, closely resembling CSS font-face definitions: # - family # - url # - weight (optional) # - style (optional) # - unicodeRange (optional) # # To host a font with your app, enable static file serving with # `server.enableStaticServing=true`. # # You can define multiple [[theme.fontFaces]] tables, including multiple # tables with the same family if your font is defined by multiple files. # # For example, a font hosted with your app may have a [[theme.fontFaces]] # table as follows: # # [[theme.fontFaces]] # family = "font_name" # url = "app/static/font_file.woff" # weight = "400" # style = "normal" fontFaces = # The root font size (in pixels) for the app. # # This determines the overall scale of text and UI elements. This is a # positive integer. # # If this isn't set, the font size will be 16px. baseFontSize = # The root font weight for the app. # # This determines the overall weight of text and UI elements. This is an # integer multiple of 100. Values can be between 100 and 600, inclusive. # # If this isn't set, the font weight will be set to 400 (normal weight). baseFontWeight = # The font family to use for headings. # # This can be one of the following: # - "sans-serif" # - "serif" # - "monospace" # - The `family` value for a custom font table under [[theme.fontFaces]] # - A comma-separated list of these (as a single string) to specify # fallbacks # # If this isn't set, Streamlit uses `theme.font` for headings. headingFont = # One or more font sizes for h1-h6 headings. # # If no sizes are set, Streamlit will use the default sizes for h1-h6 # headings. Heading font sizes set in [theme] are not inherited by # [theme.sidebar]. The following sizes are used by default: # [ # "2.75rem", # h1 (1.5rem for sidebar) # "2.25rem", # h2 (1.25rem for sidebar) # "1.75rem", # h3 (1.125rem for sidebar) # "1.5rem", # h4 (1rem for sidebar) # "1.25rem", # h5 (0.875rem for sidebar) # "1rem", # h6 (0.75rem for sidebar) # ] # # If you specify an array with fewer than six sizes, the unspecified # heading sizes will be the default values. For example, you can use the # following array to set the font sizes for h1-h3 headings while keeping # h4-h6 headings at their default sizes: # headingFontSizes = ["3rem", "2.875rem", "2.75rem"] # # Setting a single value (not in an array) will set the font size for all # h1-h6 headings to that value: # headingFontSizes = "2.75rem" # # Font sizes can be specified in pixels or rem, but rem is recommended. headingFontSizes = # One or more font weights for h1-h6 headings. # # If no weights are set, Streamlit will use the default weights for h1-h6 # headings. Heading font weights set in [theme] are not inherited by # [theme.sidebar]. The following weights are used by default: # [ # 700, # h1 (bold) # 600, # h2 (semi-bold) # 600, # h3 (semi-bold) # 600, # h4 (semi-bold) # 600, # h5 (semi-bold) # 600, # h6 (semi-bold) # ] # # If you specify an array with fewer than six weights, the unspecified # heading weights will be the default values. For example, you can use # the following array to set the font weights for h1-h2 headings while # keeping h3-h6 headings at their default weights: # headingFontWeights = [800, 700] # # Setting a single value (not in an array) will set the font weight for # all h1-h6 headings to that value: # headingFontWeights = 500 headingFontWeights = # The font family to use for code (monospace) in the sidebar. # # This can be one of the following: # - "sans-serif" # - "serif" # - "monospace" # - The `family` value for a custom font table under [[theme.fontFaces]] # - A comma-separated list of these (as a single string) to specify # fallbacks codeFont = # The font size (in pixels or rem) for code blocks and code text. # # This applies to font in code blocks, `st.json`, and `st.help`. It # doesn't apply to inline code, which is set by default to 0.75em. # # If this isn't set, the code font size will be 0.875rem. codeFontSize = # The font weight for code blocks and code text. # # This applies to font in inline code, code blocks, `st.json`, and # `st.help`. This is an integer multiple of 100. Values can be between # 100 and 900, inclusive. # # If this isn't set, the code font weight will be 400 (normal weight). codeFontWeight = # The radius used as basis for the corners of most UI elements. # # This can be one of the following: # - "none" # - "small" # - "medium" # - "large" # - "full" # - The number in pixels or rem. # # For example, you can use "10px", "0.5rem", or "2rem". To follow best # practices, use rem instead of pixels when specifying a numeric size. baseRadius = # The radius used as basis for the corners of buttons. # # This can be one of the following: # - "none" # - "small" # - "medium" # - "large" # - "full" # - The number in pixels or rem. # # For example, you can use "10px", "0.5rem", or "2rem". To follow best # practices, use rem instead of pixels when specifying a numeric size. # # If this isn't set, Streamlit uses `theme.baseRadius` instead. buttonRadius = # The color of the border around elements. borderColor = # The color of the border around dataframes and tables. # # If this isn't set, Streamlit uses `theme.borderColor` instead. dataframeBorderColor = # The background color of the dataframe's header. # # This color applies to all non-interior cells of the dataframe. This # includes the header row, the row-selection column (if present), and # the bottom row of data editors with a dynamic number of rows. If this # isn't set, Streamlit uses a mix of `theme.backgroundColor` and # `theme.secondaryBackgroundColor`. dataframeHeaderBackgroundColor = # Whether to show a border around input widgets. showWidgetBorder = # Whether to show a vertical separator between the sidebar and the main # content area. showSidebarBorder = # An array of colors to use for categorical chart data. # # This is a list of one or more color strings which are applied in order # to categorical data. These colors apply to Plotly, Altair, and # Vega-Lite charts. # # Invalid colors are skipped, and colors repeat cyclically if there are # more categories than colors. If no chart categorical colors are set, # Streamlit uses a default set of colors. # # For light themes, the following colors are the default: # [ # "#0068c9", # blue80 # "#83c9ff", # blue40 # "#ff2b2b", # red80 # "#ffabab", # red40 # "#29b09d", # blueGreen80 # "#7defa1", # green40 # "#ff8700", # orange80 # "#ffd16a", # orange50 # "#6d3fc0", # purple80 # "#d5dae5", # gray40 # ] # For dark themes, the following colors are the default: # [ # "#83c9ff", # blue40 # "#0068c9", # blue80 # "#ffabab", # red40 # "#ff2b2b", # red80 # "#7defa1", # green40 # "#29b09d", # blueGreen80 # "#ffd16a", # orange50 # "#ff8700", # orange80 # "#6d3fc0", # purple80 # "#d5dae5", # gray40 # ] chartCategoricalColors = # An array of ten colors to use for sequential or continuous chart data. # # The ten colors create a gradient color scale. These colors apply to # Plotly, Altair, and Vega-Lite charts. # # Invalid color strings are skipped. If there are not exactly ten # valid colors specified, Streamlit uses a default set of colors. # # For light themes, the following colors are the default: # [ # "#e4f5ff", #blue10 # "#c7ebff", #blue20 # "#a6dcff", #blue30 # "#83c9ff", #blue40 # "#60b4ff", #blue50 # "#3d9df3", #blue60 # "#1c83e1", #blue70 # "#0068c9", #blue80 # "#0054a3", #blue90 # "#004280", #blue100 # ] # For dark themes, the following colors are the default: # [ # "#004280", #blue100 # "#0054a3", #blue90 # "#0068c9", #blue80 # "#1c83e1", #blue70 # "#3d9df3", #blue60 # "#60b4ff", #blue50 # "#83c9ff", #blue40 # "#a6dcff", #blue30 # "#c7ebff", #blue20 # "#e4f5ff", #blue10 # ] chartSequentialColors = Sidebar theme [theme.sidebar] # Primary accent color. primaryColor = # Background color of the app. backgroundColor = # Background color used for most interactive widgets. secondaryBackgroundColor = # Color used for almost all text. textColor = # Red color used in the basic color palette. # # By default, this is #ff4b4b for the light theme and #ff2b2b for the # dark theme. # # If `redColor` is provided, and `redBackgroundColor` isn't, then # `redBackgroundColor` will be derived from `redColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. redColor = # Orange color used in the basic color palette. # # By default, this is #ffa421 for the light theme and #ff8700 for the # dark theme. # # If `orangeColor` is provided, and `orangeBackgroundColor` isn't, then # `orangeBackgroundColor` will be derived from `orangeColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. orangeColor = # Yellow color used in the basic color palette. # # By default, this is #faca2b for the light theme and #ffe312 for the # dark theme. # # If `yellowColor` is provided, and `yellowBackgroundColor` isn't, then # `yellowBackgroundColor` will be derived from `yellowColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. yellowColor = # Blue color used in the basic color palette. # # By default, this is #1c83e1 for the light theme and #0068c9 for the # dark theme. # # If a `blueColor` is provided, and `blueBackgroundColor` isn't, then # `blueBackgroundColor` will be derived from `blueColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. blueColor = # Green color used in the basic color palette. # # By default, this is #21c354 for the light theme and #09ab3b for the # dark theme. # # If `greenColor` is provided, and `greenBackgroundColor` isn't, then # `greenBackgroundColor` will be derived from `greenColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. greenColor = # Violet color used in the basic color palette. # # By default, this is #803df5 for both the light and dark themes. # # If a `violetColor` is provided, and `violetBackgroundColor` isn't, then # `violetBackgroundColor` will be derived from `violetColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. violetColor = # Gray color used in the basic color palette. # # By default, this is #a3a8b8 for the light theme and #555867 for the # dark theme. # # If `grayColor` is provided, and `grayBackgroundColor` isn't, then # `grayBackgroundColor` will be derived from `grayColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. grayColor = # Red background color used in the basic color palette. # # If `redColor` is provided, this defaults to `redColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #ff2b2b with 10% opacity for light theme and # #ff6c6c with 20% opacity for dark theme. redBackgroundColor = # Orange background color used for the basic color palette. # # If `orangeColor` is provided, this defaults to `orangeColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #ffa421 with 10% opacity for the light theme and # #ff8700 with 20% opacity for the dark theme. orangeBackgroundColor = # Yellow background color used for the basic color palette. # # If `yellowColor` is provided, this defaults to `yellowColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #ffff12 with 10% opacity for the light theme and # #ffff12 with 20% opacity for the dark theme. yellowBackgroundColor = # Blue background color used for the basic color palette. # # If `blueColor` is provided, this defaults to `blueColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #1c83ff with 10% opacity for the light theme and # #3d9df3 with 20% opacity for the dark theme. blueBackgroundColor = # Green background color used for the basic color palette. # # If `greenColor` is provided, this defaults to `greenColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #21c354 with 10% opacity for the light theme and # #3dd56d with 20% opacity for the dark theme. greenBackgroundColor = # Violet background color used for the basic color palette. # # If `violetColor` is provided, this defaults to `violetColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #9a5dff with 10% opacity for light theme and # #9a5dff with 20% opacity for dark theme. violetBackgroundColor = # Gray background color used for the basic color palette. # # If `grayColor` is provided, this defaults to `grayColor` using 10% # opacity for the light theme and 20% opacity for the dark theme. # # Otherwise, this is #31333f with 10% opacity for the light theme and # #808495 with 20% opacity for the dark theme. grayBackgroundColor = # Red text color used for the basic color palette. # # If `redColor` is provided, this defaults to `redColor`, darkened by 15% # for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #bd4043 for the light theme and #ff6c6c for the dark # theme. redTextColor = # Orange text color used for the basic color palette. # # If `orangeColor` is provided, this defaults to `orangeColor`, darkened # by 15% for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #e2660c for the light theme and #ffbd45 for the dark # theme. orangeTextColor = # Yellow text color used for the basic color palette. # # If `yellowColor` is provided, this defaults to `yellowColor`, darkened # by 15% for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #926c05 for the light theme and #ffffc2 for the dark # theme. yellowTextColor = # Blue text color used for the basic color palette. # # If `blueColor` is provided, this defaults to `blueColor`, darkened by # 15% for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #0054a3 for the light theme and #3d9df3 for the dark # theme. blueTextColor = # Green text color used for the basic color palette. # # If `greenColor` is provided, this defaults to `greenColor`, darkened by # 15% for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #158237 for the light theme and #5ce488 for the dark # theme. greenTextColor = # Violet text color used for the basic color palette. # # If `violetColor` is provided, this defaults to `violetColor`, darkened # by 15% for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #583f84 for the light theme and #b27eff for the dark # theme. violetTextColor = # Gray text color used for the basic color palette. # # If `grayColor` is provided, this defaults to `grayColor`, darkened by # 15% for the light theme and lightened by 15% for the dark theme. # # Otherwise, this is #31333f with 60% opacity for the light theme and # #fafafa with 60% opacity for the dark theme. grayTextColor = # Color used for all links. linkColor = # Whether or not links should be displayed with an underline. linkUnderline = # Background color used for code blocks. codeBackgroundColor = # The font family for all text, except code blocks. # # This can be one of the following: # - "sans-serif" # - "serif" # - "monospace" # - The `family` value for a custom font table under [[theme.fontFaces]] # - A URL to a CSS file in the format of "<font name>:<url>" (like # "Nunito:https://fonts.googleapis.com/css2?family=Nunito&display=swap") # - A comma-separated list of these (as a single string) to specify # fallbacks # # For example, you can use the following: # # font = "cool-font, fallback-cool-font, sans-serif" font = # The font family to use for headings. # # This can be one of the following: # - "sans-serif" # - "serif" # - "monospace" # - The `family` value for a custom font table under [[theme.fontFaces]] # - A URL to a CSS file in the format of "<font name>:<url>" (like # "Nunito:https://fonts.googleapis.com/css2?family=Nunito&display=swap") # - A comma-separated list of these (as a single string) to specify # fallbacks # # If this isn't set, Streamlit uses `theme.font` for headings. headingFont = # One or more font sizes for h1-h6 headings. # # If no sizes are set, Streamlit will use the default sizes for h1-h6 # headings. Heading font sizes set in [theme] are not inherited by # [theme.sidebar]. The following sizes are used by default: # [ # "2.75rem", # h1 (1.5rem for sidebar) # "2.25rem", # h2 (1.25rem for sidebar) # "1.75rem", # h3 (1.125rem for sidebar) # "1.5rem", # h4 (1rem for sidebar) # "1.25rem", # h5 (0.875rem for sidebar) # "1rem", # h6 (0.75rem for sidebar) # ] # # If you specify an array with fewer than six sizes, the unspecified # heading sizes will be the default values. For example, you can use the # following array to set the font sizes for h1-h3 headings while keeping # h4-h6 headings at their default sizes: # headingFontSizes = ["3rem", "2.875rem", "2.75rem"] # # Setting a single value (not in an array) will set the font size for all # h1-h6 headings to that value: # headingFontSizes = "2.75rem" # # Font sizes can be specified in pixels or rem, but rem is recommended. headingFontSizes = # One or more font weights for h1-h6 headings. # # If no weights are set, Streamlit will use the default weights for h1-h6 # headings. Heading font weights set in [theme] are not inherited by # [theme.sidebar]. The following weights are used by default: # [ # 700, # h1 (bold) # 600, # h2 (semi-bold) # 600, # h3 (semi-bold) # 600, # h4 (semi-bold) # 600, # h5 (semi-bold) # 600, # h6 (semi-bold) # ] # # If you specify an array with fewer than six weights, the unspecified # heading weights will be the default values. For example, you can use # the following array to set the font weights for h1-h2 headings while # keeping h3-h6 headings at their default weights: # headingFontWeights = [800, 700] # # Setting a single value (not in an array) will set the font weight for # all h1-h6 headings to that value: # headingFontWeights = 500 headingFontWeights = # The font family to use for code (monospace) in the sidebar. # # This can be one of the following: # - "sans-serif" # - "serif" # - "monospace" # - The `family` value for a custom font table under [[theme.fontFaces]] # - A URL to a CSS file in the format of "<font name>:<url>" (like # "'Space Mono':https://fonts.googleapis.com/css2?family=Space+Mono&display=swap") # - A comma-separated list of these (as a single string) to specify # fallbacks codeFont = # The font size (in pixels or rem) for code blocks and code text. # # This applies to font in code blocks, `st.json`, and `st.help`. It # doesn't apply to inline code, which is set by default to 0.75em. # # If this isn't set, the code font size will be 0.875rem. codeFontSize = # The font weight for code blocks and code text. # # This applies to font in inline code, code blocks, `st.json`, and # `st.help`. This is an integer multiple of 100. Values can be between # 100 and 600, inclusive. # # If this isn't set, the code font weight will be 400 (normal weight). codeFontWeight = # The radius used as basis for the corners of most UI elements. # # This can be one of the following: # - "none" # - "small" # - "medium" # - "large" # - "full" # - The number in pixels or rem. # # For example, you can use "10px", "0.5rem", or "2rem". To follow best # practices, use rem instead of pixels when specifying a numeric size. baseRadius = # The radius used as basis for the corners of buttons. # # This can be one of the following: # - "none" # - "small" # - "medium" # - "large" # - "full" # - The number in pixels or rem. # # For example, you can use "10px", "0.5rem", or "2rem". To follow best # practices, use rem instead of pixels when specifying a numeric size. # # If this isn't set, Streamlit uses `theme.baseRadius` instead. buttonRadius = # The color of the border around elements. borderColor = # The color of the border around dataframes and tables. # # If this isn't set, Streamlit uses `theme.borderColor` instead. dataframeBorderColor = # The background color of the dataframe's header. # # This color applies to all non-interior cells of the dataframe. This # includes the header row, the row-selection column (if present), and # the bottom row of data editors with a dynamic number of rows. If this # isn't set, Streamlit uses a mix of `theme.backgroundColor` and # `theme.secondaryBackgroundColor`. dataframeHeaderBackgroundColor = # Whether to show a border around input widgets. showWidgetBorder = Secrets [secrets] # List of locations where secrets are searched. # # An entry can be a path to a TOML file or directory path where # Kubernetes style secrets are saved. Order is important, import is # first to last, so secrets in later files will take precedence over # earlier ones. # # Default: [ <path to local environment's secrets.toml file>, <path to project's secrets.toml file>,] files = [ "~/.streamlit/secrets.toml", "~/project directory/.streamlit/secrets.toml",] arrow_backPrevious: Configurationarrow_forwardNext: st.get_optionforumStill have questions?Our forums are full of helpful information and Streamlit experts.

```
config.toml
```

**Pattern 3:** Get started with app testing This guide will cover a simple example of how tests are structured within a project and how to execute them with pytest. After seeing the big picture, keep reading to learn about the Fundamentals of app testing: Initializing and running a simulated app Retrieving elements Manipulating widgets Inspecting the results Streamlit's app testing framework is not tied to any particular testing tool, but we'll use pytest for our examples since it is one of the most common Python test frameworks. To try out the examples in this guide, be sure to install pytest into your Streamlit development environment before you begin: pip install pytest A simple testing example with pytest This section explains how a simple test is structured and executed with pytest. For a comprehensive introduction to pytest, check out Real Python's guide to Effective Python testing with pytest. How pytest is structured pytest uses a naming convention for files and functions to execute tests conveniently. Name your test scripts of the form test_<name>.py or <name>_test.py. For example, you can use test_myapp.py or myapp_test.py. Within your test scripts, each test is written as a function. Each function is named to begin or end with test. We will prefix all our test scripts and test functions with test_ for our examples in this guide. You can write as many tests (functions) within a single test script as you want. When calling pytest in a directory, all test_<name>.py files within it will be used for testing. This includes files within subdirectories. Each test_<something> function within those files will be executed as a test. You can place test files anywhere in your project directory, but it is common to collect tests into a designated tests/ directory. For other ways to structure and execute tests, check out How to invoke pytest in the pytest docs. Example project with app testing Consider the following project: myproject/ ├── app.py └── tests/ └── test_app.py Main app file: """app.py""" import streamlit as st # Initialize st.session_state.beans st.session_state.beans = st.session_state.get("beans", 0) st.title("Bean counter :paw_prints:") addend = st.number_input("Beans to add", 0, 10) if st.button("Add"): st.session_state.beans += addend st.markdown(f"Beans counted: {st.session_state.beans}") Testing file: """test_app.py""" from streamlit.testing.v1 import AppTest def test_increment_and_add(): """A user increments the number input, then clicks Add""" at = AppTest.from_file("app.py").run() at.number_input[0].increment().run() at.button[0].click().run() assert at.markdown[0].value == "Beans counted: 1" Let's take a quick look at what's in this app and test before we run it. The main app file (app.py) contains four elements when rendered: st.title, st.number_input, st.button, and st.markdown. The test script (test_app.py) includes a single test (the function named test_increment_and_add). We'll cover test syntax in more detail in the latter half of this guide, but here's a brief explanation of what this test does: Initialize the simulated app and execute the first script run. at = AppTest.from_file("app.py").run() Simulate a user clicking the plus icon (add) to increment the number input (and the resulting script rerun). at.number_input[0].increment().run() Simulate a user clicking the "Add" button (and the resulting script rerun). at.button[0].click().run() Check if the correct message is displayed at the end. assert at.markdown[0].value == "Beans counted: 1" Assertions are the heart of tests. When the assertion is true, the test passes. When the assertion is false, the test fails. A test can have multiple assertions, but keeping tests tightly focused is good practice. When tests focus on a single behavior, it is easier to understand and respond to failure. Try out a simple test with pytest Copy the files above into a new "myproject" directory. Open a terminal and change directory to your project. cd myproject Execute pytest: pytest The test should execute successfully. Your terminal should show something like this: By executing pytest at the root of your project directory, all Python files with the test prefix (test_<name>.py) will be scanned for test functions. Within each test file, each function with the test prefix will be executed as a test. pytest then counts successes and itemizes failures. You can also direct pytest to only scan your testing directory. For example, from the root of your project directory, execute: pytest tests/ Handling file paths and imports with pytest Imports and paths within a test script should be relative to the directory where pytest is called. That is why the test function uses the path app.py instead of ../app.py even though the app file is one directory up from the test script. You'll usually call pytest from the directory containing your main app file. This is typically the root of your project directory. Additionally, if .streamlit/ is present in the directory where you call pytest, any config.toml and secrets.toml within it will be accessible to your simulated app. For example, your simulated app will have access to the config.toml and secrets.toml files in this common setup: Project structure: myproject/ ├── .streamlit/ │ ├── config.toml │ └── secrets.toml ├── app.py └── tests/ └── test_app.py Initialization within test_app.py: # Path to app file is relative to myproject/ at = AppTest.from_file("app.py").run() Command to execute tests: cd myproject pytest tests/ Fundamentals of app testing Now that you understand the basics of pytest let's dive into using Streamlit's app testing framework. Every test begins with initializing and running your simulated app. Additional commands are used to retrieve, manipulate, and inspect elements. On the next page, we'll go Beyond the basics and cover more advanced scenarios like working with secrets, Session State, or multipage apps. How to initialize and run a simulated app To test a Streamlit app, you must first initialize an instance of AppTest with the code for one page of your app. There are three methods for initializing a simulated app. These are provided as class methods to AppTest. We will focus on AppTest.from_file() which allows you to provide a path to a page of your app. This is the most common scenario for building automated tests during app development. AppTest.from_string() and AppTest.from_function() may be helpful for some simple or experimental scenarios. Let's continue with the example from above. Recall the testing file: """test_app.py""" from streamlit.testing.v1 import AppTest def test_increment_and_add(): """A user increments the number input, then clicks Add""" at = AppTest.from_file("app.py").run() at.number_input[0].increment().run() at.button[0].click().run() assert at.markdown[0].value == "Beans counted: 1" Look at the first line in the test function: at = AppTest.from_file("app.py").run() This is doing two things and is equivalent to: # Initialize the app. at = AppTest.from_file("app.py") # Run the app. at.run() AppTest.from_file() returns an instance of AppTest, initialized with the contents of app.py. The .run() method is used to run the app for the first time. Looking at the test, notice that the .run() method manually executes each script run. A test must explicitly run the app each time. This applies to the app's first run and any rerun resulting from simulated user input. How to retrieve elements The attributes of the AppTest class return sequences of elements. The elements are sorted according to display order in the rendered app. Specific elements can be retrieved by index. Additionally, widgets with keys can be retrieved by key. Retrieve elements by index Each attribute of AppTest returns a sequence of the associated element type. Specific elements can be retrieved by index. In the above example, at.number_input returns a sequence of all st.number_input elements in the app. Thus, at.number_input[0] is the first such element in the app. Similarly, at.markdown returns a collection of all st.markdown elements where at.markdown[0] is the first such element. Check out the current list of supported elements in the "Attributes" section of the AppTest class or the App testing cheat sheet. You can also use the .get() method and pass the attribute's name. at.get("number_input") and at.get("markdown") are equivalent to at.number_input and at.markdown, respectively. The returned sequence of elements is ordered by appearance on the page. If containers are used to insert elements in a different order, these sequences may not match the order within your code. Consider the following example where containers are used to switch the order of two buttons on the page: import streamlit as st first = st.container() second = st.container() second.button("A") first.button("B") If the above app was tested, the first button (at.button[0]) would be labeled "B" and the second button (at.button[1]) would be labeled "A." As true assertions, these would be: assert at.button[0].label == "B" assert at.button[1].label == "A" Retrieve widgets by key You can retrieve keyed widgets by their keys instead of their order on the page. The key of the widget is passed as either an arg or kwarg. For example, look at this app and the following (true) assertions: import streamlit as st st.button("Next", key="submit") st.button("Back", key="cancel") assert at.button(key="submit").label == "Next" assert at.button("cancel").label == "Back" Retrieve containers You can also narrow down your sequences of elements by retrieving specific containers. Each retrieved container has the same attributes as AppTest. For example, at.sidebar.checkbox returns a sequence of all checkboxes in the sidebar. at.main.selectbox returns the sequence of all selectboxes in the main body of the app (not in the sidebar). For AppTest.columns and AppTest.tabs, a sequence of containers is returned. So at.columns[0].button would be the sequence of all buttons in the first column appearing in the app. How to manipulate widgets All widgets have a universal .set_value() method. Additionally, many widgets have specific methods for manipulating their value. The names of Testing element classes closely match the names of the AppTest attributes. For example, look at the return type of AppTest.button to see the corresponding class of Button. Aside from setting the value of a button with .set_value(), you can also use .click(). Check out each testing element class for its specific methods. How to inspect elements All elements, including widgets, have a universal .value property. This returns the contents of the element. For widgets, this is the same as the return value or value in Session State. For non-input elements, this will be the value of the primary contents argument. For example, .value returns the value of body for st.markdown or st.error. It returns the value of data for st.dataframe or st.table. Additionally, you can check many other details for widgets like labels or disabled status. Many parameters are available for inspection, but not all. Use linting software to see what is currently supported. Here's an example: import streamlit as st st.selectbox("A", [1,2,3], None, help="Pick a number", placeholder="Pick me") assert at.selectbox[0].value == None assert at.selectbox[0].label == "A" assert at.selectbox[0].options == ["1","2","3"] assert at.selectbox[0].index == None assert at.selectbox[0].help == "Pick a number" assert at.selectbox[0].placeholder == "Pick me" assert at.selectbox[0].disabled == False starTipNote that the options for st.selectbox were declared as integers but asserted as strings. As noted in the documentation for st.selectbox, options are cast internally to strings. If you ever find yourself getting unexpected results, check the documentation carefully for any notes about recasting types internally.arrow_backPrevious: App testingarrow_forwardNext: Beyond the basicsforumStill have questions?Our forums are full of helpful information and Streamlit experts.

```
pytest
```

**Pattern 4:** Additionally, you can check many other details for widgets like labels or disabled status. Many parameters are available for inspection, but not all. Use linting software to see what is currently supported. Here's an example:

```
import streamlit as st

st.selectbox("A", [1,2,3], None, help="Pick a number", placeholder="Pick me")
```

**Pattern 5:** Run your Streamlit app Working with Streamlit is simple. First you sprinkle a few Streamlit commands into a normal Python script, and then you run it. We list few ways to run your script, depending on your use case. Use streamlit run Once you've created your script, say your_script.py, the easiest way to run it is with streamlit run: streamlit run your_script.py As soon as you run the script as shown above, a local Streamlit server will spin up and your app will open in a new tab in your default web browser. Pass arguments to your script When passing your script some custom arguments, they must be passed after two dashes. Otherwise the arguments get interpreted as arguments to Streamlit itself: streamlit run your_script.py [-- script args] Pass a URL to streamlit run You can also pass a URL to streamlit run! This is great when your script is hosted remotely, such as a GitHub Gist. For example: streamlit run https://raw.githubusercontent.com/streamlit/demo-uber-nyc-pickups/master/streamlit_app.py Run Streamlit as a Python module Another way of running Streamlit is to run it as a Python module. This is useful when configuring an IDE like PyCharm to work with Streamlit: # Running python -m streamlit run your_script.py # is equivalent to: streamlit run your_script.py arrow_backPrevious: Architecture and executionarrow_forwardNext: Streamlit's architectureforumStill have questions?Our forums are full of helpful information and Streamlit experts.

```
your_script.py
```

**Pattern 6:** You can also pass a URL to streamlit run! This is great when your script is hosted remotely, such as a GitHub Gist. For example:

```
streamlit run
```

**Pattern 7:** st.area_chartStreamlit VersionVersion 1.50.0Version 1.49.0Version 1.48.0Version 1.47.0Version 1.46.0Version 1.45.0Version 1.44.0Version 1.43.0Version 1.42.0Version 1.41.0Version 1.40.0Version 1.39.0Version 1.38.0Version 1.37.0Version 1.36.0Version 1.35.0Version 1.34.0Version 1.33.0Version 1.32.0Version 1.31.0Version 1.30.0Version 1.29.0Version 1.28.0Version 1.27.0Version 1.26.0Version 1.25.0Version 1.24.0Version 1.23.0Version 1.22.0Display an area chart. This is syntax-sugar around st.altair_chart. The main difference is this command uses the data's own column and indices to figure out the chart's Altair spec. As a result this is easier to use for many "just plot this" scenarios, while being less customizable. Function signature[source] st.area_chart(data=None, *, x=None, y=None, x_label=None, y_label=None, color=None, stack=None, width=None, height=None, use_container_width=True) Parameters data (Anything supported by st.dataframe) Data to be plotted. x (str or None) Column name or key associated to the x-axis data. If x is None (default), Streamlit uses the data index for the x-axis values. y (str, Sequence of str, or None) Column name(s) or key(s) associated to the y-axis data. If this is None (default), Streamlit draws the data of all remaining columns as data series. If this is a Sequence of strings, Streamlit draws several series on the same chart by melting your wide-format table into a long-format table behind the scenes. x_label (str or None) The label for the x-axis. If this is None (default), Streamlit will use the column name specified in x if available, or else no label will be displayed. y_label (str or None) The label for the y-axis. If this is None (default), Streamlit will use the column name(s) specified in y if available, or else no label will be displayed. color (str, tuple, Sequence of str, Sequence of tuple, or None) The color to use for different series in this chart. For an area chart with just 1 series, this can be: None, to use the default color. A hex string like "#ffaa00" or "#ffaa0088". An RGB or RGBA tuple with the red, green, blue, and alpha components specified as ints from 0 to 255 or floats from 0.0 to 1.0. For an area chart with multiple series, where the dataframe is in long format (that is, y is None or just one column), this can be: None, to use the default colors. The name of a column in the dataset. Data points will be grouped into series of the same color based on the value of this column. In addition, if the values in this column match one of the color formats above (hex string or color tuple), then that color will be used. For example: if the dataset has 1000 rows, but this column only contains the values "adult", "child", and "baby", then those 1000 datapoints will be grouped into three series whose colors will be automatically selected from the default palette. But, if for the same 1000-row dataset, this column contained the values "#ffaa00", "#f0f", "#0000ff", then then those 1000 datapoints would still be grouped into 3 series, but their colors would be "#ffaa00", "#f0f", "#0000ff" this time around. For an area chart with multiple series, where the dataframe is in wide format (that is, y is a Sequence of columns), this can be: None, to use the default colors. A list of string colors or color tuples to be used for each of the series in the chart. This list should have the same length as the number of y values (e.g. color=["#fd0", "#f0f", "#04f"] for three lines). You can set the default colors in the theme.chartCategoryColors configuration option. stack (bool, "normalize", "center", or None) Whether to stack the areas. If this is None (default), Streamlit uses Vega's default. Other values can be as follows: True: The areas form a non-overlapping, additive stack within the chart. False: The areas overlap each other without stacking. "normalize": The areas are stacked and the total height is normalized to 100% of the height of the chart. "center": The areas are stacked and shifted to center their baseline, which creates a steamgraph. width (int or None) Desired width of the chart expressed in pixels. If width is None (default), Streamlit sets the width of the chart to fit its contents according to the plotting library, up to the width of the parent container. If width is greater than the width of the parent container, Streamlit sets the chart width to match the width of the parent container. To use width, you must set use_container_width=False. height (int or None) Desired height of the chart expressed in pixels. If height is None (default), Streamlit sets the height of the chart to fit its contents according to the plotting library. use_container_width (bool) Whether to override width with the width of the parent container. If use_container_width is True (default), Streamlit sets the width of the chart to match the width of the parent container. If use_container_width is False, Streamlit sets the chart's width according to width. ExamplesExample 1: Basic area chart from a dataframe If you don't use any of the optional parameters, Streamlit plots each column as a separate area, uses the index as the x values, and labels each series with the column name: import pandas as pd import streamlit as st from numpy.random import default_rng as rng df = pd.DataFrame(rng(0).standard_normal((20, 3)), columns=["a", "b", "c"]) st.area_chart(df) Built with Streamlit 🎈Fullscreen open_in_newExample 2: Area chart from specific dataframe columns You can choose different columns to use for the x and y values. If your dataframe is in long format (all y-values in one column), you can set the area colors from another column. If the column contains color strings, the colors will be applied directly and the series will be unlabeled. If the column contains other values, those values will label each area, and the area colors will be selected from the default color palette. You can configure this color palette in the theme.chartCategoryColors configuration option. import pandas as pd import streamlit as st from numpy.random import default_rng as rng df = pd.DataFrame( { "col1": list(range(20)) * 3, "col2": rng(0).standard_normal(60), "col3": ["a"] * 20 + ["b"] * 20 + ["c"] * 20, } ) st.area_chart(df, x="col1", y="col2", color="col3") Built with Streamlit 🎈Fullscreen open_in_newExample 3: Area chart from wide-format dataframe If your dataframe is in wide format (y-values are in multiple columns), you can pass a list of columns to the y parameter. Each column name becomes a series label. To override the default colors, pass a list of colors to the color parameter, one for each series. If your areas are overlapping, use colors with some transparency (alpha channel) for the best results. import pandas as pd import streamlit as st from numpy.random import default_rng as rng df = pd.DataFrame( { "col1": list(range(20)), "col2": rng(0).standard_normal(20), "col3": rng(1).standard_normal(20), } ) st.area_chart( df, x="col1", y=["col2", "col3"], color=["#FF000080", "#0000FF80"], ) Built with Streamlit 🎈Fullscreen open_in_newExample 4: Area chart with different stacking You can adjust the stacking behavior by setting stack. You can create a streamgraph by setting stack="center": import streamlit as st from vega_datasets import data df = data.unemployment_across_industries() st.area_chart(df, x="date", y="count", color="series", stack="center") Built with Streamlit 🎈Fullscreen open_in_new element.add_rowsStreamlit VersionVersion 1.50.0Version 1.49.0Version 1.48.0Version 1.47.0Version 1.46.0Version 1.45.0Version 1.44.0Version 1.43.0Version 1.42.0Version 1.41.0Version 1.40.0Version 1.39.0Version 1.38.0Version 1.37.0Version 1.36.0Version 1.35.0Version 1.34.0Version 1.33.0Version 1.32.0Version 1.31.0Version 1.30.0Version 1.29.0Version 1.28.0Version 1.27.0Version 1.26.0Version 1.25.0Version 1.24.0Version 1.23.0Version 1.22.0Concatenate a dataframe to the bottom of the current one. Function signature[source] element.add_rows(data=None, **kwargs) Parameters data (pandas.DataFrame, pandas.Styler, pyarrow.Table, numpy.ndarray, pyspark.sql.DataFrame, snowflake.snowpark.dataframe.DataFrame, Iterable, dict, or None) Table to concat. Optional. **kwargs (pandas.DataFrame, numpy.ndarray, Iterable, dict, or None) The named dataset to concat. Optional. You can only pass in 1 dataset (including the one in the data parameter). Example import time import pandas as pd import streamlit as st from numpy.random import default_rng as rng df1 = pd.DataFrame( rng(0).standard_normal(size=(50, 20)), columns=("col %d" % i for i in range(20)) ) df2 = pd.DataFrame( rng(1).standard_normal(size=(50, 20)), columns=("col %d" % i for i in range(20)) ) my_table = st.table(df1) time.sleep(1) my_table.add_rows(df2) You can do the same thing with plots. For example, if you want to add more data to a line chart: # Assuming df1 and df2 from the example above still exist... my_chart = st.line_chart(df1) time.sleep(1) my_chart.add_rows(df2) And for plots whose datasets are named, you can pass the data with a keyword argument where the key is the name: my_chart = st.vega_lite_chart( { "mark": "line", "encoding": {"x": "a", "y": "b"}, "datasets": { "some_fancy_name": df1, # <-- named dataset }, "data": {"name": "some_fancy_name"}, } ) my_chart.add_rows(some_fancy_name=df2) # <-- name used as keyword arrow_backPrevious: Chart elementsarrow_forwardNext: st.bar_chartforumStill have questions?Our forums are full of helpful information and Streamlit experts.

```
import pandas as pd
import streamlit as st
from numpy.random import default_rng as rng

df = pd.DataFrame(rng(0).standard_normal((20, 3)), columns=["a", "b", "c"])

st.area_chart(df)
```

**Pattern 8:** SEO and search indexability When you deploy a public app to Streamlit Community Cloud, it is automatically indexed by search engines like Google and Bing on a weekly basis. 🎈 This means that anyone can find your app by searching for its custom subdomain (e.g. "traingenerator.streamlit.app") or by searching for the app's title. Get the most out of app indexability Here are some tips to help you get the most out of app indexability: Make sure your app is public Choose a custom subdomain early Choose a descriptive app title Customize your app's meta description Make sure your app is public All public apps hosted on Community Cloud are indexed by search engines. If your app is private, it will not be indexed by search engines. To make your private app public, read Share your app. Choose a custom subdomain early Community Cloud automatically generates a subdomain for your app if you do not choose one. However, you can change your subdomain at any time! Custom subdomains modify your app URLs to reflect your app content, personal branding, or whatever you’d like. To learn how to change your app's subdomain, see View or change your app's URL. By choosing a custom subdomain, you can use it to help people find your app. For example, if you're deploying an app that generates training data, you might choose a subdomain like traingenerator.streamlit.app. This makes it easy for people to find your app by searching for "training generator" or "train generator streamlit app." We recommend choosing a custom subdomain when you deploy your app. This ensures that your app is indexed by search engines using your custom subdomain, rather than the automatically generated one. If you choose a custom subdomain later, your app may be indexed multiple times—once using the default subdomain and once using your custom subdomain. In this case, your old URL will result in a 404 error which can confuse users who are searching for your app. Choose a descriptive app title The meta title of your app is the text that appears in search engine results. It is also the text that appears in the browser tab when your app is open. By default, the meta title of your app is the same as the title of your app. However, you can customize the meta title of your app by setting the st.set_page_config parameter page_title to a custom string. For example: st.set_page_config(page_title="Traingenerator") This will change the meta title of your app to "Traingenerator." This makes it easier for people to find your app by searching for "Traingenerator" or "train generator streamlit app": Google search results for "train generator streamlit app" Customize your app's meta description Meta descriptions are the short descriptions that appear in search engine results. Search engines use the meta description to help users understand what your app is about. From our observations, search engines seem to favor the content in both st.header and st.text over st.title. If you put a description at the top of your app under st.header or st.text, there’s a good chance search engines will use this for the meta description. What does my indexed app look like? If you're curious about what your app looks like in search engine results, you can type the following into Google Search: site:<your-custom-subdomain>.streamlit.app Example: site:traingenerator.streamlit.app Google search results for "site:traingenerator.streamlit.app" What if I don't want my app to be indexed? If you don't want your app to be indexed by search engines, you can make it private. Read Share your app to learn more about making your app private. Note: each workspace can only have one private app. If you want to make your app private, you must first delete any other private app in your workspace or make it public. That said, Community Cloud is an open and free platform for the community to deploy, discover, and share Streamlit apps and code with each other. As such, we encourage you to make your app public so that it can be indexed by search engines and discovered by other Streamlit users and community members.arrow_backPrevious: Embed your apparrow_forwardNext: Share previewsforumStill have questions?Our forums are full of helpful information and Streamlit experts.

```
traingenerator.streamlit.app
```

## Reference Files

This skill includes comprehensive documentation in `references/`:

- **api.md** - Api documentation
- **concepts.md** - Concepts documentation
- **deployment.md** - Deployment documentation
- **getting_started.md** - Getting Started documentation
- **knowledge_base.md** - Knowledge Base documentation
- **other.md** - Other documentation
- **tutorials.md** - Tutorials documentation

Use `view` to read specific reference files when detailed information is needed.

## Working with This Skill

### For Beginners
Start with the getting_started or tutorials reference files for foundational concepts.

### For Specific Features
Use the appropriate category reference file (api, guides, etc.) for detailed information.

### For Code Examples
The quick reference section above contains common patterns extracted from the official docs.

## Resources

### references/
Organized documentation extracted from official sources. These files contain:
- Detailed explanations
- Code examples with language annotations
- Links to original documentation
- Table of contents for quick navigation

### scripts/
Add helper scripts here for common automation tasks.

### assets/
Add templates, boilerplate, or example projects here.

## Notes

- This skill was automatically generated from official documentation
- Reference files preserve the structure and examples from source docs
- Code examples include language detection for better syntax highlighting
- Quick reference patterns are extracted from common usage examples in the docs

## Updating

To refresh this skill with updated documentation:
1. Re-run the scraper with the same configuration
2. The skill will be rebuilt with the latest information