# Streamlit > This page contains release notes for Streamlit versions released in 2019. For the latest version of Streamlit, see [Release notes](/develop/quick-reference/release-notes). --- # Source: https://docs.streamlit.io/develop/quick-reference/release-notes/2019 # 2019 release notes This page contains release notes for Streamlit versions released in 2019. For the latest version of Streamlit, see [Release notes](/develop/quick-reference/release-notes). ## Version 0.52.0 **Release date: December 20, 2019** ### Highlights - 📤 Preview release of the file uploader widget. To try it out just call `st.file_uploader`! - Note that as a preview release, things may change in the near future. Looking forward to hearing input from the community before we stabilize the API! - 👋 Support for [emoji codes](https://www.webfx.com/tools/emoji-cheat-sheet/) in `st.write` and `st.markdown`. Try it out with `st.write(“Hello :wave:”)`. ### Breaking changes - 🛹 `st.pyplot` now clears figures by default, since that's what you want 99% of the time. This allows you to create two or more Matplotlib charts without having to call `pyplot.clf` every time. If you want to turn this behavior off, use `st.pyplot(clear_figure=False)`. - 📣 `st.cache` no longer checks for input mutations. This is the first change of our ongoing effort to simplify the caching system and prepare Streamlit for the launch of other caching primitives like Session State! ## Version 0.51.0 **Release date: November 30, 2019** ### Highlights - 🐕 You can now tweak the behavior of the file watcher with the config option `server.fileWatcherType`. Use it to switch between: - `auto` (default): Streamlit will attempt to use the watchdog module, and falls back to polling if watchdog is not available. - `watchdog`: Force Streamlit to use the watchdog module. - `poll`: Force Streamlit to always use polling. - `none`: Streamlit will not watch files. - 📣 We now cache JS files in your browser for faster loading. - 📲 Use `server.baseUrlPath` config option to set Streamlit's URL to something like `http://domain.com/customPath`. ### Notable bug fixes - Fixes numerous Windows bugs, including [Issues #339](https://github.com/streamlit/streamlit/issues/399) and [Issues #401](https://github.com/streamlit/streamlit/issues/301). - Fixes loading of root URL `/` on Windows. - 🚀 Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. - 🎥 Improved handling of widget state when Python file is modified. - 🙌 Improved HTML support in `st.write` and `st.markdown`. HTML is still unsafe, though! ### Breaking change - 🛡️ We have temporarily disabled support for sharing static "snapshots" of Streamlit apps. Now that we're no longer in a limited-access beta, we need to make sure sharing is well thought through and abides by laws like the DMCA. But we're working on a solution! ## Version 0.50.1 **Release date: November 10, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) - Fixes loading of root URL `/` on Windows. [Issue #244](https://github.com/streamlit/streamlit/issues/244) ## Version 0.49.0 **Release date: October 23, 2019** ### Highlights - 📈 Greatly improved our support for named datasets in Vega-Lite and Altair. - 📣 Added ability to ignore certain folders when watching for file changes. See the `server.folderWatchBlacklist` config option. - 🐛 Fixed numerous bugs and additional polish in preparation for our launch! ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) - Fixes loading of root URL `/` on Windows. [Issue #244](https://github.com/streamlit/streamlit/issues/244) ## Version 0.48.0 **Release date: October 12, 2019** ### Highlights - ⚡ Lightning-fast reconnect when you do a ctrl-c/rerun on your Streamlit code. - 📣 Useful error messages when the connection fails. - 💎 Fixed multiple bugs and improved polish of our newly-released interactive widgets. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.47.0 **Release date: October 1, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.46.0 **Release date: September 19, 2019** ### Highlights - 📈 Greatly improved our support for named datasets in Vega-Lite and Altair. - 📣 Added ability to ignore certain folders when watching for file changes. See the `server.folderWatchBlacklist` config option. - 🐛 Fixed numerous bugs and additional polish in preparation for our launch! ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.45.0 **Release date: August 28, 2019** ### Highlights - ⚡ Lightning-fast reconnect when you do a ctrl-c/rerun on your Streamlit code. - 📣 Useful error messages when the connection fails. - 💎 Fixed multiple bugs and improved polish of our newly-released interactive widgets. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.44.0 **Release date: July 28, 2019** ### Highlights - ⚡ Lightning-fast reconnect when you do a ctrl-c/rerun on your Streamlit code. - 📣 Useful error messages when the connection fails. - 💎 Fixed multiple bugs and improved polish of our newly-released interactive widgets. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.43.0 **Release date: July 9, 2019** ### Highlights - ⚡ Lightning-fast reconnect when you do a ctrl-c/rerun on your Streamlit code. - 📣 Useful error messages when the connection fails. - 💎 Fixed multiple bugs and improved polish of our newly-released interactive widgets. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.42.0 **Release date: July 1, 2019** ### Highlights - 💓 Ability to save Vega-Lite and Altair charts to SVG or PNG. - 🐛 Fixed numerous bugs and additional polish in preparation for our launch! ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.41.0 **Release date: June 24, 2019** ### Highlights - 📈 Greatly improved our support for named datasets in Vega-Lite and Altair. - 📣 Added ability to ignore certain folders when watching for file changes. See the `server.folderWatchBlacklist` config option. - 🐛 Fixed numerous bugs and additional polish in preparation for our launch! ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.40.0 **Release date: June 10, 2019** ### Highlights - 💓 Ability to save Vega-Lite and Altair charts to SVG or PNG. - 🐛 Fixed numerous bugs and additional polish in preparation for our launch! ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.36.0 **Release date: May 03, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.35.0 **Release date: April 26, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.34.0 **Release date: April 19, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.33.0 **Release date: April 12, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.32.0 **Release date: April 5, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.31.0 **Release date: March 29, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.30.0 **Release date: March 22, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.29.0 **Release date: March 15, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.28.0 **Release date: March 8, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.27.0 **Release date: March 1, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.26.0 **Release date: February 22, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.25.0 **Release date: February 15, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.24.0 **Release date: February 8, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.23.0 **Release date: February 1, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.22.0 **Release date: January 24, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.21.0 **Release date: January 17, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.20.0 **Release date: January 10, 2019** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.19.0 **Release date: December 20, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.18.0 **Release date: December 13, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.17.0 **Release date: December 6, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.16.0 **Release date: December 1, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.15.0 **Release date: November 24, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.14.0 **Release date: November 17, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.13.0 **Release date: November 10, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.12.0 **Release date: November 3, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.11.0 **Release date: October 26, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.10.0 **Release date: October 19, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.9.0 **Release date: October 12, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.8.0 **Release date: October 5, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.7.0 **Release date: September 28, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.6.0 **Release date: September 21, 2018** ### Highlights - 🐙 Experimental support for sidebar! Let us know if you want to be a beta tester. - 📄 Completely redesigned `st.cache`! Much more performant, has a cleaner API, support for caching functions called by `@st.cached` functions, user-friendly error messages, and much more! - 🖼️ Lightning fast `st.image`, ability to choose between JPEG and PNG compression, and between RGB and BGR (for OpenCV). - 💡 Smarter API for `st.slider`, `st.selectbox`, and `st.radio`. ### Notable bug fixes - Fixes `@st.cache` bug related to having your Python environment on current working directory. [Issue #242](https://github.com/streamlit/streamlit/issues/242) ## Version 0.5.0 **Release date: September --- # Source: https://docs.streamlit.io/develop/quick-reference/release-notes/2020 # 2020 release notes This page contains release notes for Streamlit versions released in 2020. For the latest version of Streamlit, see [Release notes](/develop/quick-reference/release-notes). ## Version 0.73.0 **Release date: December 17, 2020** ### Notable Changes - 🐍 Streamlit can now be installed on Python 3.9. Streamlit components are not yet compatible with Python 3.9 and must use version 3.8 or earlier. - 🧱 Streamlit Components now allows same origin, enabling features provided by the browser such as a webcam component. - 🐝 Fix Streamlit sharing deploy experience for users running on Git versions 2.7.0 or earlier. - 📉 Handle unexpected closing of uploaded files for [st.file_uploader](https://docs.streamlit.io/en/0.72.0/api.html#streamlit.file_uploader). ## Version 0.72.0 **Release date: December 2, 2020** ### Notable Changes - 🌈 Establish a framework for theming and migrate existing components. - 📱 Improve the sidebar experience for mobile devices. - 🧰 Update [st.file_uploader](https://docs.streamlit.io/en/0.71.0/api.html#streamlit.file_uploader) to reduce reruns. ## Version 0.71.0 **Release date: November 11, 2020** ### Notable Changes - 📄 Better support across browsers for start and stop times for st.video. - 🖼 Bug fix for intermittently failing media files. - 📦 Bug fix for custom components compatibility with Safari. Make sure to upgrade to the latest [streamlit-component-lib](https://www.npmjs.com/package/streamlit-component-lib). ## Version 0.70.0 **Release date: October 28, 2020** ### Notable Changes - 🧐 Support StringDtype from pandas version 1.0.0. - 📝 Support for running Streamlit on Unix sockets. - 🚀 Improved pandas dataframe support for st.radio, st.selectbox, and st.multiselect. - 🚩 Break out of your Streamlit app with st.stop. - 🖼 Inline SVG support for st.image. ## Version 0.69.0 **Release date: October 15, 2020** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. ## Version 0.68.0 **Release date: October 8, 2020** ### Highlights - 🌠 Improved file uploader redesigned with new functionality for multiple files uploads and better support for working with uploaded files. This may cause breaking changes. Please see the new API in our [documentation](https://docs.streamlit.io/en/0.68.0/api.html#streamlit.file_uploader). ## Version 0.67.0 **Release date: September 16, 2020** ### Highlights - 📈 Support for Streamlit Components. See [documentation](https://docs.streamlit.io/en/latest/streamlit_components.html) for more info. - 📙 Out-of-the-box support for CSRF protection using the [Cookie-to-header token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-header_token) technique. This means that if you're serving your Streamlit app from multiple replicas you'll need to configure them to use the same cookie secret with the `server.cookieSecret` config option. To turn XSRF protection off, set `server.enableXsrfProtection=false`. ## Version 0.66.0 **Release date: September 1, 2020** ### Highlights - ✏️ Ability to turn websocket compression on/off via the config option `server.enableWebsocketCompression`. This is useful if your server strips HTTP headers and you do not have access to change that behavior. - 🚀 Out-of-the-box support for CSRF protection using the [Cookie-to-header token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-header_token) technique. This means that if you're serving your Streamlit app from multiple replicas you'll need to configure them to use the same cookie secret with the `server.cookieSecret` config option. To turn XSRF protection off, set `server.enableXsrfProtection=false`. ## Version 0.65.0 **Release date: August 12, 2020** ### Highlights - ⚙️ Ability to set page title, favicon, sidebar state, and wide mode via `st.beta_set_page_config()`. See [documentation](https://docs.streamlit.io/en/0.65.0/api.html#streamlit.set_page_config) for details. - 📣 Add stateful behaviors through the use of query parameters with `st.experimental_set_query_params` and `st.experimental_get_query_params`. Thanks [@zhaoooyue](https://github.com/zhaoooyue)! - 🚩 Improved `@st.cache` support for Keras models and Tensorflow `saved_models`. ## Version 0.64.0 **Release date: July 23, 2020** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.63.0 **Release date: July 13, 2020** ### Highlights - 🧩 Support for Streamlit Components. See [documentation](https://docs.streamlit.io/en/latest/streamlit_components.html) for more info. - 📉 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.62.0 **Release date: June 21, 2020** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.61.0 **Release date: June 2, 2020** ### Highlights - ✏️ Ability to turn websocket compression on/off via the config option `server.enableWebsocketCompression`. This is useful if your server strips HTTP headers and you do not have access to change that behavior. - 🚀 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.60.0 **Release date: May 18, 2020** ### Highlights - 🤔 Support for date ranges in `st.date_picker`. See [docs](https://docs.streamlit.io/en/latest/api.html#streamlit.date_picker) for more info, but the TLDR is: just pass a list/tuple as the default date and it will be interpreted as a range. - 📣 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.59.0 **Release date: May 05, 2020** ### Highlights - 📄 Support for date ranges in `st.date_picker`. See [docs](https://docs.streamlit.io/en/latest/api.html#streamlit.date_picker) for more info, but the TLDR is: just pass a list/tuple as the default date and it will be interpreted as a range. - 📙 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.58.0 **Release date: April 22, 2020** ### Highlights - ✏️ Ability to turn websocket compression on/off via the config option `server.enableWebsocketCompression`. This is useful if your server strips HTTP headers and you do not have access to change that behavior. - 📉 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.57.0 **Release date: March 26, 2020** ### Highlights - 🤔 Support for date ranges in `st.date_picker`. See [docs](https://docs.streamlit.io/en/latest/api.html#streamlit.date_picker) for more info, but the TLDR is: just pass a list/tuple as the default date and it will be interpreted as a range. - 📙 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.56.0 **Release date: February 15, 2020** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.55.0 **Release date: February 4, 2020** ### Highlights - 🤔 Support for date ranges in `st.date_picker`. See [docs](https://docs.streamlit.io/en/latest/api.html#streamlit.date_picker) for more info, but the TLDR is: just pass a list/tuple as the default date and it will be interpreted as a range. - 📙 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.54.0 **Release date: January 29, 2020** ### Highlights - ⚙️ Support for password fields! Just pass `type="password"` to `st.text_input()`. - 🚩 Improved `@st.cache` support for Keras models and Tensorflow `saved_models`. ## Version 0.53.0 **Release date: January 14, 2020** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.52.0 **Release date: December 22, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.51.0 **Release date: December 15, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.50.0 **Release date: December 8, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.49.0 **Release date: December 1, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.48.0 **Release date: November 24, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.47.0 **Release date: November 17, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.46.0 **Release date: November 10, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.45.0 **Release date: November 3, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.44.0 **Release date: October 26, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.43.0 **Release date: October 19, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.42.0 **Release date: October 12, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.41.0 **Release date: October 5, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.40.0 **Release date: September 28, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.39.0 **Release date: September 21, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.38.0 **Release date: September 14, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.37.0 **Release date: September 7, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.36.0 **Release date: September 1, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.35.0 **Release date: August 24, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.34.0 **Release date: August 17, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.33.0 **Release date: August 10, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.32.0 **Release date: August 3, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.31.0 **Release date: July 26, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.30.0 **Release date: July 19, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.29.0 **Release date: July 12, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.28.0 **Release date: July 5, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.27.0 **Release date: June 28, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.26.0 **Release date: June 21, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.25.0 **Release date: June 14, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.24.0 **Release date: June 7, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.23.0 **Release date: June 1, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.22.0 **Release date: May 24, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.21.0 **Release date: May 17, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.20.0 **Release date: May 10, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.19.0 **Release date: May 3, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.18.0 **Release date: April 26, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.17.0 **Release date: April 19, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.16.0 **Release date: April 12, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.15.0 **Release date: April 5, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.14.0 **Release date: March 28, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.13.0 **Release date: March 21, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.12.0 **Release date: March 14, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.11.0 **Release date: March 7, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.10.0 **Release date: February 28, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.9.0 **Release date: February 21, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.8.0 **Release date: February 14, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.7.0 **Release date: February 7, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.6.0 **Release date: January 31, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.5.0 **Release date: January 24, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.4.0 **Release date: January 17, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.3.0 **Release date: January 10, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.2.0 **Release date: January 3, 2019** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. ## Version 0.1.0 **Release date: December 26, 2018** ### Highlights - 📷 Default matplotlib to display charts with a tight layout. To disable this, set `bbox_inches` to `None`, inches as a string, or a `Bbox`. - 📚 Out-of-the-box support for running Streamlit on Unix sockets. --- # Source: https://docs.streamlit.io/develop/quick-reference/release-notes/2021 # 2021 release notes This page contains release notes for Streamlit versions released in 2021. For the latest version of Streamlit, see [Release notes](/develop/quick-reference/release-notes). ## Version 1.3.0 **Release date: Dec 16, 2021** ### Notable Changes - 💯 Support for NumPy values in `st.metric`. - 🌐 Support for Mesh Layers in PyDeck. - 📊 Updated Plotly chart version to support the latest features. - 🤗 `st.spinner` element has visual animated spinner. - 🛠️ `st.caption` supports HTML in text with `unsafe_allow_html` parameter. ### Other Changes - 🪲 Bug fix: Allow `st.session_state` to be used to set number_input values with no warning ([#4047](https://github.com/streamlit/streamlit/pull/4047)). - 🪲 Bug fix: Fix footer alignment in wide mode ([#4035](https://github.com/streamlit/streamlit/pull/4035)). - 🐞 Bug fix: Better support for Graphviz and Bokeh charts in containers (columns, expanders, etc.) ([#4039](https://github.com/streamlit/streamlit/pull/4039)). - 🐞 Bug fix: Support inline data values in Vega-Lite ([#4070](https://github.com/streamlit/streamlit/pull/4070)). - ✍️ Types: Updated type annotations for experimental memo and singleton decorators. - ✍️ Types: Improved type annotations for `st.selectbox`, `st.select_slider`, `st.radio`, `st.number_input`, and `st.multiselect`. - 📝 Publish type annotations according to [PEP 561](https://mypy.readthedocs.io/en/stable/installed_packages.html). Users now get type annotations for Streamlit when running mypy ([#4025](https://github.com/streamlit/streamlit/pull/4025)). ## Version 1.2.0 **Release date: Nov 11, 2021** ### Notable Changes - ✏️  `st.text_input` and `st.text_area` now have a `placeholder` parameter to display text when the field is empty. - 📏 Viewers can now resize the input box in `st.text_area`. - 📁 Streamlit can auto-reload when files in sub-directories change. ### Other Changes - 🪲 Bug fix: Allow initialization of range slider with session state ([#3586](https://github.com/streamlit/streamlit/issues/3586)). - 🐞 Bug fix: Refresh chart when using `add_rows` with `datetime` index ([#3653](https://github.com/streamlit/streamlit/issues/3653)). - ✍️ Added some more type annotation in our codebase ([#3908](https://github.com/streamlit/streamlit/issues/3908)). ## Version 1.1.0 **Release date: Oct 21, 2021** ### Highlights - 🧠 Memory improvements: Streamlit apps allocate way less memory over time now. ### Notable Changes - 🪲 Apps automatically rerun now when the content of `secrets.toml` changes (before this you had to refresh the page manually). ### Other Changes - 📄 Redirected some links to our [brand-new docs site](https://docs.streamlit.io/), e.g., in exceptions. - 🪲 Bug fix: Allow initialization of range slider with session state ([#3557](https://github.com/streamlit/streamlit/issues/3557)). - 🐞 Bug fix: Refresh chart when using `add_rows` with `datetime` index ([#3653](https://github.com/streamlit/streamlit/issues/3653)). - ✍️ Added some more type annotation in our codebase ([#3908](https://github.com/streamlit/streamlit/issues/3908)). ## Version 1.0.0 **Release date: Oct 5, 2021** ### Highlights - 🎈 Announcing Streamlit 1.0! To read more about check out our [1.0 blog post](https://blog.streamlit.io/announcing-streamlit-1-0/). ### Other Changes - 🐞 Fixed an issue where using `df.dtypes` to show datatypes for a DF fails while using Arrow ([#3709](https://github.com/streamlit/streamlit/issues/3709)), Image captions stay within image width and are readable ([#3530](https://github.com/streamlit/streamlit/issues/3530)), `st.select_slider` resets its state upon interaction ([#3600](https://github.com/streamlit/streamlit/issues/3600)). ## Version 0.89.0 **Release date: Sep 22, 2021** ### Highlights - 💰 Introducing `st.experimental_memo` and `experimental_singleton`, a new primitive for caching! See [our blog post](https://blog.streamlit.io/new-experimental-primitives-for-caching/). ### Other Changes - 🪲 Bug fix: Unresponsive pydeck example ([#3395](https://github.com/streamlit/streamlit/issues/3395)), `JSON.parse` error message ([#2324](https://github.com/streamlit/streamlit/issues/2324)), Tooltips rendering ([#3300](https://github.com/streamlit/streamlit/issues/3300)), Colorpicker not working on Streamlit Sharing ([#2689](https://github.com/streamlit/streamlit/issues/2689)). ## Version 0.88.0 **Release date: Sep 2, 2021** ### Highlights - 📣 Introducing `st.metric`, an API for displaying KPIs. Check out the [demo app](https://streamlit-release-demos-0-87streamlit-app-0-87-rfzphf.streamlit.app/) showcasing the functionality. ### Other Changes - 🐞 Bug fixes: File uploader retains state upon expander closing ([#3594](https://github.com/streamlit/streamlit/issues/3594)), `setIn` Error with `st.empty` ([#3659](https://github.com/streamlit/streamlit/issues/3659)), `st.select_slider` resets its state upon interaction ([#3600](https://github.com/streamlit/streamlit/issues/3600)). ## Version 0.87.0 **Release date: Aug 19, 2021** ### Highlights - 📢 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/session-state-for-streamlit/). ### Other Changes - 🪄 `st.text_input` now has an `autocomplete` parameter to allow password managers to be used. - Using `set_page_config` to assign the page title no longer appends `Streamlit` to that title ([#3467](https://github.com/streamlit/streamlit/pull/3467)). ## Version 0.86.0 **Release date: Aug 5, 2021** ### Highlights - 🧠 Introducing `st.session_state` and widget callbacks to allow you to add statefulness to your apps. Check out the [blog post](http://blog.streamlit.io/introducing-submit-button-and-forms). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.85.0 **Release date: Jul 22, 2021** ### Highlights - 🏹 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.84.0 **Release date: Jul 1, 2021** ### Highlights - 🧠 Introducing `st.session_state` and widget callbacks to allow you to add statefulness to your apps. Check out the [blog post](http://blog.streamlit.io/introducing-submit-button-and-forms). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.83.0 **Release date: Jun 17, 2021** ### Highlights - 📣 Updates to Streamlit docs to include step-by-step guides which demonstrate how to connect Streamlit apps to various databases & APIs. ### Other Changes - 📝 Introducing `st.form` and `st.form_submit_button` to allow you to batch input widgets. Check out our [blog post](http://blog.streamlit.io/introducing-submit-button-and-forms). - 🔤 Introducing `st.caption` so you can add explainer text anywhere in your apps. - 🎨 Updates to Theming, including ability to build a theme that inherits from any of our default themes. - 🚀 Improvements to deployment experience to Streamlit sharing from the app menu. ## Version 0.82.0 **Release date: May 13, 2021** ### Highlights - 📣 Introducing `st.form` and `st.form_submit_button` to allow you to batch input widgets. Check out our [blog post](http://blog.streamlit.io/introducing-submit-button-and-forms). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.81.1 **Release date: Apr 29, 2021** ### Highlights - 📢 Introducing `st.form` and `st.form_submit_button` to allow you to batch input widgets. Check out our [blog post](http://blog.streamlit.io/introducing-submit-button-and-forms). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.80.0 **Release date: Apr 8, 2021** ### Highlights - 🧠 Introducing `st.session_state` and widget callbacks to allow you to add statefulness to your apps. Check out the [blog post](http://blog.streamlit.io/introducing-submit-button-and-forms). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.79.0 **Release date: Mar 18, 2021** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.78.0 **Release date: Mar 4, 2021** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.77.0 **Release date: Feb 23, 2021** ### Highlights - 📢 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.76.0 **Release date: February 4, 2021** ### Highlights - 🧠 Introducing `st.session_state` and widget callbacks to allow you to add statefulness to your apps. Check out the [blog post](http://blog.streamlit.io/introducing-submit-button-and-forms). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.75.0 **Release date: January 21, 2021** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.74.0 **Release date: January 6, 2021** ### Highlights - 🧠 Introducing `st.session_state` and widget callbacks to allow you to add statefulness to your apps. Check out the [blog post](http://blog.streamlit.io/introducing-submit-button-and-forms). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.73.0 **Release date: December 22, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.72.0 **Release date: December 15, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.71.0 **Release date: December 8, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.70.0 **Release date: December 1, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.69.0 **Release date: November 17, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.68.0 **Release date: November 10, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.67.0 **Release date: November 3, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.66.0 **Release date: October 26, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.65.0 **Release date: October 19, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.64.0 **Release date: October 12, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.63.0 **Release date: October 5, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.62.0 **Release date: September 29, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.61.0 **Release date: September 22, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.60.0 **Release date: September 14, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.59.0 **Release date: September 7, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.58.0 **Release date: September 1, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.57.0 **Release date: August 24, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.56.0 **Release date: August 17, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.55.0 **Release date: August 10, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.54.0 **Release date: August 3, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.53.0 **Release date: July 26, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.52.0 **Release date: July 19, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.51.0 **Release date: July 12, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.50.0 **Release date: July 5, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.49.0 **Release date: June 28, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.48.0 **Release date: June 21, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved color picker widget in the Custom Theme dialog ([#2970](https://github.com/streamlit/streamlit/issues/2970)). ## Version 0.47.0 **Release date: June 14, 2020** ### Highlights - 📣 Introducing support for custom themes. Check out our [blog post](http://blog.streamlit.io/introducing-theming/). ### Other Changes - 🪲 Bug fixes: `allow-downloads` capability to custom components ([#3144](https://github.com/streamlit/streamlit/pull/3144)). - Fixed markdown tables in dark theme ([#3020](https://github.com/streamlit/streamlit/issues/3020)). - Improved --- # Source: https://docs.streamlit.io/develop/quick-reference/release-notes/2022 # 2022 release notes This page contains release notes for Streamlit versions released in 2022. For the latest version of Streamlit, see [Release notes](/develop/quick-reference/release-notes). ## Version 1.16.0 **Release date: December 14, 2022** ### Highlights - 👩‍🎨 Introducing a new Streamlit theme for Altair, Plotly, and Vega-Lite charts! Check out our [blog post](https://blog.streamlit.io/a-new-streamlit-theme-for-altair-and-plotly/) for more information. - 🎨 Streamlit now supports colored text in all commands that accept Markdown, including `st.markdown`, `st.header`, and more. Learn more in our [documentation](/develop/api-reference/text/st.markdown). ### Notable Changes - 🔀 Functions cached with `st.experimental_memo` or `st.experimental_singleton` can contain Streamlit media elements and forms. - ⛄ All Streamlit commands that accept pandas DataFrames as input also support Snowpark and PySpark DataFrames. - 🏷️ `st.image` supports loading SVGs from Inkscape. ### Other Changes - 🗺️ `st.map` improvements: support for upper case columns and better exception messages (https://github.com/streamlit/streamlit/pull/5679, https://github.com/streamlit/streamlit/pull/5792) - 🐞 Bug fix: `st.plotly_chart` respects the figure's height attribute and the `use_container_width` parameter (https://github.com/streamlit/streamlit/pull/5779) - 🪲 Bug fix: all commands with the `icon` parameter such as `st.error`, `st.warning`, etc., can contain emojis with variant selectors (https://github.com/streamlit/streamlit/pull/5583) - 🐝 Bug fix: prevent `st.camera_input` from jittering when resizing the browser window (https://github.com/streamlit/streamlit/pull/5711) - 🐜 Bug fix: update exception layout to avoid overflow of stack traces (https://github.com/streamlit/streamlit/pull/5700) - 📢 Upgraded Vega-Lite library to support even more interactive charting improvements. See their [release notes](https://github.com/vega/vega-lite/releases) to find out more. (https://github.com/streamlit/streamlit/pull/4751) - 📈 Upgraded `st.vega_lite_chart` to use `datetime.timedelta` objects as `ttl` parameter value, properly hash PIL images and `Enum` classes, show better error messages when returning unevaluated dataframes (https://github.com/streamlit/streamlit/pull/4736, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4681, https://github.com/streamlit/streamlit/pull/4682, https://github.com/streamlit/streamlit/pull/4683, https://github.com/streamlit/streamlit/pull/4684, https://github.com/streamlit/streamlit/pull/4685, https://github.com/streamlit/streamlit/pull/4686, https://github.com/streamlit/streamlit/pull/4687, https://github.com/streamlit/streamlit/pull/4690, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4704, https://github.com/streamlit/streamlit/pull/4705, https://github.com/streamlit/streamlit/pull/4706, https://github.com/streamlit/streamlit/pull/4707, https://github.com/streamlit/streamlit/pull/4708, https://github.com/streamlit/streamlit/pull/4710, https://github.com/streamlit/streamlit/pull/4723, https://github.com/streamlit/streamlit/pull/4733) - 🐍 Types: More updated type annotations across Streamlit! (https://github.com/streamlit/streamlit/pull/4808, https://github.com/streamlit/streamlit/pull/4809, https://github.com/streamlit/streamlit/pull/4856) ## Version 1.15.0 **Release date: November 17, 2022** ### Highlights - 👍 Widget labels can contain inline Markdown. See our [docs](/develop/api-reference/widgets) and demo [app](https://markdown-labels.streamlit.app/) for more info. - 🎵 `st.audio` now supports playing audio data passed in as NumPy arrays with the keyword-only `sample_rate` parameter. ### Notable Changes - 🔀 Functions cached with `st.experimental_memo` or `st.experimental_singleton` can contain Streamlit widgets using the `experimental_allow_widgets` parameter. This allows caching checkboxes, sliders, radio buttons, and more! - 🐛 Design tweak to prevent jittering in sliders (https://github.com/streamlit/streamlit/pull/5612) - 🐛 Bug fix: links in headers are red, not blue (https://github.com/streamlit/streamlit/pull/5609) - 🐛 Bug fix: properly resize Plotly charts when exiting fullscreen (https://github.com/streamlit/streamlit/pull/5645) - 🐝 Bug fix: don't accidentally trigger `st.balloons` and `st.snow` (https://github.com/streamlit/streamlit/pull/5401) ### Other Changes - 🏚️ `st.time_input` allows for keyboard-only input (https://github.com/streamlit/streamlit/pull/5194) - 📚 `st.memo` will warn the user when using `ttl` and `persist` keyword argument together (https://github.com/streamlit/streamlit/pull/5032) - 🔖 `st.number_input` returns consistent type after rerun (https://github.com/streamlit/streamlit/pull/5359) - 📽 `st.sidebar` UI fixes including a fix for scrollbars in Firefox browsers (https://github.com/streamlit/streamlit/pull/5157, https://github.com/streamlit/streamlit/pull/5324) - 👩‍💻 Improvements to usage metrics to guide API development. - ✍️ More type hints! (https://github.com/streamlit/streamlit/pull/5191, https://github.com/streamlit/streamlit/pull/5192, https://github.com/streamlit/streamlit/pull/5242, https://github.com/streamlit/streamlit/pull/5243, https://github.com/streamlit/streamlit/pull/5244, https://github.com/streamlit/streamlit/pull/5245, https://github.com/streamlit/streamlit/pull/5246) Thanks [harahu](https://github.com/harahu)! - 📝 Upgraded `st.json` to support even more interactive charting improvements. See their [release notes](https://github.com/vega/vega-lite/releases) to find out more. (https://github.com/streamlit/streamlit/pull/4751) - 📈 Upgraded `st.vega_lite_chart` to use `datetime.timedelta` objects as `ttl` parameter value, properly hash PIL images and `Enum` classes, show better error messages when returning unevaluated dataframes (https://github.com/streamlit/streamlit/pull/4736, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4681, https://github.com/streamlit/streamlit/pull/4682, https://github.com/streamlit/streamlit/pull/4683, https://github.com/streamlit/streamlit/pull/4684, https://github.com/streamlit/streamlit/pull/4685, https://github.com/streamlit/streamlit/pull/4686, https://github.com/streamlit/streamlit/pull/4687, https://github.com/streamlit/streamlit/pull/4690, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4704, https://github.com/streamlit/streamlit/pull/4705, https://github.com/streamlit/streamlit/pull/4706, https://github.com/streamlit/streamlit/pull/4707, https://github.com/streamlit/streamlit/pull/4708, https://github.com/streamlit/streamlit/pull/4710, https://github.com/streamlit/streamlit/pull/4723, https://github.com/streamlit/streamlit/pull/4733) ## Version 1.14.0 **Release date: October 27, 2022** ### Highlights - 📊 Built-in charts (e.g., `st.line_chart`) get a brand-new look and parameters `x` and `y`. Check out our [blog post](https://blog.streamlit.io/built-in-charts-get-a-new-look-and-parameters/) for more information. ### Notable Changes - 🏃️ Functions cached with `st.experimental_memo` or `st.experimental_singleton` can now contain static `st` commands. This allows caching text, charts, dataframes, and more! - 🐛 Design tweak to prevent jittering in sliders (https://github.com/streamlit/streamlit/pull/5612) - 🐛 Bug fix: links in headers are red, not blue (https://github.com/streamlit/streamlit/pull/5609) - 🐛 Bug fix: properly resize Plotly charts when exiting fullscreen (https://github.com/streamlit/streamlit/pull/5645) - 🐝 Bug fix: don't accidentally trigger `st.balloons` and `st.snow` (https://github.com/streamlit/streamlit/pull/5401) ### Other Changes - 🏚️ `st.time_input` allows for keyboard-only input (https://github.com/streamlit/streamlit/pull/5194) - 📚 `st.memo` will warn the user when using `ttl` and `persist` keyword argument together (https://github.com/streamlit/streamlit/pull/5032) - 🔖 `st.number_input` returns consistent type after rerun (https://github.com/streamlit/streamlit/pull/5359) - 📽 `st.sidebar` UI fixes including a fix for scrollbars in Firefox browsers (https://github.com/streamlit/streamlit/pull/5157, https://github.com/streamlit/streamlit/pull/5324) - 👩‍💻 Improvements to usage metrics to guide API development. - ✍️ More type hints! (https://github.com/streamlit/streamlit/pull/5191, https://github.com/streamlit/streamlit/pull/5192, https://github.com/streamlit/streamlit/pull/5242, https://github.com/streamlit/streamlit/pull/5243, https://github.com/streamlit/streamlit/pull/5244, https://github.com/streamlit/streamlit/pull/5245, https://github.com/streamlit/streamlit/pull/5246) Thanks [harahu](https://github.com/harahu)! - 📝 Upgraded `st.json` to support even more interactive charting improvements. See their [release notes](https://github.com/vega/vega-lite/releases) to find out more. (https://github.com/streamlit/streamlit/pull/4751) - 📈 Upgraded `st.vega_lite_chart` to use `datetime.timedelta` objects as `ttl` parameter value, properly hash PIL images and `Enum` classes, show better error messages when returning unevaluated dataframes (https://github.com/streamlit/streamlit/pull/4736, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4681, https://github.com/streamlit/streamlit/pull/4682, https://github.com/streamlit/streamlit/pull/4683, https://github.com/streamlit/streamlit/pull/4684, https://github.com/streamlit/streamlit/pull/4685, https://github.com/streamlit/streamlit/pull/4686, https://github.com/streamlit/streamlit/pull/4687, https://github.com/streamlit/streamlit/pull/4690, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4704, https://github.com/streamlit/streamlit/pull/4705, https://github.com/streamlit/streamlit/pull/4706, https://github.com/streamlit/streamlit/pull/4707, https://github.com/streamlit/streamlit/pull/4708, https://github.com/streamlit/streamlit/pull/4710, https://github.com/streamlit/streamlit/pull/4723, https://github.com/streamlit/streamlit/pull/4733) ## Version 1.13.0 **Release date: September 22, 2022** ### Highlights - 🗂 Widgets can customize how to hide their labels with the `label_visibility` parameter. ### Notable Changes - 🐛 Design tweak to prevent jittering in sliders (https://github.com/streamlit/streamlit/pull/5612) - 🐛 Bug fix: links in headers are red, not blue (https://github.com/streamlit/streamlit/pull/5609) - 🐛 Bug fix: properly resize Plotly charts when exiting fullscreen (https://github.com/streamlit/streamlit/pull/5645) - 🐝 Bug fix: don't accidentally trigger `st.balloons` and `st.snow` (https://github.com/streamlit/streamlit/pull/5401) ### Other Changes - 🏚️ `st.time_input` allows for keyboard-only input (https://github.com/streamlit/streamlit/pull/5194) - 📚 `st.memo` will warn the user when using `ttl` and `persist` keyword argument together (https://github.com/streamlit/streamlit/pull/5032) - 🔖 `st.number_input` returns consistent type after rerun (https://github.com/streamlit/streamlit/pull/5359) - 📽 `st.sidebar` UI fixes including a fix for scrollbars in Firefox browsers (https://github.com/streamlit/streamlit/pull/5157, https://github.com/streamlit/streamlit/pull/5324) - 👩‍💻 Improvements to usage metrics to guide API development. - ✍️ More type hints! (https://github.com/streamlit/streamlit/pull/5191, https://github.com/streamlit/streamlit/pull/5192, https://github.com/streamlit/streamlit/pull/5242, https://github.com/streamlit/streamlit/pull/5243, https://github.com/streamlit/streamlit/pull/5244, https://github.com/streamlit/streamlit/pull/5245, https://github.com/streamlit/streamlit/pull/5246) Thanks [harahu](https://github.com/harahu)! - 📝 Upgraded `st.json` to support even more interactive charting improvements. See their [release notes](https://github.com/vega/vega-lite/releases) to find out more. (https://github.com/streamlit/streamlit/pull/4751) - 📈 Upgraded `st.vega_lite_chart` to use `datetime.timedelta` objects as `ttl` parameter value, properly hash PIL images and `Enum` classes, show better error messages when returning unevaluated dataframes (https://github.com/streamlit/streamlit/pull/4736, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4681, https://github.com/streamlit/streamlit/pull/4682, https://github.com/streamlit/streamlit/pull/4683, https://github.com/streamlit/streamlit/pull/4684, https://github.com/streamlit/streamlit/pull/4685, https://github.com/streamlit/streamlit/pull/4686, https://github.com/streamlit/streamlit/pull/4687, https://github.com/streamlit/streamlit/pull/4690, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4704, https://github.com/streamlit/streamlit/pull/4705, https://github.com/streamlit/streamlit/pull/4706, https://github.com/streamlit/streamlit/pull/4707, https://github.com/streamlit/streamlit/pull/4708, https://github.com/streamlit/streamlit/pull/4710, https://github.com/streamlit/streamlit/pull/4723, https://github.com/streamlit/streamlit/pull/4733) ## Version 1.12.0 **Release date: August 11, 2022** ### Highlights - 📖 Introducing native support for multipage apps! Check out our [blog post](https://blog.streamlit.io/introducing-multipage-apps/) and try out our new `streamlit hello`. ### Notable Changes - ✨ `st.dataframe` has been redesigned. - 🔘 Radio and checkboxes improve focus on Keyboard navigation (https://github.com/streamlit/streamlit/pull/4801) - 📱 The sidebar will close when users select a page from the navigation menu on mobile devices (https://github.com/streamlit/streamlit/pull/4841) - 🧠 `st.memo` supports dataclasses! (https://github.com/streamlit/streamlit/pull/4850) - 🏎️ Bug fix for a race condition that destroyed widget state with rapid interaction (https://github.com/streamlit/streamlit/pull/4882) - 🏡 Get user information on private apps using `st.experimental_user`. ### Other Changes - 📊 Upgraded Vega-Lite library to support even more interactive charting improvements. See their [release notes](https://github.com/vega/vega-lite/releases) to find out more. (https://github.com/streamlit/streamlit/pull/4751) - 📈 Upgraded `st.vega_lite_chart` to use `datetime.timedelta` objects as `ttl` parameter value, properly hash PIL images and `Enum` classes, show better error messages when returning unevaluated dataframes (https://github.com/streamlit/streamlit/pull/4736) - 🐝 Types: More updated type annotations across Streamlit! (https://github.com/streamlit/streamlit/pull/4679, https://github.com/streamlit/streamlit/pull/4680, https://github.com/streamlit/streamlit/pull/4681, https://github.com/streamlit/streamlit/pull/4682, https://github.com/streamlit/streamlit/pull/4683, https://github.com/streamlit/streamlit/pull/4684, https://github.com/streamlit/streamlit/pull/4685, https://github.com/streamlit/streamlit/pull/4686, https://github.com/streamlit/streamlit/pull/4687, https://github.com/streamlit/streamlit/pull/4688, https://github.com/streamlit/streamlit/pull/4690, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4704, https://github.com/streamlit/streamlit/pull/4705, https://github.com/streamlit/streamlit/pull/4706, https://github.com/streamlit/streamlit/pull/4707, https://github.com/streamlit/streamlit/pull/4708, https://github.com/streamlit/streamlit/pull/4710, https://github.com/streamlit/streamlit/pull/4723, https://github.com/streamlit/streamlit/pull/4733) ## Version 1.11.0 **Release date: July 14, 2022** ### Highlights - 🗂 Introducing `st.tabs` to have tab containers in your app. See our [documentation](/develop/api-reference/layout/st.tabs) on how to use this feature. ### Notable Changes - ℹ️ `st.metric` supports tooltips with the `help` keyword parameter. - 🏃️ `st.columns` supports setting the gap size between columns with the `gap` keyword parameter. ### Other Changes - 🐛 Design tweak to prevent jittering in sliders (https://github.com/streamlit/streamlit/pull/4527) - 🐛 Bug fix: links in headers are red, not blue (https://github.com/streamlit/streamlit/pull/5609) - 🐛 Bug fix: properly resize Plotly charts when exiting fullscreen (https://github.com/streamlit/streamlit/pull/5645) - 🐝 Bug fix: don't accidentally trigger `st.balloons` and `st.snow` (https://github.com/streamlit/streamlit/pull/5401) - 🏚️ `st.time_input` allows for keyboard-only input (https://github.com/streamlit/streamlit/pull/5194) - 📚 `st.memo` will warn the user when using `ttl` and `persist` keyword argument together (https://github.com/streamlit/streamlit/pull/5032) - 🔖 `st.number_input` returns consistent type after rerun (https://github.com/streamlit/streamlit/pull/5359) - 📽 `st.sidebar` UI fixes including a fix for scrollbars in Firefox browsers (https://github.com/streamlit/streamlit/pull/5157, https://github.com/streamlit/streamlit/pull/5324) - 👩‍💻 Improvements to usage metrics to guide API development. - ✍️ More type hints! (https://github.com/streamlit/streamlit/pull/5191, https://github.com/streamlit/streamlit/pull/5192, https://github.com/streamlit/streamlit/pull/5242, https://github.com/streamlit/streamlit/pull/5243, https://github.com/streamlit/streamlit/pull/5244, https://github.com/streamlit/streamlit/pull/5245, https://github.com/streamlit/streamlit/pull/5246) Thanks [harahu](https://github.com/harahu)! - 📝 Upgraded `st.json` to support even more interactive charting improvements. See their [release notes](https://github.com/vega/vega-lite/releases) to find out more. (https://github.com/streamlit/streamlit/pull/4751) - 📈 Upgraded `st.vega_lite_chart` to use `datetime.timedelta` objects as `ttl` parameter value, properly hash PIL images and `Enum` classes, show better error messages when returning unevaluated dataframes (https://github.com/streamlit/streamlit/pull/4736, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4681, https://github.com/streamlit/streamlit/pull/4682, https://github.com/streamlit/streamlit/pull/4683, https://github.com/streamlit/streamlit/pull/4684, https://github.com/streamlit/streamlit/pull/4685, https://github.com/streamlit/streamlit/pull/4686, https://github.com/streamlit/streamlit/pull/4687, https://github.com/streamlit/streamlit/pull/4690, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4704, https://github.com/streamlit/streamlit/pull/4705, https://github.com/streamlit/streamlit/pull/4706, https://github.com/streamlit/streamlit/pull/4707, https://github.com/streamlit/streamlit/pull/4708, https://github.com/streamlit/streamlit/pull/4710, https://github.com/streamlit/streamlit/pull/4723, https://github.com/streamlit/streamlit/pull/4733) ## Version 1.10.0 **Release date: June 2, 2022** ### Highlights - 📖 Introducing native support for multipage apps! Check out our [blog post](https://blog.streamlit.io/introducing-multipage-apps/) and try out our new `streamlit hello`. ### Notable Changes - ✨ `st.dataframe` has been redesigned. - 🔘 Radio and checkboxes improve focus on Keyboard navigation (https://github.com/streamlit/streamlit/pull/4801) - 📱 The sidebar will close when users select a page from the navigation menu on mobile devices (https://github.com/streamlit/streamlit/pull/4841) - 🧠 `st.memo` supports dataclasses! (https://github.com/streamlit/streamlit/pull/4850) - 🏎️ Bug fix for a race condition that destroyed widget state with rapid interaction (https://github.com/streamlit/streamlit/pull/4882) - 🏡 Get user information on private apps using `st.experimental_user`. ### Other Changes - 📊 Upgraded Vega-Lite library to support even more interactive charting improvements. See their [release notes](https://github.com/vega/vega-lite/releases) to find out more. (https://github.com/streamlit/streamlit/pull/4751) - 📈 Upgraded `st.vega_lite_chart` to use `datetime.timedelta` objects as `ttl` parameter value, properly hash PIL images and `Enum` classes, show better error messages when returning unevaluated dataframes (https://github.com/streamlit/streamlit/pull/4736) - 🐝 Types: More updated type annotations across Streamlit! (https://github.com/streamlit/streamlit/pull/4679, https://github.com/streamlit/streamlit/pull/4680, https://github.com/streamlit/streamlit/pull/4681, https://github.com/streamlit/streamlit/pull/4682, https://github.com/streamlit/streamlit/pull/4683, https://github.com/streamlit/streamlit/pull/4684, https://github.com/streamlit/streamlit/pull/4685, https://github.com/streamlit/streamlit/pull/4686, https://github.com/streamlit/streamlit/pull/4687, https://github.com/streamlit/streamlit/pull/4688, https://github.com/streamlit/streamlit/pull/4690, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4704, https://github.com/streamlit/streamlit/pull/4705, https://github.com/streamlit/streamlit/pull/4706, https://github.com/streamlit/streamlit/pull/4707, https://github.com/streamlit/streamlit/pull/4708, https://github.com/streamlit/streamlit/pull/4710, https://github.com/streamlit/streamlit/pull/4723, https://github.com/streamlit/streamlit/pull/4733) ## Version 1.9.0 **Release date: May 4, 2022** ### Highlights - 🪗 `st.json` now supports a keyword-only argument, `expanded` on whether the JSON should be expanded by default (defaults to `True`). ### Notable Changes - 🏃️ Functions cached with `st.experimental_memo` or `st.experimental_singleton` can now contain static `st` commands. This allows caching text, charts, dataframes, and more! - 🐛 Design tweak to prevent jittering in sliders (https://github.com/streamlit/streamlit/pull/5612) - 🐛 Bug fix: links in headers are red, not blue (https://github.com/streamlit/streamlit/pull/5609) - 🐛 Bug fix: properly resize Plotly charts when exiting fullscreen (https://github.com/streamlit/streamlit/pull/5645) - 🐝 Bug fix: don't accidentally trigger `st.balloons` and `st.snow` (https://github.com/streamlit/streamlit/pull/5401) ### Other Changes - 🏚️ `st.time_input` allows for keyboard-only input (https://github.com/streamlit/streamlit/pull/5194) - 📚 `st.memo` will warn the user when using `ttl` and `persist` keyword argument together (https://github.com/streamlit/streamlit/pull/5032) - 🔖 `st.number_input` returns consistent type after rerun (https://github.com/streamlit/streamlit/pull/5359) - 📽 `st.sidebar` UI fixes including a fix for scrollbars in Firefox browsers (https://github.com/streamlit/streamlit/pull/5157, https://github.com/streamlit/streamlit/pull/5324) - 👩‍💻 Improvements to usage metrics to guide API development. - ✍️ More type hints! (https://github.com/streamlit/streamlit/pull/5191, https://github.com/streamlit/streamlit/pull/5192, https://github.com/streamlit/streamlit/pull/5242, https://github.com/streamlit/streamlit/pull/5243, https://github.com/streamlit/streamlit/pull/5244, https://github.com/streamlit/streamlit/pull/5245, https://github.com/streamlit/streamlit/pull/5246) Thanks [harahu](https://github.com/harahu)! - 📝 Upgraded `st.json` to support even more interactive charting improvements. See their [release notes](https://github.com/vega/vega-lite/releases) to find out more. (https://github.com/streamlit/streamlit/pull/4751) - 📈 Upgraded `st.vega_lite_chart` to use `datetime.timedelta` objects as `ttl` parameter value, properly hash PIL images and `Enum` classes, show better error messages when returning unevaluated dataframes (https://github.com/streamlit/streamlit/pull/4736, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4681, https://github.com/streamlit/streamlit/pull/4682, https://github.com/streamlit/streamlit/pull/4683, https://github.com/streamlit/streamlit/pull/4684, https://github.com/streamlit/streamlit/pull/4685, https://github.com/streamlit/streamlit/pull/4686, https://github.com/streamlit/streamlit/pull/4687, https://github.com/streamlit/streamlit/pull/4690, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4704, https://github.com/streamlit/streamlit/pull/4705, https://github.com/streamlit/streamlit/pull/4706, https://github.com/streamlit/streamlit/pull/4707, https://github.com/streamlit/streamlit/pull/4708, https://github.com/streamlit/streamlit/pull/4710, https://github.com/streamlit/streamlit/pull/4723, https://github.com/streamlit/streamlit/pull/4733) ## Version 1.8.0 **Release date: March 24, 2022** ### Highlights - 📊 Built-in charts (e.g., `st.line_chart`) get a brand-new look and parameters `x` and `y`. Check out our [blog post](https://blog.streamlit.io/built-in-charts-get-a-new-look-and-parameters/) for more information. ### Notable Changes - 🏃️ Functions cached with `st.experimental_memo` or `st.experimental_singleton` can now contain static `st` commands. This allows caching text, charts, dataframes, and more! - 🐛 Design tweak to prevent jittering in sliders (https://github.com/streamlit/streamlit/pull/5612) - 🐛 Bug fix: links in headers are red, not blue (https://github.com/streamlit/streamlit/pull/5609) - 🐛 Bug fix: properly resize Plotly charts when exiting fullscreen (https://github.com/streamlit/streamlit/pull/5645) - 🐝 Bug fix: don't accidentally trigger `st.balloons` and `st.snow` (https://github.com/streamlit/streamlit/pull/5401) ### Other Changes - 🏚️ `st.time_input` allows for keyboard-only input (https://github.com/streamlit/streamlit/pull/5194) - 📚 `st.memo` will warn the user when using `ttl` and `persist` keyword argument together (https://github.com/streamlit/streamlit/pull/5032) - 🔖 `st.number_input` returns consistent type after rerun (https://github.com/streamlit/streamlit/pull/5359) - 📽 `st.sidebar` UI fixes including a fix for scrollbars in Firefox browsers (https://github.com/streamlit/streamlit/pull/5157, https://github.com/streamlit/streamlit/pull/5324) - 👩‍💻 Improvements to usage metrics to guide API development. - ✍️ More type hints! (https://github.com/streamlit/streamlit/pull/5191, https://github.com/streamlit/streamlit/pull/5192, https://github.com/streamlit/streamlit/pull/5242, https://github.com/streamlit/streamlit/pull/5243, https://github.com/streamlit/streamlit/pull/5244, https://github.com/streamlit/streamlit/pull/5245, https://github.com/streamlit/streamlit/pull/5246) Thanks [harahu](https://github.com/harahu)! - 📝 Upgraded `st.json` to support even more interactive charting improvements. See their [release notes](https://github.com/vega/vega-lite/releases) to find out more. (https://github.com/streamlit/streamlit/pull/4751) - 📈 Upgraded `st.vega_lite_chart` to use `datetime.timedelta` objects as `ttl` parameter value, properly hash PIL images and `Enum` classes, show better error messages when returning unevaluated dataframes (https://github.com/streamlit/streamlit/pull/4736, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4681, https://github.com/streamlit/streamlit/pull/4682, https://github.com/streamlit/streamlit/pull/4683, https://github.com/streamlit/streamlit/pull/4684, https://github.com/streamlit/streamlit/pull/4685, https://github.com/streamlit/streamlit/pull/4686, https://github.com/streamlit/streamlit/pull/4687, https://github.com/streamlit/streamlit/pull/4690, https://github.com/streamlit/streamlit/pull/4703, https://github.com/streamlit/streamlit/pull/4704, https://github.com/streamlit/streamlit/pull/4705, https://github.com/streamlit/streamlit/pull/4706, https://github.com/streamlit/streamlit/pull/4707, https://github.com/streamlit/streamlit/pull/4708, https://github.com/streamlit/streamlit/pull/4710, https://github.com/streamlit/streamlit/pull/4723, https://github.com/streamlit/streamlit/pull/4733) ## Version 1.7.0 **Release --- # Source: https://docs.streamlit.io/develop/quick-reference/release-notes/2023 # 2023 release notes This page contains release notes for Streamlit versions released in 2023. For the latest version of Streamlit, see [Release notes](/develop/quick-reference/release-notes). ## Version 1.29.0 **Release date: November 30, 2023** ### Highlights - 🔲 Introducing a new testing framework for Streamlit apps! Check out our [documentation](/develop/api-reference/app-testing) to learn how to build automated tests for your apps. - 💻 Announcing the general availability of [st.connection](/develop/api-reference/connections/st.connection), a command to conveniently manage connections in Streamlit apps. Check out the [docs](/develop/api-reference/connections/st.connection) to learn more. - 🛠️ [SnowparkConnection](/develop/api-reference/connections/st.connection) has been upgraded to the new and improved [SnowflakeConnection](/develop/api-reference/connections/st.connections.snowflakeconnection) — the same, great functionality plus more! Check out our [built-in connections](/develop/api-reference/connections#built-in-connections). - 🏗️ [st.dataframe](/develop/api-reference/data/st.dataframe) and [st.data_editor](/develop/api-reference/data/st.data_editor) have a new toolbar! Users can search and download data in addition to enjoying improved UI for row additions and deletions. See our updated guide on [Dataframes](/develop/concepts/design/dataframes). - 📚 [st.pydeck_chart](/develop/api-reference/charts/st.pydeck_chart) now supports using different Graphviz layout engines (https://github.com/streamlit/streamlit/pull/7505, https://github.com/streamlit/streamlit/issues/4089). ### Notable Changes - 📊 When using a spinner with cached functions, the spinner will be overlaid instead of pushing content down (https://github.com/streamlit/streamlit/pull/7488). - 📅 st.dataframe and st.selectbox now support datetime index editing (https://github.com/streamlit/streamlit/pull/6974). - ⏱️ The `ttl` parameter in [st.cache_data](/develop/api-reference/caching-and-state/st.cache_data) and [st.cache_resource](/develop/api-reference/caching-and-state/st.cache_resource) accepts formatted strings, so you can simply say `ttl="30d"`, `ttl="1h30m"` and any other combination of `w`, `d`, `h`, `m`, `s` supported by [Pandas's Timedelta constructor](https://pandas.pydata.org/docs/reference/api/pandas.Timedelta.html) (https://github.com/streamlit/streamlit/pull/6560). ### Other Changes - 🐦 Improved string dtype handling for DataFrames (https://github.com/streamlit/streamlit/pull/7479). - ✒️ `st.write` will avoid using `unsafe_allow_html=True` if possible (https://github.com/streamlit/streamlit/pull/7432). - 🐛 Bug fix: Implementation of `st.expander` was simplified for improved behavior and consistency (https://github.com/streamlit/streamlit/pull/7247, https://github.com/streamlit/streamlit/issues/2839, https://github.com/streamlit/streamlit/issues/4111, https://github.com/streamlit/streamlit/issues/4651, https://github.com/streamlit/streamlit/issues/5604). - 🪲 Bug fix: Multipage links in the sidebar are now aligned with other sidebar elements (https://github.com/streamlit/streamlit/pull/7531). - 🏷️ [st.chat_input](/develop/api-reference/widgets/st.chat_message) won't incorrectly prompt for `label` parameter in IDEs (https://github.com/streamlit/streamlit/pull/7560). - 🐝 Bug fix: Label backgrounds for `st.tabs` are now transparent (https://github.com/streamlit/streamlit/pull/7070, https://github.com/streamlit/streamlit/issues/5707). - 🐝 Bug fix: Page width is no longer ignored when using the `help` parameter in `st.button` (https://github.com/streamlit/streamlit/pull/7033, https://github.com/streamlit/streamlit/issues/6161). - 🏷️ [st.code](/develop/api-reference/widgets/st.code) no longer triggers a `CachedStFunctionWarning` (https://github.com/streamlit/streamlit/pull/7306, https://github.com/streamlit/streamlit/issues/7055). ## Version 1.28.0 **Release date: October 26, 2023** ### Highlights - 📐 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Notable Changes - 📉 [st.experimental_user](/develop/api-reference/widgets/st.experimental_user) now defaults to `test@example.com` (https://github.com/streamlit/streamlit/pull/7219, https://github.com/streamlit/streamlit/issues/7215). - 🏷️ Removed unmaintained [pympler](https://github.com/streamlit/streamlit/pull/7193) dependency (https://github.com/streamlit/streamlit/pull/7193, https://github.com/streamlit/streamlit/issues/7131). ### Other Changes - 🐛 Bug fix: `st.multiselect` labels don't overlap when small ranges are selected (https://github.com/streamlit/streamlit/pull/7221, https://github.com/streamlit/streamlit/issues/3385). - 🐝 Bug fix: Type-checking correctly identifies all string types to avoid hashing errors (https://github.com/streamlit/streamlit/pull/7255, https://github.com/streamlit/streamlit/issues/6455). - 🐝 Bug fix: JSON is parsed with JSON5 to avoid errors from null values when using `st.pydeck_chart` (https://github.com/streamlit/streamlit/pull/7256, https://github.com/streamlit/streamlit/issues/5799). ## Version 1.27.0 **Release date: September 21, 2023** ### Highlights - 📐 Introducing [st.toast](/develop/api-reference/status/st.toast) — a command to briefly show toast messages to users in the bottom-right corner of apps. See [our documentation](/develop/api-reference/status/st.toast) on how to use this feature. ### Notable Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ### Other Changes - 📈 [st.date_input](/develop/api-reference/text/st.date_input) now uses `target="_self"` instead of opening a new tab (https://github.com/streamlit/streamlit/pull/7151, https://github.com/streamlit/streamlit/issues/7132). - 🛠️ [Forms](/develop/api-reference/execution-flow/st.form) can now be submitted with Enter/Return while inside [st.text_input](/develop/api-reference/widgets/st.text_input), [st.number_input](/develop/api-reference/widgets/st.number_input), or [st.text_area](/develop/api-reference/widgets/st.text_area) (https://github.com/streamlit/streamlit/pull/6911, https://github.com/streamlit/streamlit/issues/3790). ## Version 1.26.0 **Release date: August 24, 2023** ### Highlights - 📐 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Notable Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ### Other Changes - 📈 [st.date_input](/develop/api-reference/text/st.date_input) now uses `target="_self"` instead of opening a new tab (https://github.com/streamlit/streamlit/pull/7151, https://github.com/streamlit/streamlit/issues/7132). - 🛠️ [Forms](/develop/api-reference/execution-flow/st.form) can now be submitted with Enter/Return while inside [st.text_input](/develop/api-reference/widgets/st.text_input), [st.number_input](/develop/api-reference/widgets/st.number_input), or [st.text_area](/develop/api-reference/widgets/st.text_area) (https://github.com/streamlit/streamlit/pull/6911, https://github.com/streamlit/streamlit/issues/3790). ## Version 1.25.0 **Release date: July 20, 2023** ### Highlights - 📐 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Notable Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ### Other Changes - 📈 [st.date_input](/develop/api-reference/text/st.date_input) now uses `target="_self"` instead of opening a new tab (https://github.com/streamlit/streamlit/pull/7151, https://github.com/streamlit/streamlit/issues/7132). - 🛠️ [Forms](/develop/api-reference/execution-flow/st.form) can now be submitted with Enter/Return while inside [st.text_input](/develop/api-reference/widgets/st.text_input), [st.number_input](/develop/api-reference/widgets/st.number_input), or [st.text_area](/develop/api-reference/widgets/st.text_area) (https://github.com/streamlit/streamlit/pull/6911, https://github.com/streamlit/streamlit/issues/3790). ## Version 1.24.0 **Release date: June 27, 2023** ### Highlights - 📐 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Notable Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ### Other Changes - 📈 [st.date_input](/develop/api-reference/text/st.date_input) now uses `target="_self"` instead of opening a new tab (https://github.com/streamlit/streamlit/pull/7151, https://github.com/streamlit/streamlit/issues/7132). - 🛠️ [Forms](/develop/api-reference/execution-flow/st.form) can now be submitted with Enter/Return while inside [st.text_input](/develop/api-reference/widgets/st.text_input), [st.number_input](/develop/api-reference/widgets/st.number_input), or [st.text_area](/develop/api-reference/widgets/st.text_area) (https://github.com/streamlit/streamlit/pull/6911, https://github.com/streamlit/streamlit/issues/3790). ## Version 1.23.0 **Release date: June 1, 2023** ### Highlights - 📐 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Notable Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ### Other Changes - 📈 [st.date_input](/develop/api-reference/text/st.date_input) now uses `target="_self"` instead of opening a new tab (https://github.com/streamlit/streamlit/pull/7151, https://github.com/streamlit/streamlit/issues/7132). - 🛠️ [Forms](/develop/api-reference/execution-flow/st.form) can now be submitted with Enter/Return while inside [st.text_input](/develop/api-reference/widgets/st.text_input), [st.number_input](/develop/api-reference/widgets/st.number_input), or [st.text_area](/develop/api-reference/widgets/st.text_area) (https://github.com/streamlit/streamlit/pull/6911, https://github.com/streamlit/streamlit/issues/3790). ## Version 1.22.0 **Release date: April 27, 2023** ### Highlights - 📐 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Notable Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ### Other Changes - 📈 [st.date_input](/develop/api-reference/text/st.date_input) now uses `target="_self"` instead of opening a new tab (https://github.com/streamlit/streamlit/pull/7151, https://github.com/streamlit/streamlit/issues/7132). - 🛠️ [Forms](/develop/api-reference/execution-flow/st.form) can now be submitted with Enter/Return while inside [st.text_input](/develop/api-reference/widgets/st.text_input), [st.number_input](/develop/api-reference/widgets/st.number_input), or [st.text_area](/develop/api-reference/widgets/st.text_area) (https://github.com/streamlit/streamlit/pull/6911, https://github.com/streamlit/streamlit/issues/3790). ## Version 1.21.0 **Release date: April 6, 2023** ### Highlights - 📐 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Notable Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ### Other Changes - 📈 [st.date_input](/develop/api-reference/text/st.date_input) now uses `target="_self"` instead of opening a new tab (https://github.com/streamlit/streamlit/pull/7151, https://github.com/streamlit/streamlit/issues/7132). - 🛠️ [Forms](/develop/api-reference/execution-flow/st.form) can now be submitted with Enter/Return while inside [st.text_input](/develop/api-reference/widgets/st.text_input), [st.number_input](/develop/api-reference/widgets/st.number_input), or [st.text_area](/develop/api-reference/widgets/st.text_area) (https://github.com/streamlit/streamlit/pull/6911, https://github.com/streamlit/streamlit/issues/3790). ## Version 1.20.0 **Release date: March 09, 2023** ### Highlights - 📐 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.19.0 **Release date: February 23, 2023** ### Highlights - 📐 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.18.0 **Release date: February 09, 2023** ### Highlights - 📐 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.17.0 **Release date: January 12, 2023** ### Highlights - 🪄 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📈 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.16.0 **Release date: December 22, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.15.0 **Release date: December 14, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.14.0 **Release date: December 06, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.13.0 **Release date: November 29, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.12.0 **Release date: November 15, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.11.0 **Release date: November 02, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.10.0 **Release date: October 19, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.9.0 **Release date: October 05, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.8.0 **Release date: September 20, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.7.0 **Release date: September 06, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.6.0 **Release date: August 22, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.5.0 **Release date: August 08, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.4.0 **Release date: July 24, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.3.0 **Release date: July 10, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.2.0 **Release date: June 24, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.1.0 **Release date: June 10, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 1.0.0 **Release date: May 24, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 0.1.0 **Release date: May 10, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 0.0.0 **Release date: April 24, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 0.0.0 **Release date: April 10, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 0.0.0 **Release date: April 03, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 0.0.0 **Release date: March 27, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 0.0.0 **Release date: March 13, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 0.0.0 **Release date: March 06, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 0.0.0 **Release date: February 22, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 0.0.0 **Release date: February 14, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status) to display output from long-running processes and external API calls (https://github.com/streamlit/streamlit/pull/7140). Works great with [st.chat_message](/develop/api-reference/chat/st.chat_message)! ### Other Changes - 📺 [st.map](/develop/api-reference/charts/st.map) now has parameters for `latitude`, `longitude`, `color`, and `size` to customize data points (https://github.com/streamlit/streamlit/pull/6896). ## Version 0.0.0 **Release date: February 07, 2022** ### Highlights - 📈 Introducing [st.status](/develop/api-reference/status/st.status --- # Source: https://docs.streamlit.io/develop/quick-reference/release-notes/2024 # 2024 release notes This page contains release notes for Streamlit versions released in 2024. For the latest version of Streamlit, see [Release notes](/develop/quick-reference/release-notes). ## Version 1.41.0 **Release date: December 10, 2024** ### Notable Changes - 🔲 Text and background color in Markdown can use the "primary" color from the `theme.primaryColor` configuration option (https://github.com/streamlit/streamlit/pull/9676). - 🧼 You can set `use_container_width` for `st.columns` to make them always visible when scrolling horizontally (https://github.com/streamlit/streamlit/pull/9535). - 🛠️ Bug fix: Streamlit now watches for changes to imported modules in addition to pages (https://github.com/streamlit/streamlit/pull/8372). ### Other Changes - 📐 You can use icons from the Material Symbols library in Markdown (https://github.com/streamlit/streamlit/pull/8593). - 📷 Anchor button for headers display inline at the end of headers for a more beautiful and consistent appearance (https://github.com/streamlit/streamlit/pull/8587). - 🏗️ Custom components support callback functions (https://github.com/streamlit/streamlit/pull/8633, https://github.com/streamlit/streamlit/issues/3977). ## Version 1.39.0 **Release date: October 1, 2024** ### Highlights - 📿 Introducing `st.experimental_audio_input` to let users record with their microphones! (https://github.com/streamlit/streamlit/pull/9078). - 📷 You can pass `graphviz.Source` objects to `st.graphviz_chart` (https://github.com/streamlit/streamlit/pull/9078). ### Notable Changes - 🔲 You can pass `query` as a `sqlalchemy.URL.create` parameter so you can specify character sets (https://github.com/streamlit/streamlit/pull/8581). ### Other Changes - 📐 You can now set all query parameters with a single call to `st.query_params.from_dict` (https://github.com/streamlit/streamlit/pull/8666, https://github.com/streamlit/streamlit/issues/8644). ## Version 1.38.0 **Release date: August 27, 2024** ### Highlights - 📿 Introducing `st.context` to read headers and cookies! (https://github.com/streamlit/streamlit/pull/8593). - 📷 You can use `st.image` to add an image in the sidebar, above navigation (https://github.com/streamlit/streamlit/pull/8587). ### Notable Changes - 📈 You can now set `use_container_width` for `st.columns` to make them always visible when scrolling horizontally (https://github.com/streamlit/streamlit/pull/8587). ### Other Changes - 📐 You can now customize axis labels for `st.area_chart`, `st.bar_chart`, `st.line_chart`, and `st.scatter_chart` (https://github.com/streamlit/streamlit/pull/8640). ## Version 1.37.0 **Release date: May 23, 2024** ### Highlights - 📿 Introducing `st.experimental_dialog` to collect ratings and sentiment from your users! (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ### Other Changes - 📐 You can now set `use_container_width` for `st.columns` to make them always visible when scrolling horizontally (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.36.0 **Release date: April 4, 2024** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal dialogs! (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ### Other Changes - 📐 You can now set `use_container_width` for `st.columns` to make them always visible when scrolling horizontally (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.35.0 **Release date: March 7, 2024** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.34.0 **Release date: February 1, 2024** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.33.0 **Release date: January 23, 2024** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.32.0 **Release date: December 20, 2023** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.31.0 **Release date: November 6, 2023** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.30.0 **Release date: October 1, 2023** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.29.0 **Release date: September 20, 2023** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.28.0 **Release date: August 27, 2023** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.27.0 **Release date: July 25, 2023** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.26.0 **Release date: June 20, 2023** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.25.0 **Release date: May 23, 2023** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.24.0 **Release date: April 4, 2023** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.23.0 **Release date: March 7, 2023** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.22.0 **Release date: February 1, 2023** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.21.0 **Release date: January 23, 2023** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.20.0 **Release date: December 20, 2022** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.19.0 **Release date: November 6, 2022** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.18.0 **Release date: October 1, 2022** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.17.0 **Release date: September 20, 2022** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.16.0 **Release date: August 27, 2022** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.15.0 **Release date: July 25, 2022** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.14.0 **Release date: June 20, 2022** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.13.0 **Release date: May 23, 2022** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.12.0 **Release date: April 4, 2022** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.11.0 **Release date: March 7, 2022** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.10.0 **Release date: December 20, 2021** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.9.0 **Release date: November 6, 2021** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.8.0 **Release date: October 1, 2021** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.7.0 **Release date: September 20, 2021** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.6.0 **Release date: August 27, 2021** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.5.0 **Release date: July 25, 2021** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.4.0 **Release date: June 20, 2021** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.3.0 **Release date: May 23, 2021** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.2.0 **Release date: April 4, 2021** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.1.0 **Release date: March 7, 2021** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 1.0.0 **Release date: December 20, 2020** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 0.10.0 **Release date: November 6, 2020** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 0.9.0 **Release date: October 1, 2020** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 0.8.0 **Release date: September 20, 2020** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 0.7.0 **Release date: August 27, 2020** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 0.6.0 **Release date: July 25, 2020** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 0.5.0 **Release date: June 20, 2020** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 0.4.0 **Release date: May 23, 2020** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github.com/streamlit/streamlit/pull/8633). ### Notable Changes - 📷 You can now pass subtitles to `st.video`! (https://github.com/streamlit/streamlit/pull/8203). ### Other Changes - 📐 You can now set `use_container_width` for `st.expander` to display a "show more" button for more consistent behavior (https://github.com/streamlit/streamlit/pull/8587). ## Version 0.3.0 **Release date: April 4, 2020** ### Highlights - 📿 Introducing `st.experimental_dialog` to create modal overlay that can also rerun independently from the rest of your app. (https://github --- # Source: https://docs.streamlit.io/develop/quick-reference/release-notes/2025 # 2025 release notes This page contains release notes for Streamlit versions released in 2025. For the latest version of Streamlit, see [Release notes](/develop/quick-reference/release-notes). ## Version 1.52.0 **Release date: December 3, 2025** ### Highlights - 📧 Introducing custom [light and dark theme](/develop/api-reference/configuration/theming) configuration options! - 📈 Announcing [reusable themes](/develop/api-reference/configuration/config.toml#theme)! ### Notable Changes - 🔕 To prevent widgets from resetting when you change a parameter, widgets are transitioning to an identity based only on their keys (if provided). The following widgets use only their key for their identity: - st.button - st.download_button - st.form_submit_button - st.checkbox - st.toggle - st.text_area - st.text_input - st.number_input - st.time_input - st.date_input - st.selectbox - st.multiselect - 🛠️ You can set the width of most Streamlit elements. - 🛠️ Font face declarations in [config.toml](/develop/api-reference/configuration/config.toml#theme) support weight and unicode ranges. - 📚 You can configure a list of allowed origins when CORS protection is enabled. - 📊 You can configure the width of the table cell to show the column type and button label. - 🪲 Bug fix: The file watcher has more robust exception handling and clearer logging. - 🐙 Bug fix: The file watcher correctly applies a lock to watched paths. - 🪳 Bug fix: The sidebar state is cleared when the client disconnects from the Streamlit server. - 🪱 Bug fix: The sidebar is closed when the sidebar is resized. - 🪳 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 Bug fix: The file watcher correctly retries reading files when blocked by a Python event loop. - 🐙 --- # Source: https://docs.streamlit.io/get-started/fundamentals/additional-features # Additional Streamlit features So you've read all about Streamlit's [Basic concepts](/get-started/fundamentals/main-concepts) and gotten a taste of caching and Session State in [Advanced concepts](/get-started/fundamentals/advanced-concepts). But what about the bells and whistles? Here's a quick look at some extra features to take your app to the next level. ## Theming Streamlit supports Light and Dark themes out of the box. Streamlit will first check if the user viewing an app has a Light or Dark mode preference set by their operating system and browser. If so, then that preference will be used. Otherwise, the Light theme is applied by default. You can also change the active theme from "⋮" → "Settings". ![Changing Themes](/images/change_theme.gif) Want to add your own theme to an app? The "Settings" menu has a theme editor accessible by clicking on "Edit active theme". You can use this editor to try out different colors and see your app update live. ![Editing Themes](/images/edit_theme.gif) When you're happy with your work, themes can be saved by [setting config options](/develop/concepts/configuration) in the `[theme]` config section. After you've defined a theme for your app, it will appear as "Custom Theme" in the theme selector and will be applied by default instead of the included Light and Dark themes. More information about the options available when defining a theme can be found in the [theme option documentation](/develop/concepts/configuration/theming). **Note:** The theme editor menu is available only in local development. If you've deployed your app using Streamlit Community Cloud, the "Edit active theme" button will no longer be displayed in the "Settings" menu. **Tip:** Another way to experiment with different theme colors is to turn on the "Run on save" option, edit your config.toml file, and watch as your app reruns with the new theme colors applied. ## Pages As apps grow large, it becomes useful to organize them into multiple pages. This makes the app easier to manage as a developer and easier to navigate as a user. Streamlit provides a powerful way to create multipage apps using [st.Page](/develop/api-reference/navigation/st.page) and [st.navigation](/develop/api-reference/navigation/st.navigation). Just create your pages and connect them with navigation as follows: 1. Create an entry point script that defines and connects your pages 2. Create separate Python files for each page's content 3. Use [st.Page](/develop/api-reference/navigation/st.page) to define your pages and [st.navigation](/develop/api-reference/navigation/st.navigation) to connect them Here's an example of a three-page app: ### `streamlit_app.py` ```python import streamlit as st # Define the pages main_page = st.Page("main_page.py", title="Main Page", icon="🎈") page_2 = st.Page("page_2.py", title="Page 2", icon="❄️") page_3 = st.Page("page_3.py", title="Page 3", icon="🎉") # Set up navigation pg = st.navigation([main_page, page_2, page_3]) # Run the selected page pg.run() ``` ### `main_page.py` ```python import streamlit as st # Main page content st.markdown("# Main page 🎈") st.sidebar.markdown("# Main page 🎈") ``` ### `page_2.py` ```python import streamlit as st st.markdown("# Page 2 ❄️") st.sidebar.markdown("# Page 2 ❄️") ``` ### `page_3.py` ```python import streamlit as st st.markdown("# Page 3 🎉") st.sidebar.markdown("# Page 3 🎉") ``` ![MPA-V2-Main Concepts](/images/mpa-v2-main-concepts.gif) Our documentation on [Multipage apps](/develop/concepts/multipage-apps) teaches you how to add pages to your app, including how to define pages, structure and run multipage apps, and navigate between pages. Once you understand the basics, [create your first multipage app](/get-started/tutorials/create-a-multipage-app)! ## Custom components If you can't find the right component within the Streamlit library, try out custom components to extend Streamlit's built-in functionality. Explore and browse through popular, community-created components in the [Components gallery](https://streamlit.io/components). If you dabble in frontend development, you can build your own custom component with Streamlit's [components API](/develop/concepts/custom-components/intro). ## Static file serving As you learned in Streamlit fundamentals, Streamlit runs a server that clients connect to. That means viewers of your app don't have direct access to the files which are local to your app. Most of the time, this doesn't matter because Streamlt commands handle that for you. When you use `st.image` your Streamlit server will access the file and handle the necessary hosting so your app viewers can see it. However, if you want a direct URL to an image or file you'll need to host it. This requires setting the correct configuration and placing your hosted files in a directory named `static`. For example, your project could look like: ```bash your-project/ ├── static/ │ └── my_hosted-image.png └── streamlit_app.py ``` To learn more, read our guide on [Static file serving](/develop/concepts/configuration/serving-static-files). ## App testing Good development hygiene includes testing your code. Automated testing allows you to write higher quality code, faster! Streamlit has a built-in testing framework that lets you build tests easily. Use your favorite testing framework to run your tests. We like [pytest](https://pypi.org/project/pytest/). When you test a Streamlit app, you simulate running the app, declare user input, and inspect the results. You can use GitHub workflows to automate your tests and get instant alerts about breaking changes. Learn more in our guide to [App testing](/develop/concepts/app-testing). --- # Source: https://docs.streamlit.io/get-started/fundamentals/advanced-concepts # Advanced concepts of Streamlit Now that you know how a Streamlit app runs and handles data, let's talk about being efficient. Caching allows you to save the output of a function so you can skip over it on rerun. Session State lets you save information for each user that is preserved between reruns. This not only allows you to avoid unecessary recalculation, but also allows you to create dynamic pages and handle progressive processes. ## Caching Caching allows your app to stay performant even when loading data from the web, manipulating large datasets, or performing expensive computations. The basic idea behind caching is to store the results of expensive function calls and return the cached result when the same inputs occur again. This avoids repeated execution of a function with the same input values. To cache a function in Streamlit, you need to apply a caching decorator to it. You have two choices: - `st.cache_data` is the recommended way to cache computations that return data. Use `st.cache_data` when you use a function that returns a serializable data object (e.g., str, int, float, DataFrame, dict, list). **It creates a new copy of the data at each function call**, making it safe against [mutations and race conditions](/develop/concepts/architecture/caching#mutation-and-concurrency-issues). The behavior of `st.cache_data` is what you want in most cases – so if you're unsure, start with `st.cache_data` and see if it works! - `st.cache_resource` is the recommended way to cache global resources like ML models or database connections. Use `st.cache_resource` when your function returns unserializable objects that you don’t want to load multiple times. **It returns the cached object itself**, which is shared across all reruns and sessions without copying or duplication. If you mutate an object that is cached using `st.cache_resource`, that mutation will exist across all reruns and sessions. ### Example ```python import streamlit as st conn = st.connection("my_database") df = conn.query("select * from my_table") st.dataframe(df) ``` ### Example ```python import streamlit as st import pandas as pd import numpy as np if "df" not in st.session_state: st.session_state.df = pd.DataFrame(np.random.randn(20, 2), columns=["x", "y"]) st.header("Choose a datapoint color") color = st.color_picker("Color", "#FF0000") st.divider() st.scatter_chart(st.session_state.df, x="x", y="y", color=color) ``` If you are pulling the same data for all users, you'd likely cache a function that retrieves that data. On the other hand, if you pull data specific to a user, such as querying their personal information, you may want to save that in Session State. That way, the queried data is only available in that one session. As mentioned in [Basic concepts](/get-started/fundamentals/main-concepts#widgets), Session State is also related to widgets. Widgets are magical and handle statefulness quietly on their own. As an advanced feature however, you can manipulate the value of widgets within your code by assigning keys to them. Any key assigned to a widget becomes a key in Session State tied to the value of the widget. This can be used to manipulate the widget. After you finish understanding the basics of Streamlit, check out our guide on [Widget behavior](/develop/concepts/architecture/widget-behavior) to dig in the details if you're interested. ## Connections As hinted above, you can use `@st.cache_resource` to cache connections. This is the most general solution which allows you to use almost any connection from any Python library. However, Streamlit also offers a convenient way to handle some of the most popular connections, like SQL! `st.connection` takes care of the caching for you so you can enjoy fewer lines of code. Getting data from your database can be as easy as: ```python import streamlit as st conn = st.connection("my_database") df = conn.query("select * from my_table") st.dataframe(df) ``` Of course, you may be wondering where your username and password go. Streamlit has a convenient mechanism for [Secrets management](/develop/concepts/connections/secrets-management). For now, let's just see how `st.connection` works very nicely with secrets. In your local project directory, you can save a `.streamlit/secrets.toml` file. You save your secrets in the toml file and `st.connection` just uses them! For example, if you have an app file `streamlit_app.py` your project directory may look like this: ```bash your-LOCAL-repository/ ├── .streamlit/ │ └── secrets.toml # Make sure to gitignore this! └── streamlit_app.py ``` For the above SQL example, your `secrets.toml` file might look like the following: ```toml [connections.my_database] type="sql" dialect="mysql" username="xxx" password="xxx" host="example.com" # IP or URL port=3306 # Port number database="mydb" # Database name ``` Since you don't want to commit your `secrets.toml` file to your repository, you'll need to learn how your host handles secrets when you're ready to publish your app. Each host platform may have a different way for you to pass your secrets. If you use Streamlit Community Cloud for example, each deployed app has a settings menu where you can load your secrets. After you've written an app and are ready to deploy, you can read all about how to [Deploy your app](/deploy/streamlit-community-cloud/deploy-your-app) on Community Cloud. [forum](/get-started/fundamentals/advanced-concepts#) ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. --- # Source: https://docs.streamlit.io/get-started/installation/anaconda-distribution # Install Streamlit using Anaconda Distribution This page walks you through installing Streamlit locally using Anaconda Distribution. At the end, you'll build a simple "Hello world" app and run it. You can read more about [Getting started with Anaconda Distribution](https://docs.anaconda.com/free/anaconda/getting-started/) in Anaconda's docs. If you prefer to manage your Python environments via command line, check out how to [Install Streamlit using command line](/get-started/installation/command-line). ## Prerequisites 1. **A code editor** Anaconda Distribution includes Python and basically everything you need to get started. The only thing left for you to choose is a code editor. Our favorite editor is [VS Code](https://code.visualstudio.com/download), which is also what we use in all our tutorials. 2. **Knowledge about environment managers** Environment managers create virtual environments to isolate Python package installations between projects. For a detailed introduction to Python environments, check out [Python Virtual Environments: A Primer](https://realpython.com/python-virtual-environments-a-primer/). But don't worry! In this guide we'll teach you how to install and use an environment manager (Anaconda). ## Install Anaconda Distribution 1. Go to [anaconda.com/download](https://www.anaconda.com/download). 2. Install Anaconda Distribution for your OS. 3. Open Anaconda Navigator (the graphical interface included with Anaconda Distribution). 4. You can decline signing in to Anaconda if prompted. 5. In the left menu, click "Environments". 6. At the bottom of your environments list, click "Create". 7. Enter "streamlitenv" for the name of your environment. 8. Click "Create". 9. In your terminal, type: ```bash pip install streamlit ``` 10. To validate your installation, enter: ```bash streamlit hello ``` If this doesn't work, use the long-form command: ```bash python -m streamlit hello ``` 11. The Streamlit Hello example app will automatically open in your browser. If it doesn't, open your browser and go to the localhost address indicated in your terminal, typically `http://localhost:8501`. Play around with the app! 12. Close your terminal. ## Create a `Hello World` app and run it 1. Open VS Code with a new project. 2. Create a Python file named `app.py` in your project folder. 3. Copy the following code into `app.py` and save it. ```python import streamlit as st st.write("Hello World") ``` 4. Click your Python interpreter in the lower-right corner, then choose your `streamlitenv` environment from the drop-down. 5. Right-click `app.py` in your file navigation and click "Open in integrated terminal". 6. A terminal will open with your environment activated. Confirm this by looking for "(streamlitenv)" at the beginning of your next prompt. If it is not there, manually activate your environment with the command: ```bash conda activate streamlitenv ``` 7. In your terminal, type: ```bash streamlit run app.py ``` 8. If this doesn't work, use the long-form command: ```bash python -m streamlit run app.py ``` 9. Your app will automatically open in your browser. If it doesn't for any reason, open your browser and go to the localhost address indicated in your terminal, typically `http://localhost:8501`. 10. Change `st.write` to `st.title` and save your file: ```python import streamlit as st st.title("Hello World") ``` 11. In your browser, click "Always rerun" to instantly rerun your app whenever you save a change to your file. 12. Your app will update! Keep making changes and you will see your changes as soon as you save your file. 13. When you're done, you can stop your app with `Ctrl+C` in your terminal or just by closing your terminal. ## What's next? Read about our [Basic concepts](/get-started/fundamentals/main-concepts) and try out more commands in your app. --- # Source: https://docs.streamlit.io/develop/concepts/design/animate # Animate and update elements Sometimes you display a chart or dataframe and want to modify it live as the app runs (for example, in a loop). Some elements have built-in methods to allow you to update them in-place without rerunning the app. Updatable elements include the following: - `st.empty` containers can be written to in sequence and will always show the last thing written. They can also be cleared with an additional `.empty()` called like a method. - `st.dataframe`, `st.table`, and many chart elements can be updated with the `.add_rows()` method which appends data. - `st.progress` elements can be updated with additional `.progress()` calls. They can also be cleared with a `.empty()` method call. - `st.status` containers have an `.update()` method to change their labels, expanded state, and status. - `st.toast` messages can be updated in place with additional `.toast()` calls. ## `st.empty` containers `st.empty` can hold a single element. When you write any element to an `st.empty` container, Streamlit discards its previous content displays the new element. You can also `st.empty` containers by calling `.empty()` as a method. If you want to update a set of elements, use a plain container (`st.container()`) inside `st.empty` and write contents to the plain container. Rewrite the plain container and its contents as often as desired to update your app's display. ```python import streamlit as st import pandas as pd import numpy as np import time df = pd.DataFrame(np.random.randn(15, 3), columns=['A', 'B', 'C']) my_data_element = st.line_chart(df) for tick in range(10): time.sleep(.5) add_df = pd.DataFrame(np.random.randn(1, 3), columns=['A', 'B', 'C']) my_data_element.add_rows(add_df) st.button("Regenerate") --- # Source: https://docs.streamlit.io/develop/tutorials/elements/annotate-an-altair-chart # Annotate an Altair chart Altair allows you to annotate your charts with text, images, and emojis. You can do this by overlaying two charts to create a layered chart. Within the data layer, you'll add a multi-line tooltip to show information about datapoints. To learn more about multi-line tooltips, see this example in Vega-Altair's documentation. You'll add another tooltip to the annotation layer. ## Build the data layer You'll build an interactive time-series chart of the stock prices with a multi-line tooltip. The x-axis represents the date, and the y-axis represents the stock price. 1. Import data from `vega_datasets`. 2. Define a mouseover selection event in Altair. 3. Define a basic line chart to graph the five series in your data set. 4. Draw points on the lines and highlight them based on the mouseover selection. 5. Draw a vertical rule at the location of the mouseover selection. 6. Combine the lines, points, and tooltips into a single chart. 7. Optional: Test out your code by rendering your data layer. 8. Save your file and examine the chart in your app. Use your mouse to hover over points. Observe the circle marks, vertical line, and tooltip as you hover over a point. Delete the line or keep it at the end of your app to be updated as you continue. ## Build the annotation layer Now that you have the first chart that shows the data, you can annotate it with text and an emoji. In this section, you'll add some emojis and tooltips to mark specific points of interest. 1. Create a list of annotations. 2. Create a scatter plot with the x-axis representing the date and the y-axis representing the height (price) of each annotation. 3. Define the combined chart. 4. Display the chart in Streamlit. ## Combine the chart layers 1. Define the combined chart. 2. Display the chart in Streamlit. ## Next steps Play around with your new app. - If you want to use custom images instead of text or emojis to annotate your chart, you can replace the line containing `.mark_text()` with `.mark_image()`. For some URL string stored in a variable `IMAGE_URL`, you could do something like this: - If you want to enable panning and zooming for your chart, add `.interactive()` when you define your combined chart: --- # Source: https://docs.streamlit.io/develop/api-reference # API Reference - Streamlit Docs API Reference ------------- Visually explore a gallery of Streamlit's API. Streamlit makes it easy for you to visualize, mutate, and share data. The API reference is organized by activity type, like displaying data or optimizing performance. Each section includes methods associated with the activity type, including examples. Browse our API below and click to learn more about any of our available commands! 🎈 ### Display almost anything #### Markdown Display string formatted as Markdown. ```python st.markdown("Hello **world**!") ``` ### Dataframes Display a dataframe as an interactive table. ```python st.dataframe(my_data_frame) ``` ### Data editor Display a data editor widget. ```python edited = st.data_editor(df, num_rows=5) ``` ### Column configuration Configure the display and editing behavior of dataframes and data editors. ```python st.column_config.NumberColumn('Price (in USD)', min_value=0, format='$%d') ``` ### Static tables Display a static table. ```python st.table(my_data_frame) ``` ### Line chart Display a line chart. ```python st.line_chart(my_data_frame) ``` ### Scatterplot on maps Display a map with points on it. ```python st.map(my_data_frame) ``` ### Plotly Display a plotly chart. ```python st.plotly_chart(my_plotly_chart) ``` ### PyDeck Display a chart using the PyDeck library. ```python st.pydeck_chart(my_pydeck_chart) ``` ### Image Display an image or list of images. ```python st.image(numpy_array) st.image(image_bytes) st.image(file) st.image("https://example.com/myimage.jpg") ``` ### Logo Display a logo in the upper-left corner of your app and its sidebar. ```python st.logo("logo.jpg") ``` ### PDF Display a PDF file. ```python st.pdf(my_document.pdf) ``` ### Audio Display an audio player. ```python st.audio(numpy_array) st.audio(audio_bytes) st.audio(file) st.audio("https://example.com/myaudio.mp3", format="audio/mp3") ``` ### Video Display a video player. ```python st.video(numpy_array) st.video(video_bytes) st.video(file) st.video("https://example.com/myvideo.mp4", format="video/mp4") ``` ### Chat input Display a chat input widget. ```python prompt = st.chat_input("Say something") if prompt: st.write(f"The user has sent: {prompt}") ``` ### Text input Display a single-line text input widget. ```python name = st.text_input("First name") ``` ### Audio input Display a widget that allows users to record with their microphone. ```python speech = st.audio_input("Record a voice message") ``` ### Data editor Display a data editor widget. ```python content = st.data_editor(df, num_rows=5) ``` ### Page Define a page in a multipage app. ```python home = st.Page( "home.py", title="Home", icon="🏠", ) ``` ### Page link Display a link to another page in a multipage app. ```python st.page_link("app.py", label="Home", icon="🏠") st.page_link("pages/profile.py", label="My profile") ``` ### Modal dialog Insert a modal dialog that can rerun independently from the rest of the script. ```python @st.dialog("Sign up") def email_form(): name = st.text_input("Name") email = st.text_input("Email") ``` ### Status container Display output of long-running tasks in a container. ```python with st.status('Running'): do_something_slow() ``` ### Progress bar Display a progress bar. ```python for i in range(101): st.progress(i) do_something_slow() ``` ### Spinner Temporarily displays a message while executing a block of code. ```python with st.spinner("Please wait..."): do_something_slow() ``` ### Status container Display output of long-running tasks in a container. ```python with st.status('Running'): do_something_slow() ``` ### Toast Briefly displays a toast message in the bottom-right corner. ```python st.toast('Butter!', icon='🧈') ``` ### Snowflakes Display celebratory snowflakes! ```python do_something() # Celebrate when all done! st.snow() ``` ### Success box Display a success message. ```python st.success("Match found!") ``` ### Info box Display an informational message. ```python st.info("Dataset is updated every day at midnight.") ``` ### Warning box Display warning message. ```python st.warning("Unable to fetch image. Skipping...") ``` ### Error box Display error message. ```python st.error("We encountered an error") ``` ### Autorefresh Force a refresh without tying up a script. Created by @kmcgrady. ```python from streamlit_autorefresh import st_autorefresh st_autorefresh(interval=2000, limit=100, key="fizzbuzzcounter") ``` ### Pydantic Auto-generate Streamlit UI from Pydantic Models and Dataclasses. Created by @lukasmasuch. ```python import streamlit_pydantic as sp sp.pydantic_form(key="my_form", model=ExampleModel) ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by @blackary. ```python from st_pages import Page, show_pages, add_page_title show_pages([Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:")] ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/manage-your-app/app-analytics # App analytics Streamlit Community Cloud allows you to see the viewership of each of your apps. Specifically, you can see: - The total viewers count of your app (counted from April 2022). - The most recent unique viewers (capped at the last 20 viewers). - A relative timestamp of each unique viewer's last visit. ## Access your app analytics You can get to your app's analytics: - [From your workspace](#access-app-analytics-from-your-workspace). - [From your Cloud logs](#access-app-analytics-from-your-cloud-logs). ### Access app analytics from your workspace From your workspace at [share.streamlit.io](https://share.streamlit.io/), click the overflow icon (more_vert) next to your app. Click "Analytics". ### Access app analytics from your Cloud logs From your app at `.streamlit.app`, click "Manage app" in the lower-right corner. Click the overflow menu icon (more_vert) and click "Analytics". ## App viewers For public apps, we anonymize all viewers outside your workspace to protect their privacy and display anonymous viewers as random pseudonyms. You'll still be able to see the identities of fellow members in your workspace, including any viewers you've invited (once they've accepted). Meanwhile, for private apps where you control who has access, you will be able to see the specific users who recently viewed your apps. Additionally, you may occasionally see anonymous users in a private app. Rest assured, these anonymous users do have authorized view access granted by you or your workspace members. Common reasons why users show up anonymously are: - The app was previously public. - The given viewer viewed the app in April 2022, when the Streamlit team was honing user identification for this feature. See Streamlit's general [Privacy Notice](https://streamlit.io/privacy-policy). --- # Source: https://docs.streamlit.io/develop/concepts/architecture/app-chrome # The app chrome Your Streamlit app has a few widgets in the top right to help you as you develop. These widgets also help your viewers as they use your app. We call this things “the app chrome”. The chrome includes a status area, toolbar, and app menu. Your app menu is configurable. By default, you can access developer options from the app menu when viewing an app locally or on Streamlit Community Cloud while logged into an account with administrative access. While viewing an app, click the icon in the upper-right corner to access the menu. ## Menu options The menu is split into two sections. The upper section contains options available to all viewers and the lower section contains options for developers. Read more about [customizing this menu](#customize-the-menu) at the end of this page. ### Clear cache Reset your app's cache by clicking "Clear cache" from the app's menu or by pressing "C" on your keyboard while not focused on an input element. This will remove all cached entries for `@st.cache_data` and `@st.cache_resource`. ### Deploy this app If you are running an app locally from within a git repo, you can deploy your app to Streamlit Community Cloud in a few easy clicks! Make sure your work has been pushed to your online GitHub repository before beginning. For the greatest convenience, make sure you have already created your [Community Cloud account](/deploy/streamlit-community-cloud/get-started/create-your-account) and are signed in. 1. Click "Deploy" next to the app menu icon (more_vert). 2. Click "Deploy now". 3. You will be taken to Community Cloud's "Deploy an app" page. Your app's repository, branch, and file name will be prefilled to match your current app! Learn more about [deploying an app](/deploy/streamlit-community-cloud/deploy-your-app) on Streamlit Community Cloud. The whole process looks like this: ## Customize the menu Using `client.toolbarMode` in your app's [configuration](/develop/concepts/configuration), you can make the app menu appear in the following ways: - `developer` — Show the developer options to all viewers. - `viewer` — Hide the developer options from all viewers. - `minimal` — Show only those options set externally. These options can be declared through [st.set_page_config](/develop/api-reference/configuration/st.set_page_config) or populated through Streamlit Community Cloud. - `auto` — This is the default and will show the developer options when accessed through localhost or through Streamlit Community Cloud when logged into an administrative account for the app. Otherwise, the developer options will not show. --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/deploy-your-app/app-dependencies # App dependencies for your Community Cloud app The main reason that apps fail to build properly is because Streamlit Community Cloud can't find your dependencies! There are two kinds of dependencies your app might have: Python dependencies and external dependencies. Python dependencies are other Python packages (just like Streamlit!) that you `import` into your script. External dependencies are less common, but they include any other software your script needs to function properly. Because Community Cloud runs on Linux, these will be Linux dependencies installed with `apt-get` outside the Python environment. For your dependencies to be installed correctly, make sure you: 1. Add a [requirements file](#add-python-dependencies) for Python dependencies. 2. Optional: To manage any external dependencies, add a `packages.txt` file. ## Add Python dependencies With each `import` statement in your script, you are bringing in a Python dependency. You need to tell Community Cloud how to install those dependencies through a Python package manager. We recommend using a `requirements.txt` file, which is based on `pip`. You should _not_ include built-in Python libraries like `math`, `random`, or `distutils` in your `requirements.txt` file. These are a part of Python and aren't installed separately. Also, Community Cloud has `streamlit` installed by default. You don't strictly need to include `streamlit` unless you want to pin or restrict the version. If you deploy an app without a `requirements.txt` file, your app will run in an environment with just `streamlit` (and its dependencies) installed. If you have a script like the following, no extra dependencies would be needed since `pandas` and `numpy` are installed as direct dependencies of `streamlit`. Similarly, `math` and `random` are built into Python. ```python import streamlit as st import pandas as pd import numpy as np import math import random st.write("Hi!") ``` However, a valid `requirements.txt` file would be: ```none streamlit pandas numpy ``` Alternatively, if you needed to specify certain versions, another valid example would be: ```none streamlit==1.24.1 pandas>2.0 numpy<=1.25.1 ``` In the above example, `streamlit` is pinned to version `1.24.1`, `pandas` must be strictly greater than version 2.0, and `numpy` must be at-or-below version 1.25.1. Each line in your `requirements.txt` file is effectively what you would like to `pip install` into your cloud environment. ### Important You should only use one dependency file for your app. If you include more than one (e.g., `requirements.txt` and `environment.yaml`), only the first file encountered will be used as described above, with any dependency file in your entrypoint file's directory taking precedence over any dependency file in the root of your repository. ## apt-get dependencies For many apps, a `packages.txt` file is not required. However, if your script requires any software to be installed that is not a Python package, you need a `packages.txt` file. Community Cloud is built on Debian Linux. Anything you want to `apt-get install` must go in your `packages.txt` file. To browse available packages that can be installed, see the Debian 11 (`"bullseye"`) [package list](https://packages.debian.org/bullseye/). If `packages.txt` exists in the root directory of your repository we automatically detect it, parse it, and install the listed packages. You can read more about apt-get in [Linux documentation](https://linux.die.net/man/8/apt-get). Add `apt-get` dependencies to `packages.txt` — one package name per line. For example, `mysqlclient` is a Python package which requires additional software be installed to function. A valid `packages.txt` file to enable `mysqlclient` would be: ```none build-essential pkg-config default-libmysqlclient-dev ``` ### Warning You should only use one dependency file for your app. If you include more than one (e.g., `requirements.txt` and `environment.yaml`), only the first file encountered will be used as described above, with any dependency file in your entrypoint file's directory taking precedence over any dependency file in the root of your repository. --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/manage-your-app/app-settings # App settings This page is about your app settings on Streamlit Community Cloud. From your app settings you can [view or change your app's URL](/deploy/streamlit-community-cloud/manage-your-app/app-settings#view-or-change-your-apps-url), manage [public or private access to your app](/deploy/streamlit-community-cloud/share-your-app), and update your saved [secrets for your apps](/deploy/streamlit-community-cloud/deploy-your-app/secrets-management). If you access "Settings" from your [app chrome](/develop/concepts/architecture/app-chrome) in the upper-right corner of your running app, you can access features to control the appearance of your app while it's running. ## Access your app settings You can get to your app's settings: 1. Access your app's settings as described above. 2. On the "General" tab in the "App settings" dialog, see your app's unique subdomain in the "App URL" field. ![General app settings on Streamlit Community Cloud: Custom subdomain](/images/streamlit-community-cloud/workspace-app-settings-general.png) 3. Optional: Enter a new, custom subdomain between 6 and 63 characters in length, and then click "Save". ![New custom subdomain for your app](/images/streamlit-community-cloud/workspace-app-settings-general-valid-domain.png) If a custom subdomain is not available (e.g., because it's already taken or contains restricted words), you'll see an error message. Change your subdomain as indicated. ![Invalid custom subdomain for your app](/images/streamlit-community-cloud/workspace-app-settings-general-invalid-domain.png) ## Update your app's share settings Learn how to [Share your app](/deploy/streamlit-community-cloud/share-your-app). ![Share settings on Streamlit Community Cloud](/images/streamlit-community-cloud/workspace-app-settings-sharing.png) ## View or update your secrets 1. Access your app's settings as described above. 2. On the "Secrets" tab in the "App settings" dialog, see your app's secrets in the "Secrets" field. ![Secrets app settings on Streamlit Community Cloud](/images/streamlit-community-cloud/workspace-app-settings-secrets.png) 3. Optional: Add, edit, or delete your secrets, and then click "Save". Learn more about [Secrets management for your Community Cloud app](/deploy/streamlit-community-cloud/deploy-your-app/secrets-management). --- # Source: https://docs.streamlit.io/develop/api-reference/app-testing # Source: https://docs.streamlit.io/develop/concepts/app-testing # Streamlit's native app testing framework Streamlit app testing enables developers to build and run automated tests. Bring your favorite test automation software and enjoy simple syntax to simulate user input and inspect rendered output. The provided class, `AppTest`, simulates a running app and provides methods to set up, manipulate, and inspect the app contents via API instead of a browser UI. AppTest provides similar functionality to browser automation tools like Selenium or Playwright, but with less overhead to write and execute tests. Use our testing framework with a tool like [pytest](https://docs.pytest.org/) to execute or automate your tests. A typical pattern is to build a suite of tests for an app to ensure consistent functionality as the app evolves. The tests run locally and/or in a CI environment like GitHub Actions. ## Get started [Get started](/develop/concepts/app-testing/get-started) introduces you to the app testing framework and how to execute tests using `pytest`. Learn how to initialize and run simulated apps, including how to retrieve, manipulate, and inspect app elements. ## Beyond the basics [Beyond the basics](/develop/concepts/app-testing/beyond-the-basics) explains how to work with secrets and Session State within app tests, including how to test multipage apps. ## Automate your tests [Automate your tests](/develop/concepts/app-testing/automate-tests) with Continuous Integration (CI) to validate app changes over time. ## Example [Example](/develop/concepts/app-testing/examples) puts together the concepts explained above. Check out an app with multiple tests in place. ## Cheat sheet [Cheat sheet](/develop/concepts/app-testing/cheat-sheet) is a compact reference summarizing the available syntax. ## Previous and Next [Previous: Configuration and theming](/develop/concepts/configuration) [Next: Get started](/develop/concepts/app-testing/get-started) --- # Source: https://docs.streamlit.io/develop/concepts/architecture/architecture # Source: https://docs.streamlit.io/develop/concepts/architecture # Working with Streamlit's execution model ## Navigation - [Get started](/get-started) - [Installation](/get-started/installation) - [Fundamentals](/get-started/fundamentals) - [First steps](/get-started/tutorials) - [Develop](/develop) - [Concepts](/develop/concepts) - [Architecture and execution](/develop/concepts/architecture) - [Running your app](/develop/concepts/architecture/run-your-app) - [Streamlit's architecture](/develop/concepts/architecture/architecture) - [The app chrome](/develop/concepts/architecture/app-chrome) - [Caching](/develop/concepts/architecture/caching) - [Session State](/develop/concepts/architecture/session-state) - [Forms](/develop/concepts/architecture/forms) - [Fragments](/develop/concepts/architecture/fragments) - [Widget behavior](/develop/concepts/architecture/widget-behavior) - [Multipage apps](/develop/concepts/multipage-apps) - [Overview](/develop/concepts/multipage-apps/overview) - [Page and navigation](/develop/concepts/multipage-apps/page-and-navigation) - [Pages directory](/develop/concepts/multipage-apps/pages-directory) - [Working with widgets](/develop/concepts/multipage-apps/widgets) - [App design](/develop/concepts/design) - [Animate and update elements](/develop/concepts/design/animate) - [Button behavior and examples](/develop/concepts/design/buttons) - [Dataframes](/develop/concepts/design/dataframes) - [Multithreading](/develop/concepts/design/multithreading) - [Using custom classes](/develop/concepts/design/custom-classes) - [Working with timezones](/develop/concepts/design/timezone-handling) - [ADDITIONAL](/develop/concepts/design) - [Connections, secrets, and authentication](/develop/concepts/connections/connecting-to-data) - [Secrets management](/develop/concepts/connections/secrets-management) - [User authentication](/develop/concepts/connections/authentication) - [Security reminders](/develop/concepts/connections/security-reminders) - [Customize your theme](/develop/concepts/configuration/theming) - [Customize colors and borders](/develop/concepts/configuration/theming-customize-colors-and-borders) - [Customize fonts](/develop/concepts/configuration/theming-customize-fonts) - [App testing](/develop/concepts/app-testing) - [Get started](/develop/concepts/app-testing/get-started) - [Beyond the basics](/develop/concepts/app-testing/beyond-the-basics) - [Automate your tests](/develop/concepts/app-testing/automate-tests) - [Example](/develop/concepts/app-testing/examples) - [Cheat sheet](/develop/concepts/app-testing/cheat-sheet) - [API reference](/develop/api-reference) - [Tutorials](/develop/tutorials) - [Quick reference](/develop/quick-reference) - [Deploy](/deploy) - [Concepts](/deploy/concepts) - [Streamlit Community Cloud](/deploy/streamlit-community-cloud) - [Snowflake](/deploy/snowflake) - [Other platforms](/deploy/tutorials) - [Knowledge base](/knowledge-base) - [FAQ](/knowledge-base/using-streamlit) - [Installing dependencies](/knowledge-base/dependencies) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/app-analytics) - [Sanity checks](/knowledge-base/sanity-checks) - [How to create an anchor link?](/knowledge-base/using-streamlit/create-anchor-link) - [Enabling camera access in your browser](/knowledge-base/using-streamlit/enable-camera) - [How to download a file in Streamlit?](/knowledge-base/using-streamlit/how-download-file-streamlit) - [How to download a Pandas DataFrame as a CSV?](/knowledge-base/using-streamlit/how-download-pandas-dataframe-csv) - [How do you retrieve the filename of a file uploaded with st.file_uploader?](/knowledge-base/using-streamlit/retrieve-filename-uploaded) - [How can I make st.pydeck_chart use custom Mapbox styles?](/knowledge-base/using-streamlit/pydeck-chart-custom-mapbox-styles) - [How do I make Streamlit watch for changes in other modules I'm importing in my app?](/knowledge-base/using-streamlit/streamlit-watch-changes-other-modules-importing-app) - [What browsers does Streamlit support?](/knowledge-base/using-streamlit/supported-browsers) - [Where does st.file_uploader store uploaded files and when do they get deleted?](/knowledge-base/using-streamlit/where-file-uploader-store-when-deleted) - [Widget updating for every second input when using session state](/knowledge-base/using-streamlit/widget-updating-session-state) - [Why does Streamlit restrict nested st.columns?](/knowledge-base/using-streamlit/why-streamlit-restrict-nested-columns) - [What is serializable session state?](/knowledge-base/using-streamlit/serializable-session-state) - [How to share apps with viewers outside my organization?](/knowledge-base/using-streamlit/share-apps-with-viewers-outside-organization) - [How do I share apps with viewers outside my organization?](/knowledge-base/using-streamlit/share-apps-with-viewers-outside-organization) - [How do I deploy multiple Streamlit apps on different subdomains?](/knowledge-base/using-streamlit/deploy-multiple-streamlit-apps-different-subdomains) - [How do I deploy Streamlit on a domain so it appears to run on a regular port (i.e. port 80)?](/knowledge-base/using-streamlit/deploy-streamlit-domain-port-80) - [Does Streamlit support the WSGI Protocol? (aka Can I deploy Streamlit with gunicorn)?](/knowledge-base/using-streamlit/does-streamlit-support-wsgi-protocol) - [How do I increase the upload limit of st.file_uploader on Streamlit Community Cloud?](/knowledge-base/using-streamlit/increase-file-uploader-limit-streamlit-cloud) - [How do I submit a support case for Streamlit Community Cloud?](/knowledge-base/using-streamlit/how-to-submit-a-support-case-for-streamlit-community-cloud) - [Caching and state](/develop/concepts/architecture) - [Caching](/develop/concepts/architecture/caching) - [Session State](/develop/concepts/architecture/session-state) - [Forms](/develop/concepts/architecture/forms) - [Widget behavior](/develop/concepts/architecture/widget-behavior) - [App testing](/develop/concepts/app-testing) - [App analytics](/develop/concepts/app-testing/app-analytics) - [App settings](/develop/concepts/app-testing/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/deploy/app-analytics) - [App settings](/knowledge-base/deploy/app-settings) - [Delete your app](/knowledge-base/deploy/delete-your-app) - [Edit your app](/knowledge-base/deploy/edit-your-app) - [Favorite your app](/knowledge-base/deploy/favorite-your-app) - [Reboot your app](/knowledge-base/deploy/reboot-your-app) - [Rename your app in GitHub](/knowledge-base/deploy/rename-your-app) - [Upgrade Python](/knowledge-base/deploy/upgrade-python) - [Upgrade Streamlit](/knowledge-base/deploy/upgrade-streamlit) - [How to submit a support case for Streamlit Community Cloud](/knowledge-base/deploy/how-to-submit-a-support-case-for-streamlit-community-cloud) - [Knowledge base](/knowledge-base) - [FAQ](/knowledge-base/using-streamlit) - [Installing dependencies](/knowledge-base/dependencies) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/app-analytics) - [Sanity checks](/knowledge-base/sanity-checks) - [How to create an anchor link?](/knowledge-base/using-streamlit/create-anchor-link) - [Enabling camera access in your browser](/knowledge-base/using-streamlit/enable-camera) - [How to download a file in Streamlit?](/knowledge-base/using-streamlit/how-download-file-streamlit) - [How to download a Pandas DataFrame as a CSV?](/knowledge-base/using-streamlit/how-download-pandas-dataframe-csv) - [How do you retrieve the filename of a file uploaded with st.file_uploader?](/knowledge-base/using-streamlit/retrieve-filename-uploaded) - [How can I make st.pydeck_chart use custom Mapbox styles?](/knowledge-base/using-streamlit/pydeck-chart-custom-mapbox-styles) - [How do I make Streamlit watch for changes in other modules I'm importing in my app?](/knowledge-base/using-streamlit/streamlit-watch-changes-other-modules-importing-app) - [What browsers does Streamlit support?](/knowledge-base/using-streamlit/supported-browsers) - [Where does st.file_uploader store uploaded files and when do they get deleted?](/knowledge-base/using-streamlit/where-file-uploader-store-when-deleted) - [Widget updating for every second input when using session state](/knowledge-base/using-streamlit/widget-updating-session-state) - [Why does Streamlit restrict nested st.columns?](/knowledge-base/using-streamlit/why-streamlit-restrict-nested-columns) - [What is serializable session state?](/knowledge-base/using-streamlit/serializable-session-state) - [Caching and state](/develop/concepts/architecture) - [Caching](/develop/concepts/architecture/caching) - [Session State](/develop/concepts/architecture/session-state) - [Forms](/develop/concepts/architecture/forms) - [Widget behavior](/develop/concepts/architecture/widget-behavior) - [App testing](/develop/concepts/app-testing) - [App analytics](/develop/concepts/app-testing/app-analytics) - [App settings](/develop/concepts/app-testing/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/deploy/app-analytics) - [App settings](/knowledge-base/deploy/app-settings) - [Delete your app](/knowledge-base/deploy/delete-your-app) - [Edit your app](/knowledge-base/deploy/edit-your-app) - [Favorite your app](/knowledge-base/deploy/favorite-your-app) - [Reboot your app](/knowledge-base/deploy/reboot-your-app) - [Rename your app in GitHub](/knowledge-base/deploy/rename-your-app) - [Upgrade Python](/knowledge-base/deploy/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Knowledge base](/knowledge-base) - [FAQ](/knowledge-base/using-streamlit) - [Installing dependencies](/knowledge-base/dependencies) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/app-analytics) - [Sanity checks](/knowledge-base/sanity-checks) - [How to create an anchor link?](/knowledge-base/using-streamlit/create-anchor-link) - [Enabling camera access in your browser](/knowledge-base/using-streamlit/enable-camera) - [How to download a file in Streamlit?](/knowledge-base/using-streamlit/how-download-file-streamlit) - [How to download a Pandas DataFrame as a CSV?](/knowledge-base/using-streamlit/how-download-pandas-dataframe-csv) - [How do you retrieve the filename of a file uploaded with st.file_uploader?](/knowledge-base/using-streamlit/retrieve-filename-uploaded) - [How can I make st.pydeck_chart use custom Mapbox styles?](/knowledge-base/using-streamlit/pydeck-chart-custom-mapbox-styles) - [How do I make Streamlit watch for changes in other modules I'm importing in my app?](/knowledge-base/using-streamlit/streamlit-watch-changes-other-modules-importing-app) - [What browsers does Streamlit support?](/knowledge-base/using-streamlit/supported-browsers) - [Where does st.file_uploader store uploaded files and when do they get deleted?](/knowledge-base/using-streamlit/where-file-uploader-store-when-deleted) - [Widget updating for every second input when using session state](/knowledge-base/using-streamlit/widget-updating-session-state) - [Why does Streamlit restrict nested st.columns?](/knowledge-base/using-streamlit/why-streamlit-restrict-nested-columns) - [What is serializable session state?](/knowledge-base/using-streamlit/serializable-session-state) - [Caching and state](/develop/concepts/architecture) - [Caching](/develop/concepts/architecture/caching) - [Session State](/develop/concepts/architecture/session-state) - [Forms](/develop/concepts/architecture/forms) - [Widget behavior](/develop/concepts/architecture/widget-behavior) - [App testing](/develop/concepts/app-testing) - [App analytics](/develop/concepts/app-testing/app-analytics) - [App settings](/develop/concepts/app-testing/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/deploy/app-analytics) - [App settings](/knowledge-base/deploy/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Knowledge base](/knowledge-base) - [FAQ](/knowledge-base/using-streamlit) - [Installing dependencies](/knowledge-base/dependencies) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/app-analytics) - [Sanity checks](/knowledge-base/sanity-checks) - [How to create an anchor link?](/knowledge-base/using-streamlit/create-anchor-link) - [Enabling camera access in your browser](/knowledge-base/using-streamlit/enable-camera) - [How to download a file in Streamlit?](/knowledge-base/using-streamlit/how-download-file-streamlit) - [How to download a Pandas DataFrame as a CSV?](/knowledge-base/using-streamlit/how-download-pandas-dataframe-csv) - [How do you retrieve the filename of a file uploaded with st.file_uploader?](/knowledge-base/using-streamlit/retrieve-filename-uploaded) - [How can I make st.pydeck_chart use custom Mapbox styles?](/knowledge-base/using-streamlit/pydeck-chart-custom-mapbox-styles) - [How do I make Streamlit watch for changes in other modules I'm importing in my app?](/knowledge-base/using-streamlit/streamlit-watch-changes-other-modules-importing-app) - [What browsers does Streamlit support?](/knowledge-base/using-streamlit/supported-browsers) - [Where does st.file_uploader store uploaded files and when do they get deleted?](/knowledge-base/using-streamlit/where-file-uploader-store-when-deleted) - [Widget updating for every second input when using session state](/knowledge-base/using-streamlit/widget-updating-session-state) - [Why does Streamlit restrict nested st.columns?](/knowledge-base/using-streamlit/why-streamlit-restrict-nested-columns) - [What is serializable session state?](/knowledge-base/using-streamlit/serializable-session-state) - [Caching and state](/develop/concepts/architecture) - [Caching](/develop/concepts/architecture/caching) - [Session State](/develop/concepts/architecture/session-state) - [Forms](/develop/concepts/architecture/forms) - [Widget behavior](/develop/concepts/architecture/widget-behavior) - [App testing](/develop/concepts/app-testing) - [App analytics](/develop/concepts/app-testing/app-analytics) - [App settings](/develop/concepts/app-testing/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/deploy/app-analytics) - [App settings](/knowledge-base/deploy/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Knowledge base](/knowledge-base) - [FAQ](/knowledge-base/using-streamlit) - [Installing dependencies](/knowledge-base/dependencies) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/app-analytics) - [Sanity checks](/knowledge-base/sanity-checks) - [How to create an anchor link?](/knowledge-base/using-streamlit/create-anchor-link) - [Enabling camera access in your browser](/knowledge-base/using-streamlit/enable-camera) - [How to download a file in Streamlit?](/knowledge-base/using-streamlit/how-download-file-streamlit) - [How to download a Pandas DataFrame as a CSV?](/knowledge-base/using-streamlit/how-download-pandas-dataframe-csv) - [How do you retrieve the filename of a file uploaded with st.file_uploader?](/knowledge-base/using-streamlit/retrieve-filename-uploaded) - [How can I make st.pydeck_chart use custom Mapbox styles?](/knowledge-base/using-streamlit/pydeck-chart-custom-mapbox-styles) - [How do I make Streamlit watch for changes in other modules I'm importing in my app?](/knowledge-base/using-streamlit/streamlit-watch-changes-other-modules-importing-app) - [What browsers does Streamlit support?](/knowledge-base/using-streamlit/supported-browsers) - [Where does st.file_uploader store uploaded files and when do they get deleted?](/knowledge-base/using-streamlit/where-file-uploader-store-when-deleted) - [Widget updating for every second input when using session state](/knowledge-base/using-streamlit/widget-updating-session-state) - [Why does Streamlit restrict nested st.columns?](/knowledge-base/using-streamlit/why-streamlit-restrict-nested-columns) - [What is serializable session state?](/knowledge-base/using-streamlit/serializable-session-state) - [Caching and state](/develop/concepts/architecture) - [Caching](/develop/concepts/architecture/caching) - [Session State](/develop/concepts/architecture/session-state) - [Forms](/develop/concepts/architecture/forms) - [Widget behavior](/develop/concepts/architecture/widget-behavior) - [App testing](/develop/concepts/app-testing) - [App analytics](/develop/concepts/app-testing/app-analytics) - [App settings](/develop/concepts/app-testing/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/deploy/app-analytics) - [App settings](/knowledge-base/deploy/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Knowledge base](/knowledge-base) - [FAQ](/knowledge-base/using-streamlit) - [Installing dependencies](/knowledge-base/dependencies) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/app-analytics) - [Sanity checks](/knowledge-base/sanity-checks) - [How to create an anchor link?](/knowledge-base/using-streamlit/create-anchor-link) - [Enabling camera access in your browser](/knowledge-base/using-streamlit/enable-camera) - [How to download a file in Streamlit?](/knowledge-base/using-streamlit/how-download-file-streamlit) - [How to download a Pandas DataFrame as a CSV?](/knowledge-base/using-streamlit/how-download-pandas-dataframe-csv) - [How do you retrieve the filename of a file uploaded with st.file_uploader?](/knowledge-base/using-streamlit/retrieve-filename-uploaded) - [How can I make st.pydeck_chart use custom Mapbox styles?](/knowledge-base/using-streamlit/pydeck-chart-custom-mapbox-styles) - [How do I make Streamlit watch for changes in other modules I'm importing in my app?](/knowledge-base/using-streamlit/streamlit-watch-changes-other-modules-importing-app) - [What browsers does Streamlit support?](/knowledge-base/using-streamlit/supported-browsers) - [Where does st.file_uploader store uploaded files and when do they get deleted?](/knowledge-base/using-streamlit/where-file-uploader-store-when-deleted) - [Widget updating for every second input when using session state](/knowledge-base/using-streamlit/widget-updating-session-state) - [Why does Streamlit restrict nested st.columns?](/knowledge-base/using-streamlit/why-streamlit-restrict-nested-columns) - [What is serializable session state?](/knowledge-base/using-streamlit/serializable-session-state) - [Caching and state](/develop/concepts/architecture) - [Caching](/develop/concepts/architecture/caching) - [Session State](/develop/concepts/architecture/session-state) - [Forms](/develop/concepts/architecture/forms) - [Widget behavior](/develop/concepts/architecture/widget-behavior) - [App testing](/develop/concepts/app-testing) - [App analytics](/develop/concepts/app-testing/app-analytics) - [App settings](/develop/concepts/app-testing/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/deploy/app-analytics) - [App settings](/knowledge-base/deploy/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Knowledge base](/knowledge-base) - [FAQ](/knowledge-base/using-streamlit) - [Installing dependencies](/knowledge-base/dependencies) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/app-analytics) - [Sanity checks](/knowledge-base/sanity-checks) - [How to create an anchor link?](/knowledge-base/using-streamlit/create-anchor-link) - [Enabling camera access in your browser](/knowledge-base/using-streamlit/enable-camera) - [How to download a file in Streamlit?](/knowledge-base/using-streamlit/how-download-file-streamlit) - [How to download a Pandas DataFrame as a CSV?](/knowledge-base/using-streamlit/how-download-pandas-dataframe-csv) - [How do you retrieve the filename of a file uploaded with st.file_uploader?](/knowledge-base/using-streamlit/retrieve-filename-uploaded) - [How can I make st.pydeck_chart use custom Mapbox styles?](/knowledge-base/using-streamlit/pydeck-chart-custom-mapbox-styles) - [How do I make Streamlit watch for changes in other modules I'm importing in my app?](/knowledge-base/using-streamlit/streamlit-watch-changes-other-modules-importing-app) - [What browsers does Streamlit support?](/knowledge-base/using-streamlit/supported-browsers) - [Where does st.file_uploader store uploaded files and when do they get deleted?](/knowledge-base/using-streamlit/where-file-uploader-store-when-deleted) - [Widget updating for every second input when using session state](/knowledge-base/using-streamlit/widget-updating-session-state) - [Why does Streamlit restrict nested st.columns?](/knowledge-base/using-streamlit/why-streamlit-restrict-nested-columns) - [What is serializable session state?](/knowledge-base/using-streamlit/serializable-session-state) - [Caching and state](/develop/concepts/architecture) - [Caching](/develop/concepts/architecture/caching) - [Session State](/develop/concepts/architecture/session-state) - [Forms](/develop/concepts/architecture/forms) - [Widget behavior](/develop/concepts/architecture/widget-behavior) - [App testing](/develop/concepts/app-testing) - [App analytics](/develop/concepts/app-testing/app-analytics) - [App settings](/develop/concepts/app-testing/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/deploy/app-analytics) - [App settings](/knowledge-base/deploy/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Knowledge base](/knowledge-base) - [FAQ](/knowledge-base/using-streamlit) - [Installing dependencies](/knowledge-base/dependencies) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/app-analytics) - [Sanity checks](/knowledge-base/sanity-checks) - [How to create an anchor link?](/knowledge-base/using-streamlit/create-anchor-link) - [Enabling camera access in your browser](/knowledge-base/using-streamlit/enable-camera) - [How to download a file in Streamlit?](/knowledge-base/using-streamlit/how-download-file-streamlit) - [How to download a Pandas DataFrame as a CSV?](/knowledge-base/using-streamlit/how-download-pandas-dataframe-csv) - [How do you retrieve the filename of a file uploaded with st.file_uploader?](/knowledge-base/using-streamlit/retrieve-filename-uploaded) - [How can I make st.pydeck_chart use custom Mapbox styles?](/knowledge-base/using-streamlit/pydeck-chart-custom-mapbox-styles) - [How do I make Streamlit watch for changes in other modules I'm importing in my app?](/knowledge-base/using-streamlit/streamlit-watch-changes-other-modules-importing-app) - [What browsers does Streamlit support?](/knowledge-base/using-streamlit/supported-browsers) - [Where does st.file_uploader store uploaded files and when do they get deleted?](/knowledge-base/using-streamlit/where-file-uploader-store-when-deleted) - [Widget updating for every second input when using session state](/knowledge-base/using-streamlit/widget-updating-session-state) - [Why does Streamlit restrict nested st.columns?](/knowledge-base/using-streamlit/why-streamlit-restrict-nested-columns) - [What is serializable session state?](/knowledge-base/using-streamlit/serializable-session-state) - [Caching and state](/develop/concepts/architecture) - [Caching](/develop/concepts/architecture/caching) - [Session State](/develop/concepts/architecture/session-state) - [Forms](/develop/concepts/architecture/forms) - [Widget behavior](/develop/concepts/architecture/widget-behavior) - [App testing](/develop/concepts/app-testing) - [App analytics](/develop/concepts/app-testing/app-analytics) - [App settings](/develop/concepts/app-testing/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/deploy/app-analytics) - [App settings](/knowledge-base/deploy/app-settings) - [Delete your app](/develop/concepts/app-testing/delete-your-app) - [Edit your app](/develop/concepts/app-testing/edit-your-app) - [Favorite your app](/develop/concepts/app-testing/favorite-your-app) - [Reboot your app](/develop/concepts/app-testing/reboot-your-app) - [Rename your app in GitHub](/develop/concepts/app-testing/rename-your-app) - [Upgrade Python](/develop/concepts/app-testing/upgrade-python) - [Upgrade Streamlit](/develop/concepts/app-testing/upgrade-streamlit) - [Knowledge base](/knowledge-base) - [FAQ](/knowledge-base/using-streamlit) - [Installing dependencies](/knowledge-base/dependencies) - [Deployment issues](/knowledge-base/deploy) - [App analytics](/knowledge-base/app-analytics) - [Sanity checks](/knowledge-base/sanity-checks) - [How to create an anchor link?](/knowledge-base/using-streamlit/create-anchor-link) - [Enabling camera access in your browser](/knowledge-base/using-streamlit/enable-camera) - [How to download a file in Streamlit?](/knowledge-base/using-streamlit/how-download-file-streamlit) - [How to download a Pandas DataFrame as a CSV?](/knowledge-base/using-streamlit/how-download-pandas-dataframe-csv) - [How do you retrieve the filename of a file uploaded with st.file_uploader?](/knowledge-base/using-streamlit/retrieve-filename-uploaded) - [How can I make st.pydeck_chart use custom Mapbox styles?](/knowledge-base/using-streamlit/pydeck-chart-custom-mapbox-styles) - [How do I make Streamlit watch for changes in other modules I'm importing in my app?](/knowledge-base/using-streamlit/streamlit-watch-changes-other-modules-importing-app) - [What browsers does Streamlit support?](/knowledge-base/using-streamlit/supported-browsers) - [Where does st.file_uploader store uploaded files and when do they get deleted?](/knowledge-base/using-streamlit/where-file-uploader-store-when-deleted) - [Widget updating for every second input when using session state](/knowledge-base/using-streamlit/widget-updating-session-state) - [Why does Streamlit restrict nested st.columns?](/knowledge-base/using-streamlit/why-streamlit-restrict-nested-columns) - [What is serializable session state?](/knowledge-base/using-streamlit/serializable-session-state) - [Caching and state](/develop/concepts/architecture) - [Caching](/develop/concepts/architecture/caching) - [Session State](/develop/concepts/architecture/session-state) - [Forms](/develop/concepts/architecture/forms) - [Widget behavior](/develop/concepts/architecture/widget-behavior) - [App testing](/develop/concepts/app-testing) - [App analytics]( --- # Source: https://docs.streamlit.io/develop/tutorials/authentication # Source: https://docs.streamlit.io/develop/concepts/connections/authentication # User authentication and information Personalizing your app for your users is a great way to make your app more engaging. User authentication and personalization unlocks a plethora of use cases for developers, including controls for admins, a personalized stock ticker, or a chatbot app with a saved history between sessions. Before reading this guide, you should have a basic understanding of [secrets management](/develop/concepts/connections/secrets-management). ## OpenID Connect Streamlit supports user authentication with OpenID Connect (OIDC), which is an authentication protocol built on top of OAuth 2.0. OIDC supports authentication, but not authorization: that is, OIDC connections tell you who a user is (authentication), but don't give you the authority to impersonate them (authorization). If you need to connect with a generic OAuth 2.0 provider or have your app to act on behalf of a user, consider using or creating a custom component. Some popular OIDC providers are: - [Google Identity](https://developers.google.com/identity/openid-connect/openid-connect) - [Microsoft Entra ID](https://learn.microsoft.com/en-us/power-pages/security/authentication/openid-settings) - [Okta](https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_oidc.htm) - [Auth0](https://auth0.com/docs/get-started/auth0-overview/create-applications/regular-web-apps) ### Configure your OIDC connection in Streamlit After you've configured your identity-provider client, you'll need to configure your Streamlit app, too. `st.login()` uses your app's `secrets.toml` file to configure your connection, similar to how `st.connection()` works. Whether you have one OIDC provider or many, you'll need to declare a unique name for each. If you want to use Google Identity and Microsoft Entra ID as two providers for the same app, your configuration for local development will look like the following TOML file: ```toml [auth] redirect_uri = "http://localhost:8501/oauth2callback" cookie_secret = "xxx" client_id = "xxx" client_secret = "xxx" server_metadata_url = "https://{account}.{region}.auth0.com/.well-known/openid-configuration" ``` Microsoft's server metadata URL varies slightly depending on how your client is scoped. Replace `{tenant}` with the appropriate value described in Microsoft's documentation for [OpenID configuration](https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols-oidc#find-your-apps-openid-configuration-document-uri). Your app code: ```python import streamlit as st if not st.user.is_logged_in: if st.button("Log in with Google"): st.login("google") st.stop() if st.button("Log out"): st.logout() st.markdown(f"Welcome! {st.user.name}") ``` Using callbacks, this would look like: ```python import streamlit as st if not st.user.is_logged_in: st.button("Log in with Google", on_click=st.login) st.stop() st.button("Log out", on_click=st.logout) st.markdown(f"Welcome! {st.user.name}") ``` ## Passing keywords to your identity provider To customize the behavior of your identity provider, you may need to declare additional keywords. For a complete list of OIDC parameters, see [OpenID Connect Core](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest) and your provider's documentation. By default, Streamlit sets `scope="openid profile email"` and `prompt="select_account"`. You can change these and other OIDC parameters by passing a dictionary of settings to `client_kwargs`. `state` and `nonce`, which are used for security, are handled automatically and don't need to be specified. For example, if you are using Auth0 and need to force users to log in every time, use `prompt="login"` as described in Auth0's [Customize Signup and Login Prompts](https://auth0.com/docs/customize/login-pages/universal-login/customize-signup-and-login-prompts). Your configuration will look like this: ```toml [auth] redirect_uri = "http://localhost:8501/oauth2callback" cookie_secret = "xxx" [auth.auth0] client_id = "xxx" client_secret = "xxx" server_metadata_url = "https://{account}.{region}.auth0.com/.well-known/openid-configuration" client_kwargs = { "prompt" = "login" } ``` Hosted Code environments such as GitHub Codespaces have additional security controls in place preventing the login redirect to be handled properly. --- # Source: https://docs.streamlit.io/develop/concepts/app-testing/automate-tests # 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](https://docs.github.com/en/actions). For more information about GitHub Actions, see: - [Quickstart for GitHub Actions](https://docs.github.com/en/actions/quickstart) - [GitHub Actions: About continuous integration](https://docs.github.com/en/actions/automating-builds-and-tests/about-continuous-integration) - [GitHub Actions: Build & test Python](https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python) ## Streamlit App Action [Streamlit App Action](https://github.com/marketplace/actions/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: ```yaml # .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 ``` 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. If 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. ## 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](https://github.com/streamlit/llm-examples/actions), defined in [this workflow file](https://github.com/streamlit/llm-examples/blob/main/.github/workflows/app-testing.yml). [forum](https://docs.streamlit.io/develop/concepts/app-testing/automate-tests#forum) ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. --- # Source: https://docs.streamlit.io/develop/tutorials/databases/aws-s3 # Connect Streamlit to AWS S3 This guide explains how to securely access files on AWS S3 from Streamlit Community Cloud. It uses [Streamlit FilesConnection](https://github.com/streamlit/files-connection), the [s3fs](https://github.com/dask/s3fs) library, and optionally Streamlit's [Secrets management](https://docs.streamlit.io/develop/concepts/connections/secrets-management). ## Create an S3 bucket and add a file First, [sign up for AWS](https://aws.amazon.com/) or log in. Go to the [S3 console](https://s3.console.aws.amazon.com/s3/home) and create a new bucket: ![AWS screenshot 1](https://docs.streamlit.io/images/databases/aws-1.png) ![AWS screenshot 2](https://docs.streamlit.io/images/databases/aws-2.png) Navigate to the upload section of your new bucket: ![AWS screenshot 3](https://docs.streamlit.io/images/databases/aws-3.png) ![AWS screenshot 4](https://docs.streamlit.io/images/databases/aws-4.png) And note down the "AWS Region" for later. In this example, it's `us-east-1`, but it may differ for you. Next, upload the following CSV file, which contains some example data: [myfile.csv](https://docs.streamlit.io/images/databases/myfile.csv) ## Create access keys Go to the [AWS console](https://console.aws.amazon.com/), create access keys as shown below and copy the "Access Key ID" and "Secret Access Key": ![AWS screenshot 5](https://docs.streamlit.io/images/databases/aws-5.png) ![AWS screenshot 6](https://docs.streamlit.io/images/databases/aws-6.png) Access keys created as a root user have wide-ranging permissions. In order to make your AWS account more secure, you should consider creating an IAM account with restricted permissions and using its access keys. More information [here](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html). ## Set up your AWS credentials locally Streamlit FilesConnection and s3fs will read and use your existing [AWS credentials and configuration](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html) if available - such as from an `~/.aws/credentials` file or environment variables. If you don't already have this set up, or plan to host the app on Streamlit Community Cloud, you should specify the credentials from a file `.streamlit/secrets.toml` in your app's root directory or your home directory. Create this file if it doesn't exist yet and add to it the access key ID, access key secret, and the AWS default region you noted down earlier, as shown below: ```toml # .streamlit/secrets.toml AWS_ACCESS_KEY_ID = "xxx" AWS_SECRET_ACCESS_KEY = "xxx" AWS_DEFAULT_REGION = "xxx" ``` Be sure to replace `xxx` above with the values you noted down earlier, and add this file to `.gitignore` so you don't commit it to your GitHub repo! ## Copy your app secrets to the cloud To host your app on Streamlit Community Cloud, you will need to pass your credentials to your deployed app via secrets. Go to the [app dashboard](https://share.streamlit.io/) and in the app's dropdown menu, click on **Edit Secrets**. Copy the content of `secrets.toml` above into the text area. More information is available at [Secrets management](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app/secrets-management). ![Secrets manager screenshot](https://docs.streamlit.io/images/databases/edit-secrets.png) ## Add FilesConnection and s3fs to your requirements file Add the [FilesConnection](https://github.com/streamlit/files-connection) and [s3fs](https://github.com/dask/s3fs) packages to your `requirements.txt` file, preferably pinning the versions (replace `x.x.x` with the version you want installed): ```bash # requirements.txt s3fs==x.x.x st-files-connection ``` ## Write your Streamlit app Copy the code below to your Streamlit app and run it. Make sure to adapt the name of your bucket and file. Note that Streamlit automatically turns the access keys from your secrets file into environment variables, where `s3fs` searches for them by default. ```python # streamlit_app.py import streamlit as st from st_files_connection import FilesConnection # Create connection object and retrieve file contents. # Specify input format is a csv and to cache the result for 600 seconds. conn = st.connection('s3', type=FilesConnection) df = conn.read("testbucket-jrieke/myfile.csv", input_format="csv", ttl=600) # Print results. for row in df.itertuples(): st.write(f"{row.Owner} has a :{row.Pet}:") ``` See `st.connection` above? This handles secrets retrieval, setup, result caching, and retries. By default, `read()` results are cached without expiring. In this case, we set `ttl=600` to ensure the file contents is cached for no longer than 10 minutes. You can also set `ttl=0` to disable caching. Learn more in [Caching](https://docs.streamlit.io/develop/concepts/architecture/caching). If everything worked out (and you used the example file given above), your app should look like this: ![Finished app screenshot](https://docs.streamlit.io/images/databases/streamlit-app.png) --- # Source: https://docs.streamlit.io/develop/concepts/app-testing/beyond-the-basics # Beyond the basics of app testing Now that you're comfortable with executing a basic test for a Streamlit app let's cover the mutable attributes of [AppTest](/develop/api-reference/app-testing/st.testing.v1.apptest): - `AppTest.secrets` - `AppTest.session_state` - `AppTest.query_params` You can read and update values using dict-like syntax for all three attributes. For `.secrets` and `.query_params`, you can use key notation but not attribute notation. For example, the `.secrets` attribute for `AppTest` accepts `at.secrets["my_key"]` but **not** `at.secrets.my_key`. This differs from how you can use the associated command in the main library. On the other hand, `.session_state` allows both key notation and attribute notation. ## Using secrets with app testing Be careful not to include secrets directly in your tests. Consider this simple project with `pytest` executed in the project's root directory: ```none myproject/ ├── .streamlit/ │ ├── config.toml │ └── secrets.toml ├── app.py └── tests/ └── test_app.py ``` In the above scenario, your simulated app will have access to your `secrets.toml` file. However, since you don't want to commit your secrets to your repository, you may need to write tests where you securely pull your secrets into memory or use dummy secrets. ### Example: declaring secrets in a test Within a test, declare each secret after initializing your `AppTest` instance but before the first run. (A missing secret may result in an app that doesn't run!) For example, consider the following secrets file and corresponding test initialization to assign the same secrets manually: **Secrets file:** ```toml db_username = "Jane" db_password = "mypassword" [my_other_secrets] things_i_like = ["Streamlit", "Python"] ``` **Testing file with equivalent secrets:** ```python # Initialize an AppTest instance. at = AppTest.from_file("app.py") # Declare the secrets. at.secrets["db_username"] = "Jane" at.secrets["db_password"] = "mypassword" at.secrets["my_other_secrets.things_i_like"] = ["Streamlit", "Python"] # Run the app. at.run() assert at.markdown[0].value == ":balloon:" ``` By setting the value `at.session_state["magic_word"] = "Balloons"` within the test, you can simulate a user navigating to `second.py` after entering and saving "Balloons" on `first.py". --- # Source: https://docs.streamlit.io/develop/tutorials/databases/bigquery # Connect Streamlit to Google BigQuery This guide explains how to securely access a BigQuery database from Streamlit Community Cloud. It uses the [google-cloud-bigquery](https://googleapis.dev/python/bigquery/latest/index.html) library and Streamlit's [Secrets management](/develop/concepts/connections/secrets-management). ## Create a BigQuery Database Programmatic access to BigQuery is controlled through [Google Cloud Platform](https://cloud.google.com/). Create an account or sign in and head over to the [APIs & Services dashboard](https://console.cloud.google.com/apis/dashboard) (select or create a project if asked). As shown below, search for the BigQuery API and enable it: ![Bigquery screenshot 1](/images/databases/big-query-1.png) ![Bigquery screenshot 2](/images/databases/big-query-2.png) ![Bigquery screenshot 3](/images/databases/big-query-3.png) ## Create a Service Account & Key File To use the BigQuery API from Streamlit Community Cloud, you need a Google Cloud Platform service account (a special account type for programmatic data access). Go to the [Service Accounts](https://console.cloud.google.com/iam-admin/serviceaccounts) page and create an account with the **Viewer** permission (this will let the account access data but not change it): ![Bigquery screenshot 4](/images/databases/big-query-4.png) ![Bigquery screenshot 5](/images/databases/big-query-5.png) ![Bigquery screenshot 6](/images/databases/big-query-6.png) If the button **CREATE SERVICE ACCOUNT** is gray, you don't have the correct permissions. Ask the admin of your Google Cloud project for help. After clicking **DONE**, you should be back on the service accounts overview. Create a JSON key file for the new account and download it: ![Bigquery screenshot 7](/images/databases/big-query-7.png) ![Bigquery screenshot 8](/images/databases/big-query-8.png) ![Bigquery screenshot 9](/images/databases/big-query-9.png) Your local Streamlit app will read secrets from a file `.streamlit/secrets.toml` in your app's root directory. Create this file if it doesn't exist yet and add the content of the key file you just downloaded to it as shown below: ```toml # .streamlit/secrets.toml [gcp_service_account] type = "service_account" project_id = "xxx" private_key_id = "xxx" private_key = "xxx" client_email = "xxx" client_id = "xxx" auth_uri = "https://accounts.google.com/o/oauth2/auth" token_uri = "https://oauth2.googleapis.com/token" auth_provider_x509_cert_url = "https://www.googleapis.com/oauth2/v1/certs" client_x509_cert_url = "xxx" ``` Add this file to `.gitignore` and don't commit it to your GitHub repo! ## Copy Your App Secrets to the Cloud As the `secrets.toml` file above is not committed to GitHub, you need to pass its content to your deployed app (on Streamlit Community Cloud) separately. Go to the [app dashboard](https://share.streamlit.io/) and in the app's dropdown menu, click on **Edit Secrets**. Copy the content of `secrets.toml` into the text area. More information is available at [Secrets management](/deploy/streamlit-community-cloud/deploy-your-app/secrets-management). ![Secrets manager screenshot](/images/databases/edit-secrets.png) ## Add Google Cloud BigQuery to Your Requirements File Add the [google-cloud-bigquery](https://googleapis.dev/python/bigquery/latest/index.html) package to your `requirements.txt` file, preferably pinning its version (replace `x.x.x` with the version you want installed): ```bash # requirements.txt google-cloud-bigquery==x.x.x ``` ## Write Your Streamlit App Copy the code below to your Streamlit app and run it. Make sure to adapt the query if you don't use the sample table: ```python # streamlit_app.py import streamlit as st from google.oauth2 import service_account from google.cloud import bigquery # Create API client. credentials = service_account.Credentials.from_service_account_info( st.secrets["gcp_service_account"] ) client = bigquery.Client(credentials=credentials) # Perform query. # Uses st.cache_data to only rerun when the query changes or after 10 min. @st.cache_data(ttl=600) def run_query(query): query_job = client.query(query) rows_raw = query_job.result() # Convert to list of dicts. Required for st.cache_data to hash the return value. rows = [dict(row) for row in rows_raw] return rows rows = run_query("SELECT word FROM `bigquery-public-data.samples.shakespeare` LIMIT 10") # Print results. st.write("Some wise words from Shakespeare:") for row in rows: st.write("✍️ " + row['word']) ``` See `st.cache_data` above? Without it, Streamlit would run the query every time the app reruns (e.g., on a widget interaction). With `st.cache_data`, it only runs when the query changes or after 10 minutes (that's what `ttl` is for). Watch out: If your database updates more frequently, you should adapt `ttl` or remove caching so viewers always see the latest data. Learn more in [Caching](/develop/concepts/architecture/caching). Alternatively, you can use pandas to read from BigQuery right into a dataframe! Follow all the above steps, install the [pandas-gbq](https://pandas-gbq.readthedocs.io/en/latest/index.html) library (don't forget to add it to `requirements.txt`!), and call `pandas.read_gbq(query, credentials=credentials)`. More info [in the pandas docs](https://pandas.pydata.org/docs/reference/api/pandas.read_gbq.html). If everything worked out (and you used the sample table), your app should look like this: ![Final app screenshot](/images/databases/big-query-10.png) --- # Source: https://docs.streamlit.io/develop/tutorials/chat-and-llm-apps/build-conversational-apps # Build a basic LLM chat app ## Introduction The advent of large language models like GPT has revolutionized the ease of developing chat-based applications. Streamlit offers several [Chat elements](/develop/api-reference/chat), enabling you to build Graphical User Interfaces (GUIs) for conversational agents or chatbots. Leveraging [session state](/develop/concepts/architecture/session-state) along with these elements allows you to construct anything from a basic chatbot to a more advanced, ChatGPT-like experience using purely Python code. In this tutorial, we'll start by walking through Streamlit's chat elements, `st.chat_message` and `st.chat_input`. Then we'll proceed to construct three distinct applications, each showcasing an increasing level of complexity and functionality: 1. First, we'll [Build a bot that mirrors your input](#build-a-bot-that-mirrors-your-input) to get a feel for the chat elements and how they work. We'll also introduce [session state](/develop/concepts/architecture/session-state) and how it can be used to store the chat history. This section will serve as a foundation for the rest of the tutorial. 2. Next, you'll learn how to [Build a simple chatbot GUI with streaming](#build-a-simple-chatbot-gui-with-streaming). 3. Finally, we'll [Build a ChatGPT-like app](#build-a-chatgpt-like-app) that leverages session state to remember conversational context, all within less than 50 lines of code. ## Install dependencies First, let's install the dependencies we'll need for this section: ```bash pip install openai streamlit ``` ## Add OpenAI API key to Streamlit secrets Next, let's add our OpenAI API key to [Streamlit secrets](/develop/concepts/connections/secrets-management). We do this by creating `.streamlit/secrets.toml` file in our project directory and adding the following lines to it: ```toml # .streamlit/secrets.toml OPENAI_API_KEY = "YOUR_API_KEY" ``` ## Write the app Now let's write the app. We'll use the same code as before, but we'll replace the default model to `gpt-3.5-turbo` and set our OpenAI API key from Streamlit secrets. Here's where it gets interesting. We can replace our emulated stream with the model's responses from OpenAI: ```python import streamlit as st from openai import OpenAI st.title("ChatGPT-like clone") client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"]) if "openai_model" not in st.session_state: st.session_state["openai_model"] = "gpt-3.5-turbo" if "messages" not in st.session_state: st.session_state.messages = [] for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("What is up?"): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) with st.chat_message("assistant"): stream = client.chat.completions.create( model=st.session_state["openai_model"], messages=[ {"role": m["role"], "content": m["content"]} for m in st.session_state.messages ], stream=True, ) response = st.write_stream(stream) st.session_state.messages.append({"role": "assistant", "content": response}) ``` ## Status and limitations ## Quick reference ## Deployment issues ## Knowledge base ## Build a basic LLM chat app Learn to build conversational LLM applications with Streamlit using chat elements, session state, and Python to create ChatGPT-like experiences. ## Build a basic LLM chat app ### Introduction The advent of large language models like GPT has revolutionized the ease of developing chat-based applications. Streamlit offers several [Chat elements](/develop/api-reference/chat), enabling you to build Graphical User Interfaces (GUIs) for conversational agents or chatbots. Leveraging [session state](/develop/concepts/architecture/session-state) along with these elements allows you to construct anything from a basic chatbot to a more advanced, ChatGPT-like experience using purely Python code. In this tutorial, we'll start by walking through Streamlit's chat elements, `st.chat_message` and `st.chat_input`. Then we'll proceed to construct three distinct applications, each showcasing an increasing level of complexity and functionality: 1. First, we'll [Build a bot that mirrors your input](#build-a-bot-that-mirrors-your-input) to get a feel for the chat elements and how they work. We'll also introduce [session state](/develop/concepts/architecture/session-state) and how it can be used to store the chat history. This section will serve as a foundation for the rest of the tutorial. 2. Next, you'll learn how to [Build a simple chatbot GUI with streaming](#build-a-simple-chatbot-gui-with-streaming). 3. Finally, we'll [Build a ChatGPT-like app](#build-a-chatgpt-like-app) that leverages session state to remember conversational context, all within less than 50 lines of code. ## Install dependencies First, let's install the dependencies we'll need for this section: ```bash pip install openai streamlit ``` ## Add OpenAI API key to Streamlit secrets Next, let's add our OpenAI API key to [Streamlit secrets](/develop/concepts/connections/secrets-management). We do this by creating `.streamlit/secrets.toml` file in our project directory and adding the following lines to it: ```toml # .streamlit/secrets.toml OPENAI_API_KEY = "YOUR_API_KEY" ``` ## Write the app Now let's write the app. We'll use the same code as before, but we'll replace the default model to `gpt-3.5-turbo` and set our OpenAI API key from Streamlit secrets. Here's where it gets interesting. We can replace our emulated stream with the model's responses from OpenAI: ```python import streamlit as st from openai import OpenAI st.title("ChatGPT-like clone") client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"]) if "openai_model" not in st.session_state: st.session_state["openai_model"] = "gpt-3.5-turbo" if "messages" not in st.session_state: st.session_state.messages = [] for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("What is up?"): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) with st.chat_message("assistant"): stream = client.chat.completions.create( model=st.session_state["openai_model"], messages=[ {"role": m["role"], "content": m["content"]} for m in st.session_state.messages ], stream=True, ) response = st.write_stream(stream) st.session_state.messages.append({"role": "assistant", "content": response}) ``` ## Status and limitations ## Quick reference ## Deployment issues ## Knowledge base ## Build a basic LLM chat app Learn to build conversational LLM applications with Streamlit using chat elements, session state, and Python to create ChatGPT-like experiences. ## Build a basic LLM chat app ### Introduction The advent of large language models like GPT has revolutionized the ease of developing chat-based applications. Streamlit offers several [Chat elements](/develop/api-reference/chat), enabling you to build Graphical User Interfaces (GUIs) for conversational agents or chatbots. Leveraging [session state](/develop/concepts/architecture/session-state) along with these elements allows you to construct anything from a basic chatbot to a more advanced, ChatGPT-like experience using purely Python code. In this tutorial, we'll start by walking through Streamlit's chat elements, `st.chat_message` and `st.chat_input`. Then we'll proceed to construct three distinct applications, each showcasing an increasing level of complexity and functionality: 1. First, we'll [Build a bot that mirrors your input](#build-a-bot-that-mirrors-your-input) to get a feel for the chat elements and how they work. We'll also introduce [session state](/develop/concepts/architecture/session-state) and how it can be used to store the chat history. This section will serve as a foundation for the rest of the tutorial. 2. Next, you'll learn how to [Build a simple chatbot GUI with streaming](#build-a-simple-chatbot-gui-with-streaming). 3. Finally, we'll [Build a ChatGPT-like app](#build-a-chatgpt-like-app) that leverages session state to remember conversational context, all within less than 50 lines of code. ## Install dependencies First, let's install the dependencies we'll need for this section: ```bash pip install openai streamlit ``` ## Add OpenAI API key to Streamlit secrets Next, let's add our OpenAI API key to [Streamlit secrets](/develop/concepts/connections/secrets-management). We do this by creating `.streamlit/secrets.toml` file in our project directory and adding the following lines to it: ```toml # .streamlit/secrets.toml OPENAI_API_KEY = "YOUR_API_KEY" ``` ## Write the app Now let's write the app. We'll use the same code as before, but we'll replace the default model to `gpt-3.5-turbo` and set our OpenAI API key from Streamlit secrets. Here's where it gets interesting. We can replace our emulated stream with the model's responses from OpenAI: ```python import streamlit as st from openai import OpenAI st.title("ChatGPT-like clone") client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"]) if "openai_model" not in st.session_state: st.session_state["openai_model"] = "gpt-3.5-turbo" if "messages" not in st.session_state: st.session_state.messages = [] for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("What is up?"): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) with st.chat_message("assistant"): stream = client.chat.completions.create( model=st.session_state["openai_model"], messages=[ {"role": m["role"], "content": m["content"]} for m in st.session_state.messages ], stream=True, ) response = st.write_stream(stream) st.session_state.messages.append({"role": "assistant", "content": response}) ``` ## Status and limitations ## Quick reference ## Deployment issues ## Knowledge base ## Build a basic LLM chat app Learn to build conversational LLM applications with Streamlit using chat elements, session state, and Python to create ChatGPT-like experiences. ## Build a basic LLM chat app ### Introduction The advent of large language models like GPT has revolutionized the ease of developing chat-based applications. Streamlit offers several [Chat elements](/develop/api-reference/chat), enabling you to build Graphical User Interfaces (GUIs) for conversational agents or chatbots. Leveraging [session state](/develop/concepts/architecture/session-state) along with these elements allows you to construct anything from a basic chatbot to a more advanced, ChatGPT-like experience using purely Python code. In this tutorial, we'll start by walking through Streamlit's chat elements, `st.chat_message` and `st.chat_input`. Then we'll proceed to construct three distinct applications, each showcasing an increasing level of complexity and functionality: 1. First, we'll [Build a bot that mirrors your input](#build-a-bot-that-mirrors-your-input) to get a feel for the chat elements and how they work. We'll also introduce [session state](/develop/concepts/architecture/session-state) and how it can be used to store the chat history. This section will serve as a foundation for the rest of the tutorial. 2. Next, you'll learn how to [Build a simple chatbot GUI with streaming](#build-a-simple-chatbot-gui-with-streaming). 3. Finally, we'll [Build a ChatGPT-like app](#build-a-chatgpt-like-app) that leverages session state to remember conversational context, all within less than 50 lines of code. ## Install dependencies First, let's install the dependencies we'll need for this section: ```bash pip install openai streamlit ``` ## Add OpenAI API key to Streamlit secrets Next, let's add our OpenAI API key to [Streamlit secrets](/develop/concepts/connections/secrets-management). We do this by creating `.streamlit/secrets.toml` file in our project directory and adding the following lines to it: ```toml # .streamlit/secrets.toml OPENAI_API_KEY = "YOUR_API_KEY" ``` ## Write the app Now let's write the app. We'll use the same code as before, but we'll replace the default model to `gpt-3.5-turbo` and set our OpenAI API key from Streamlit secrets. Here's where it gets interesting. We can replace our emulated stream with the model's responses from OpenAI: ```python import streamlit as st from openai import OpenAI st.title("ChatGPT-like clone") client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"]) if "openai_model" not in st.session_state: st.session_state["openai_model"] = "gpt-3.5-turbo" if "messages" not in st.session_state: st.session_state.messages = [] for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("What is up?"): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) with st.chat_message("assistant"): stream = client.chat.completions.create( model=st.session_state["openai_model"], messages=[ {"role": m["role"], "content": m["content"]} for m in st.session_state.messages ], stream=True, ) response = st.write_stream(stream) st.session_state.messages.append({"role": "assistant", "content": response}) ``` ## Status and limitations ## Quick reference ## Deployment issues ## Knowledge base ## Build a basic LLM chat app Learn to build conversational LLM applications with Streamlit using chat elements, session state, and Python to create ChatGPT-like experiences. ## Build a basic LLM chat app ### Introduction The advent of large language models like GPT has revolutionized the ease of developing chat-based applications. Streamlit offers several [Chat elements](/develop/api-reference/chat), enabling you to build Graphical User Interfaces (GUIs) for conversational agents or chatbots. Leveraging [session state](/develop/concepts/architecture/session-state) along with these elements allows you to construct anything from a basic chatbot to a more advanced, ChatGPT-like experience using purely Python code. In this tutorial, we'll start by walking through Streamlit's chat elements, `st.chat_message` and `st.chat_input`. Then we'll proceed to construct three distinct applications, each showcasing an increasing level of complexity and functionality: 1. First, we'll [Build a bot that mirrors your input](#build-a-bot-that-mirrors-your-input) to get a feel for the chat elements and how they work. We'll also introduce [session state](/develop/concepts/architecture/session-state) and how it can be used to store the chat history. This section will serve as a foundation for the rest of the tutorial. 2. Next, you'll learn how to [Build a simple chatbot GUI with streaming](#build-a-simple-chatbot-gui-with-streaming). 3. Finally, we'll [Build a ChatGPT-like app](#build-a-chatgpt-like-app) that leverages session state to remember conversational context, all within less than 50 lines of code. ## Install dependencies First, let's install the dependencies we'll need for this section: ```bash pip install openai streamlit ``` ## Add OpenAI API key to Streamlit secrets Next, let's add our OpenAI API key to [Streamlit secrets](/develop/concepts/connections/secrets-management). We do this by creating `.streamlit/secrets.toml` file in our project directory and adding the following lines to it: ```toml # .streamlit/secrets.toml OPENAI_API_KEY = "YOUR_API_KEY" ``` ## Write the app Now let's write the app. We'll use the same code as before, but we'll replace the default model to `gpt-3.5-turbo` and set our OpenAI API key from Streamlit secrets. Here's where it gets interesting. We can replace our emulated stream with the model's responses from OpenAI: ```python import streamlit as st from openai import OpenAI st.title("ChatGPT-like clone") client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"]) if "openai_model" not in st.session_state: st.session_state["openai_model"] = "gpt-3.5-turbo" if "messages" not in st.session_state: st.session_state.messages = [] for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("What is up?"): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) with st.chat_message("assistant"): stream = client.chat.completions.create( model=st.session_state["openai_model"], messages=[ {"role": m["role"], "content": m["content"]} for m in st.session_state.messages ], stream=True, ) response = st.write_stream(stream) st.session_state.messages.append({"role": "assistant", "content": response}) ``` ## Status and limitations ## Quick reference ## Deployment issues ## Knowledge base ## Build a basic LLM chat app Learn to build conversational LLM applications with Streamlit using chat elements, session state, and Python to create ChatGPT-like experiences. ## Build a basic LLM chat app ### Introduction The advent of large language models like GPT has revolutionized the ease of developing chat-based applications. Streamlit offers several [Chat elements](/develop/api-reference/chat), enabling you to build Graphical User Interfaces (GUIs) for conversational agents or chatbots. Leveraging [session state](/develop/concepts/architecture/session-state) along with these elements allows you to construct anything from a basic chatbot to a more advanced, ChatGPT-like experience using purely Python code. In this tutorial, we'll start by walking through Streamlit's chat elements, `st.chat_message` and `st.chat_input`. Then we'll proceed to construct three distinct applications, each showcasing an increasing level of complexity and functionality: 1. First, we'll [Build a bot that mirrors your input](#build-a-bot-that-mirrors-your-input) to get a feel for the chat elements and how they work. We'll also introduce [session state](/develop/concepts/architecture/session-state) and how it can be used to store the chat history. This section will serve as a foundation for the rest of the tutorial. 2. Next, you'll learn how to [Build a simple chatbot GUI with streaming](#build-a-simple-chatbot-gui-with-streaming). 3. Finally, we'll [Build a ChatGPT-like app](#build-a-chatgpt-like-app) that leverages session state to remember conversational context, all within less than 50 lines of code. ## Install dependencies First, let's install the dependencies we'll need for this section: ```bash pip install openai streamlit ``` ## Add OpenAI API key to Streamlit secrets Next, let's add our OpenAI API key to [Streamlit secrets](/develop/concepts/connections/secrets-management). We do this by creating `.streamlit/secrets.toml` file in our project directory and adding the following lines to it: ```toml # .streamlit/secrets.toml OPENAI_API_KEY = "YOUR_API_KEY" ``` ## Write the app Now let's write the app. We'll use the same code as before, but we'll replace the default model to `gpt-3.5-turbo` and set our OpenAI API key from Streamlit secrets. Here's where it gets interesting. We can replace our emulated stream with the model's responses from OpenAI: ```python import streamlit as st from openai import OpenAI st.title("ChatGPT-like clone") client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"]) if "openai_model" not in st.session_state: st.session_state["openai_model"] = "gpt-3.5-turbo" if "messages" not in st.session_state: st.session_state.messages = [] for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("What is up?"): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) with st.chat_message("assistant"): stream = client.chat.completions.create( model=st.session_state["openai_model"], messages=[ {"role": m["role"], "content": m["content"]} for m in st.session_state.messages ], stream=True, ) response = st.write_stream(stream) st.session_state.messages.append({"role": "assistant", "content": response}) ``` ## Status and limitations ## Quick reference ## Deployment issues ## Knowledge base ## Build a basic LLM chat app Learn to build conversational LLM applications with Streamlit using chat elements, session state, and Python to create ChatGPT-like experiences. ## Build a basic LLM chat app ### Introduction The advent of large language models like GPT has revolutionized the ease of developing chat-based applications. Streamlit offers several [Chat elements](/develop/api-reference/chat), enabling you to build Graphical User Interfaces (GUIs) for conversational agents or chatbots. Leveraging [session state](/develop/concepts/architecture/session-state) along with these elements allows you to construct anything from a basic chatbot to a more advanced, ChatGPT-like experience using purely Python code. In this tutorial, we'll start by walking through Streamlit's chat elements, `st.chat_message` and `st.chat_input`. Then we'll proceed to construct three distinct applications, each showcasing an increasing level of complexity and functionality: 1. First, we'll [Build a bot that mirrors your input](#build-a-bot-that-mirrors-your-input) to get a feel for the chat elements and how they work. We'll also introduce [session state](/develop/concepts/architecture/session-state) and how it can be used to store the chat history. This section will serve as a foundation for the rest of the tutorial. 2. Next, you'll learn how to [Build a simple chatbot GUI with streaming](#build-a-simple-chatbot-gui-with-streaming). 3. Finally, we'll [Build a ChatGPT-like app](#build-a-chatgpt-like-app) that leverages session state to remember conversational context, all within less than 50 lines of code. ## Install dependencies First, let's install the dependencies we'll need for this section: ```bash pip install openai streamlit ``` ## Add OpenAI API key to Streamlit secrets Next, let's add our OpenAI API key to [Streamlit secrets](/develop/concepts/connections/secrets-management). We do this by creating `.streamlit/secrets.toml` file in our project directory and adding the following lines to it: ```toml # .streamlit/secrets.toml OPENAI_API_KEY = "YOUR_API_KEY" ``` ## Write the app Now let's write the app. We'll use the same code as before, but we'll replace the default model to `gpt-3.5-turbo` and set our OpenAI API key from Streamlit secrets. Here's where it gets interesting. We can replace our emulated stream with the model's responses from OpenAI: ```python import streamlit as st from openai import OpenAI st.title("ChatGPT-like clone") client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"]) if "openai_model" not in st.session_state: st.session_state["openai_model"] = "gpt-3.5-turbo" if "messages" not in st.session_state: st.session_state.messages = [] for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("What is up?"): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) with st.chat_message("assistant"): stream = client.chat.completions.create( model=st.session_state["openai_model"], messages=[ {"role": m["role"], "content": m["content"]} for m in st.session_state.messages ], stream=True, ) response = st.write_stream(stream) st.session_state.messages.append({"role": "assistant", "content": response}) ``` ## Status and limitations ## Quick reference ## Deployment issues ## Knowledge base ## Build a basic LLM chat app Learn to build conversational LLM applications with Streamlit using chat elements, session state, and Python to create ChatGPT-like experiences. ## Build a basic LLM chat app ### Introduction The advent of large language models like GPT has revolutionized the ease of developing chat-based applications. Streamlit offers several [Chat elements](/develop/api-reference/chat), enabling you to build Graphical User Interfaces (GUIs) for conversational agents or chatbots. Leveraging [session state](/develop/concepts/architecture/session-state) along with these elements allows you to construct anything from a basic chatbot to a more advanced, ChatGPT-like experience using purely Python code. In this tutorial, we'll start by walking through Streamlit's chat elements, `st.chat_message` and `st.chat_input`. Then we'll proceed to construct three distinct applications, each showcasing an increasing level of complexity and functionality: 1. First, we'll [Build a bot that mirrors your input](#build-a-bot-that-mirrors-your-input) to get a feel for the chat elements and how they work. We'll also introduce [session state](/develop/concepts/architecture/session-state) and how it can be used to store the chat history. This section will serve as a foundation for the rest of the tutorial. 2. Next, you'll learn how to [Build a simple chatbot GUI with streaming](#build-a-simple-chatbot-gui-with-streaming). 3. Finally, we'll [Build a ChatGPT-like app](#build-a-chatgpt-like-app) that leverages session state to remember conversational context, all within less than 50 lines of code. ## Install dependencies First, let's install the dependencies we'll need for this section: ```bash pip install openai streamlit ``` ## Add OpenAI API key to Streamlit secrets Next, let's add our OpenAI API key to [Streamlit secrets](/develop/concepts/connections/secrets-management). We do this by creating `.streamlit/secrets.toml` file in our project directory and adding the following lines to it: ```toml # .streamlit/secrets.toml OPENAI_API_KEY = "YOUR_API_KEY" ``` ## Write the app Now let's write the app. We'll use the same code as before, but we'll replace the default model to `gpt-3.5-turbo` and set our OpenAI API key from Streamlit secrets. Here's where it gets interesting. We can replace our emulated stream with the model's responses from OpenAI: ```python import streamlit as st from openai import OpenAI st.title("ChatGPT-like clone") client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"]) if "openai_model" not in st.session_state: st.session_state["openai_model"] = "gpt-3.5-turbo" if "messages" not in st.session_state: st.session_state.messages = [] for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("What is up?"): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) with st.chat_message("assistant"): stream = client.chat.completions.create( model=st.session_state["openai_model"], messages=[ {"role": m["role"], "content": m["content"]} for m in st.session_state.messages ], stream=True, ) response = st.write_stream(stream) st.session_state.messages.append({"role": "assistant", "content": response}) ``` ## Status and limitations ## Quick reference ## Deployment issues ## Knowledge base ## Build a basic LLM chat app Learn to build conversational LLM applications with Streamlit using chat elements, session state, and Python to create ChatGPT-like experiences. ## Build a basic LLM chat app ### Introduction The advent of large language models like GPT has revolutionized the ease of developing chat-based applications. Streamlit offers several [Chat elements](/develop/api-reference/chat), enabling you to build Graphical User Interfaces (GUIs) for conversational agents or chatbots. Leveraging [session state](/develop/concepts/architecture/session-state) along with these elements allows you to construct anything from a basic chatbot to a more advanced, ChatGPT-like experience using purely Python code. In this tutorial, we'll start by walking through Streamlit's chat elements, `st.chat_message` and `st.chat_input`. Then we'll proceed to construct three distinct applications, each showcasing an increasing level of complexity and functionality: 1. First, we'll [Build a bot that mirrors your input](#build-a-bot-that-mirrors-your-input) to get a feel for the chat elements and how they work. We'll also introduce [session state](/develop/concepts/architecture/session-state) and how it can be used to store the chat history. This section will serve as a foundation for the rest of the tutorial. 2. Next, you'll learn how to [Build a simple chatbot GUI with streaming](#build-a-simple-chatbot-gui-with-streaming). 3. Finally, we'll [Build a ChatGPT-like app](#build-a-chatgpt-like-app) that leverages session state to remember conversational context, all within less than 50 lines of code. ## Install dependencies First, let's install the dependencies we'll need for this section: ```bash pip install openai streamlit ``` ## Add OpenAI API key to Streamlit secrets Next, let's add our OpenAI API key to [Streamlit secrets](/develop/concepts/connections/secrets-management). We do this by creating `.streamlit/secrets.toml` file in our project directory and adding the following lines to it: ```toml # .streamlit/secrets.toml OPENAI_API_KEY = "YOUR_API_KEY" ``` ## Write the app Now let's write the app. We'll use the same code as before, but we'll replace the default model to `gpt-3.5-turbo` and set our OpenAI API key from Streamlit secrets. Here's where it gets interesting. We can replace our emulated stream with the model's responses from OpenAI: ```python import streamlit as st from openai import OpenAI st.title("ChatGPT-like clone") client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"]) if "openai_model" not in st.session_state: st.session_state["openai_model"] = "gpt-3.5-turbo" if "messages" not in st.session_state: st.session_state.messages = [] for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("What is up?"): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) with st.chat_message("assistant"): stream = client.chat.completions.create( model=st.session_state["openai_model"], messages=[ {"role": m["role"], "content": m["content"]} for m in st.session_state.messages ], stream=True, ) response = st.write_stream(stream) st.session_state.messages.append({"role": "assistant", "content": response}) ``` ## Status and limitations ## Quick reference ## Deployment issues ## Knowledge base ## Build a basic LLM chat app Learn to build conversational LLM applications with Streamlit using chat elements, session state, and Python to create ChatGPT-like experiences. ## Build a basic LLM chat app ### Introduction The advent of large language models like GPT has revolutionized the ease of developing chat-based applications. Streamlit offers several [Chat elements](/develop/api-reference/chat), enabling you to build Graphical User Interfaces (GUIs) for conversational agents or chatbots. Leveraging [session state](/develop/concepts/architecture/session-state) along with these elements allows you to construct anything from a basic chatbot to a more advanced, ChatGPT-like experience using purely Python code. In this tutorial, we'll start by walking through Streamlit's chat elements, `st.chat_message` and `st.chat_input`. Then we'll proceed to construct three distinct applications, each showcasing an increasing level of complexity and functionality: 1. First, we'll [Build a bot that mirrors your input](#build-a-bot-that-mirrors-your-input) to get a feel for the chat elements and how they work. We'll also introduce [session state](/develop/concepts/architecture/session-state) and how it can be used to store the chat history. This section will serve as a foundation for the rest of the tutorial. 2. Next, you'll learn how to [Build a simple chatbot GUI with streaming](#build-a-simple-chatbot-gui-with-streaming). 3. Finally, we'll [Build a ChatGPT-like app](#build-a-chatgpt-like-app) that leverages session state to remember conversational context, all within less than 50 lines of code. ## Install dependencies First, let's install the dependencies we'll need for this section: ```bash pip install openai streamlit ``` ## Add OpenAI API key to Streamlit secrets Next, let's add our OpenAI API key to [Streamlit secrets](/develop/concepts/connections/secrets-management). We do this by creating `.streamlit/secrets.toml` file in our project directory and adding the following lines to it: ```toml # .streamlit/secrets.toml OPENAI_API_KEY = "YOUR_API_KEY" ``` ## Write the app Now let's write the app. We'll use the same code as before, but we'll replace the default model to `gpt-3.5-turbo` and set our OpenAI API key from Streamlit secrets. Here's where it gets interesting. We can replace our emulated stream with the model's responses from OpenAI: ```python import streamlit as st from openai import OpenAI st.title("ChatGPT-like clone") client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"]) if "openai_model" not in st.session_state: st.session_state["openai_model"] = "gpt-3.5-turbo" if "messages" not in st.session_state: st.session_state.messages = [] for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("What is up?"): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) with st.chat_message("assistant"): stream = client.chat.completions.create( model=st.session_state["openai_model"], messages=[ {"role": m["role"], "content": m["content"]} for m in st.session_state.messages ], stream=True, ) response = st.write_stream(stream) st.session_state.messages.append({"role": "assistant", "content": response}) ``` ## Status and limitations ## Quick reference ## Deployment issues ## Knowledge base ## Build a basic LLM chat app Learn to build conversational LLM applications with Streamlit using chat elements, session state, and Python to create ChatGPT-like experiences. ## Build a basic LLM chat app ### Introduction The advent of large language models like GPT has revolutionized the ease of developing chat-based applications. Streamlit offers several [Chat elements](/develop/api-reference/chat), enabling you to --- # Source: https://docs.streamlit.io/develop/concepts/design/buttons # Button behavior and examples ## Summary Buttons created with `st.button` do not retain state. They return `True` on the script rerun resulting from their click and immediately return to `False` on the next script rerun. If a displayed element is nested inside `if st.button('Click me'):`, the element will be visible when the button is clicked and disappear as soon as the user takes their next action. This is because the script reruns and the button return value becomes `False`. In this guide, we will illustrate the use of buttons and explain common misconceptions. Read on to see a variety of examples that expand on `st.button` using `st.session_state` for interactive applications. ## When to use `if st.button()` When code is conditioned on a button's value, it will execute once in response to the button being clicked and not again (until the button is clicked again). ### Good to nest inside buttons - Transient messages that immediately disappear. - Once-per-click processes that saves data to session state, a file, or a database. ### Bad to nest inside buttons - Displayed items that should persist as the user continues. - Other widgets which cause the script to rerun when used. - Processes that neither modify session state nor write to a file/database. * This can be appropriate when disposable results are desired. If you have a `Validate` button, that could be a process conditioned directly on a button. It could be used to create an alert to say 'Valid' or 'Invalid' with no need to keep that info. ## Common logic with buttons ### Show a temporary message with a button If you want to give the user a quick button to check if an entry is valid, but not keep that check displayed as the user continues. In this example, a user can click a button to check if their `animal` string is in the `animal_shelter` list. When the user clicks "Check availability" they will see "We have that animal!" or "We don't have that animal." If they change the animal in `st.text_input`, the script reruns and the message disappears until they click "Check availability" again. ```python import streamlit as st animal_shelter = ['cat', 'dog', 'rabbit', 'bird'] animal = st.text_input('Type an animal') if st.button('Check availability'): have_it = animal.lower() in animal_shelter 'We have that animal!' if have_it else 'We don't have that animal.' ``` Note: The above example uses `magic` to render the message on the frontend. ### Stateful button If you want a clicked button to continue to be `True`, create a value in `st.session_state` and use the button to set that value to `True` in a callback. ```python import streamlit as st if 'clicked' not in st.session_state: st.session_state.clicked = False def click_button(): st.session_state.clicked = True st.button('Click me', on_click=click_button) if st.session_state.clicked: # The message and nested widget will remain on the page st.write('Button clicked!') st.slider('Select a value') ``` ### Toggle button If you want a button to work like a toggle switch, consider using `st.checkbox`. Otherwise, you can use a button with a callback function to reverse a boolean value saved in `st.session_state`. In this example, we use `st.button` to toggle another widget on and off. By displaying `st.slider` conditionally on a value in `st.session_state`, the user can interact with the slider without it disappearing. ```python import streamlit as st if 'button' not in st.session_state: st.session_state.button = False def click_button(): st.session_state.button = not st.session_state.button st.button('Click me', on_click=click_button) if st.session_state.button: # The message and nested widget will remain on the page st.write('Button is on!') st.slider('Select a value') else: st.write('Button is off!') ``` ### Buttons to continue or control stages of a process Another alternative to nesting content inside a button is to use a value in `st.session_state` that designates the "step" or "stage" of a process. In this example, we have four stages in our script: 1. Before the user begins. 2. User enters their name. 3. User chooses a color. 4. User gets a thank-you message. A button at the beginning advances the stage from 0 to 1. A button at the end resets the stage from 3 to 0. The other widgets used in stage 1 and 2 have callbacks to set the stage. If you have a process with dependent steps and want to keep previous stages visible, such a callback forces a user to retrace subsequent stages if they change an earlier widget. ```python import streamlit as st if 'stage' not in st.session_state: st.session_state.stage = 0 def set_state(i): st.session_state.stage = i if st.session_state.stage == 0: st.button('Begin', on_click=set_state, args=[1]) if st.session_state.stage > 1: name = st.text_input('Name', on_change=set_state, args=[2]) if st.session_state.stage > 2: st.write(f'Hello {name}!') color = st.selectbox( 'Pick a Color', [None, 'red', 'orange', 'green', 'blue', 'violet'], on_change=set_state, args=[3]) if color is None: set_state(2) if st.session_state.stage > 3: st.write(f':{color}[Thank you!]') st.button('Start Over', on_click=set_state, args=[0]) ``` ### Buttons to modify `st.session_state` If you modify `st.session_state` inside of a button, you must consider where that button is within the script. #### Option 1: Use a key for the button and put the logic before the widget If you assign a key to a button, you can condition code on a button's state by using its value in `st.session_state`. This means that logic depending on your button can be in your script before that button. In the following example, we use the `get()` method on `st.session_state` because the keys for the buttons will not exist when the script runs for the first time. The `get()` method will return `False` if it can't find the key. Otherwise, it will return the value of the key. ```python import streamlit as st if st.session_state.get('clear'): st.session_state['name'] = '' if st.session_state.get('streamlit'): st.session_state['name'] = 'Streamlit' st.text_input('Name', key='name') st.button('Clear name', key='clear') st.button('Streamlit!', key='streamlit') ``` #### Option 2: Use a callback ```python import streamlit as st st.text_input('Name', key='name') def set_name(name): st.session_state.name = name st.button('Clear name', on_click=set_name) st.button('Streamlit!', on_click=set_name) ``` #### Option 3: Use containers By using `st.container` you can have widgets appear in different orders in your script and frontend view (webpage). ```python import streamlit as st begin = st.container() if st.button('Clear name'): st.session_state.name = '' if st.button('Streamlit!'): st.session_state.name = ('Streamlit') # The widget is second in logic, but first in display begin.text_input('Name', key='name') ``` ## Buttons to add other widgets dynamically When dynamically adding widgets to the page, make sure to use an index to keep the keys unique and avoid a `DuplicateWidgetID` error. In this example, we define a function `display_input_row` which renders a row of widgets. That function accepts an `index` as a parameter. The widgets rendered by `display_input_row` use `index` within their keys so that `display_input_row` can be executed multiple times on a single script rerun without repeating any widget keys. ```python import streamlit as st def display_input_row(index): left, middle, right = st.columns(3) left.text_input('First', key=f'first_{index}') middle.text_input('Middle', key=f'middle_{index}') right.text_input('Last', key=f'last_{index}') if 'rows' not in st.session_state: st.session_state['rows'] = 0 def increase_rows(): st.session_state['rows'] += 1 st.button('Add person', on_click=increase_rows) for i in range(st.session_state['rows']): display_input_row(i) st.subheader('People') for i in range(st.session_state['rows']): st.write( f'Person {i+1}:', st.session_state[f'first_{i}'], st.session_state[f'middle_{i}'], st.session_state[f'last_{i}'] ) ``` ## Buttons to handle expensive or file-writing processes When you have expensive processes, set them to run upon clicking a button and save the results into `st.session_state`. This allows you to keep accessing the results of the process without re-executing it unnecessarily. This is especially helpful for processes that save to disk or write to a database. In this example, we have an `expensive_process` that depends on two parameters: `option` and `add`. Functionally, `add` changes the output, but `option` does not—`option` is there to provide a parameter. ```python import streamlit as st import pandas as pd import time def expensive_process(option, add): with st.spinner('Processing...'): time.sleep(5) df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C':[7, 8, 9]}) + add return (df, add) cols = st.columns(2) option = cols[0].selectbox('Select a number', options=['1', '2', '3']) add = cols[1].number_input('Add a number', min_value=0, max_value=10) if 'processed' not in st.session_state: st.session_state.processed = {} # Process and save results if st.button('Process'): result = expensive_process(option, add) st.session_state.processed[option] = result st.write(f'Option {option} processed with add {add}') result[0] ``` Astute observers may think, "This feels a little like caching." We are only saving results relative to one parameter, but the pattern could easily be expanded to save results relative to both parameters. In that sense, yes, it has some similarities to caching, but also some important differences. When you save results in `st.session_state`, the results are only available to the current user in their current session. If you use `st.cache_data` instead, the results are available to all users across all sessions. Furthermore, if you want to update a saved result, you have to clear all saved results for that function to do so. ## Anti-patterns Here are some simplified examples of how buttons can go wrong. Be on the lookout for these common mistakes. ### Buttons nested inside buttons ```python import streamlit as st if st.button('Button 1'): st.write('Button 1 was clicked') if st.button('Button 2'): # This will never be executed. st.write('Button 2 was clicked') ``` ### Other widgets nested inside buttons ```python import streamlit as st if st.button('Sign up'): name = st.text_input('Name') if name: # This will never be executed. st.success(f'Welcome {name}') ``` ### Nesting a process inside a button without saving to session state ```python import streamlit as st import pandas as pd file = st.file_uploader('Upload a file', type='csv') if st.button('Get data'): df = pd.read_csv(file) # This display will go away with the user's next action. st.write(df) if st.button('Save'): # This will always error. df.to_csv('data.csv') --- # Source: https://docs.streamlit.io/develop/api-reference/cli/cache # streamlit cache clear Clear persisted files from the on-disk [Streamlit cache](/develop/api-reference/caching-and-state), if present. ## Syntax ```bash streamlit cache clear ``` [arrow_back Previous: Command line](/develop/api-reference/cli) [arrow_forward Next: streamlit config](/develop/api-reference/cli/config) ## Forum ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. --- © 2025 Snowflake Inc. --- # Source: https://docs.streamlit.io/develop/api-reference/caching-and-state # Caching and state Optimize performance and add statefulness to your app! ## Caching Streamlit provides powerful [cache primitives](/develop/concepts/architecture/caching) for data and global resources. They allow your app to stay performant even when loading data from the web, manipulating large datasets, or performing expensive computations. ### Cache data Function decorator to cache functions that return data (e.g. dataframe transforms, database queries, ML inference). ```python @st.cache_data def long_function(param1, param2): # Perform expensive computation here or # fetch data from the web here return data ``` ### Cache resource Function decorator to cache functions that return global resources (e.g. database connections, ML models). ```python @st.cache_resource def init_model(): # Return a global resource here return pipeline( "sentiment-analysis", model="distilbert-base-uncased-finetuned-sst-2-english" ) ``` ## Browser and server state Streamlit re-executes your script with each user interaction. Widgets have built-in statefulness between reruns, but Session State lets you do more! ### Context `st.context` provides a read-only interface to access cookies, headers, locale, and other browser-session information. ```python st.context.cookies st.context.headers ``` ### Session State Save data between reruns and across pages. ```python st.session_state["foo"] = "bar" ``` ### Query parameters Get, set, or clear the query parameters that are shown in the browser's URL bar. ```python st.query_params[key] = value st.query_params.clear() ``` ## Deprecated commands ### Get query parameters Get query parameters that are shown in the browser's URL bar. ```python param_dict = st.experimental_get_query_params() ``` ### Set query parameters Set query parameters that are shown in the browser's URL bar. ```python st.experimental_set_query_params( {"show_all": True, "selected": ["asia", "america"]} ) --- # Source: https://docs.streamlit.io/develop/concepts/architecture/caching # Caching overview Streamlit runs your script from top to bottom at every user interaction or code change. This execution model makes development super easy. But it comes with two major challenges: 1. Long-running functions run again and again, which slows down your app. 2. Objects get recreated again and again, which makes it hard to persist them across reruns or sessions. But don't worry! Streamlit lets you tackle both issues with its built-in caching mechanism. Caching stores the results of slow function calls, so they only need to run once. This makes your app much faster and helps with persisting objects across reruns. Cached values are available to all users of your app. If you need to save results that should only be accessible within a session, use [Session State](https://docs.streamlit.io/develop/concepts/architecture/session-state) instead. ## Table of contents 1. [Minimal example](#minimal-example) 2. [Basic usage](#basic-usage) 3. [Advanced usage](#advanced-usage) 4. [Migrating from st.cache](#migrating-from-stcache) ## Minimal example To cache a function in Streamlit, you must decorate it with one of two decorators (`st.cache_data` or `st.cache_resource`): ```python @st.cache_data def long_running_function(param1, param2): return ... ``` In this example, decorating `long_running_function` with `@st.cache_data` tells Streamlit that whenever the function is called, it checks two things: 1. The values of the input parameters (in this case, `param1` and `param2`). 2. The code inside the function. If this is the first time Streamlit sees these parameter values and function code, it runs the function and stores the return value in a cache. The next time the function is called with the same parameters and code (e.g., when a user interacts with the app), Streamlit will skip executing the function altogether and return the cached value instead. During development, the cache updates automatically as the function code changes, ensuring that the latest changes are reflected in the cache. As mentioned, there are two caching decorators: - `st.cache_data` is the recommended way to cache computations that return data: loading a DataFrame from CSV, transforming a NumPy array, querying an API, or any other function that returns a serializable data object (str, int, float, DataFrame, array, list, …). It creates a new copy of the data at each function call, making it safe against [mutations and race conditions](#mutation-and-concurrency-issues). The behavior of `st.cache_data` is what you want in most cases – so if you're unsure, start with `st.cache_data` and see if it works! - `st.cache_resource` is the recommended way to cache global resources like ML models or database connections – unserializable objects that you don't want to load multiple times. Using it, you can share these resources across all reruns and sessions of an app without copying or duplication. Note that any mutations to the cached return value directly affects the object in the cache (more details below). When benchmarking `st.cache_data` on pandas DataFrames with four columns, we found that it becomes slow when going beyond 100 million rows. The table shows runtimes for both caching decorators at different numbers of rows (all with four columns): | | 10M rows | 50M rows | 100M rows | 200M rows | | --- | --- | --- | --- | --- | | `st.cache_data` | First run* | 0.4 s | 3 s | 14 s | 28 s | | Subsequent runs | 0.2 s | 1 s | 2 s | 7 s | | `st.cache_resource` | First run* | 0.01 s | 0.1 s | 0.2 s | 1 s | | Subsequent runs | 0 s | 0 s | 0 s | 0 s | *For the first run, the table only shows the overhead time of using the caching decorator. It does not include the runtime of the cached function itself. ## Basic usage ### st.cache_data `st.cache_data` is your go-to command for all functions that return data – whether DataFrames, NumPy arrays, str, int, float, or other serializable types. It's the right command for almost all use cases! Within each user session, an `@st.cache_data`-decorated function returns a `copy` of the cached return value (if the value is already cached). #### Usage Let's look at an example of using `st.cache_data`. Suppose your app loads the [Uber ride-sharing dataset](https://github.com/plotly/datasets/blob/master/uber-rides-data1.csv) – a CSV file of 50 MB – from the internet into a DataFrame: ```python def load_data(url): df = pd.read_csv(url) # 👈 Download the data return df df = load_data("https://github.com/plotly/datasets/raw/master/uber-rides-data1.csv") st.dataframe(df) st.button("Rerun") ``` Running the `load_data` function takes 2 to 30 seconds, depending on your internet connection. (Tip: if you are on a slow connection, use [this 5 MB dataset instead](https://github.com/plotly/datasets/blob/master/26k-consumer-complaints.csv).) Without caching, the download is rerun each time the app is loaded or with user interaction. Try it yourself by clicking the button we added! Not a great experience… 😕 Now let's add the `@st.cache_data` decorator on `load_data`: ```python @st.cache_data # 👈 Add the caching decorator def load_data(url): df = pd.read_csv(url) return df ``` Run the app again. You'll notice that the slow download only happens on the first run. Every subsequent rerun should be almost instant! 💨 #### Behavior How does this work? Let's go through the behavior of `st.cache_data` step by step: 1. On the first run, Streamlit recognizes that it has never called the `load_data` function with the specified parameter value (the URL of the CSV file) So it runs the function and downloads the data. 2. Now our caching mechanism becomes active: the returned DataFrame is serialized (converted to bytes) via [pickle](https://docs.python.org/3/library/pickle.html) and stored in the cache (together with the value of the `url` parameter). 3. On the next run, Streamlit checks the cache for an entry of `load_data` with the specific `url`. There is one! So it retrieves the cached object, deserializes it to a DataFrame, and returns it instead of re-running the function and downloading the data again. This process of serializing and deserializing the cached object creates a copy of our original DataFrame. While this copying behavior may seem unnecessary, it's what we want when caching data objects since it effectively prevents mutation and concurrency issues. Read the section “[Mutation and concurrency issues](#mutation-and-concurrency-issues)” below to understand this in more detail. #### Examples **DataFrame transformations** In the example above, we already showed how to cache loading a DataFrame. It can also be useful to cache DataFrame transformations such as `df.filter`, `df.apply`, or `df.sort_values`. Especially with large DataFrames, these operations can be slow. ```python @st.cache_data def transform(df): df = df.filter(items=['one', 'three']) df = df.apply(np.sum, axis=0) return df ``` **Array computations** Similarly, it can make sense to cache computations on NumPy arrays: ```python @st.cache_data def add(arr1, arr2): return arr1 + arr2 ``` **Database queries** You usually make SQL queries to load data into your app when working with databases. Repeatedly running these queries can be slow, cost money, and degrade the performance of your database. We strongly recommend caching any database queries in your app. See also [our guides on connecting Streamlit to different databases](https://docs.streamlit.io/develop/tutorials/databases) for in-depth examples. ```python connection = database.connect() @st.cache_data def query(): return pd.read_sql_query("SELECT * from table", connection) ``` #### Using `st.cache_resource` `st.cache_resource` is the right command to cache “resources” that should be available globally across all users, sessions, and reruns. It has more limited use cases than `st.cache_data`, especially for caching database connections and ML models. Within each user session, an `@st.cache_resource`-decorated function returns the cached instance of the return value (if the value is already cached). Therefore, objects cached by `st.cache_resource` act like singletons and can mutate. #### Usage As an example for `st.cache_resource`, let's look at a typical machine learning app. As a first step, we need to load an ML model. We do this with [Hugging Face's transformers library](https://huggingface.co/docs/transformers/index): ```python from transformers import pipeline model = pipeline("sentiment-analysis") # 👈 Load the model ``` If we put this code into a Streamlit app directly, the app will load the model at each rerun or user interaction. Repeatedly loading the model poses two problems: - Loading the model takes time and slows down the app. - Each session loads the model from scratch, which takes up a huge amount of memory. Instead, it would make much more sense to load the model once and use that same object across all users and sessions. That's exactly the use case for `st.cache_resource`! Let's add it to our app and process some text the user entered: ```python from transformers import pipeline @st.cache_resource # 👈 Add the caching decorator def load_model(): return pipeline("sentiment-analysis") model = load_model() query = st.text_input("Your query", value="I love Streamlit! 🎈") if query: result = model(query)[0] # 👈 Classify the query text st.write(result) ``` If you run this app, you'll see that the app calls `load_model` only once – right when the app starts. Subsequent runs will reuse that same model stored in the cache, saving time and memory! #### Behavior How does this work? Let's go through the behavior of `st.cache_resource` step by step: 1. On the first run, Streamlit recognizes that it has never called the `load_model` function with the specified parameter value (the URL of the CSV file) So it runs the function and downloads the data. 2. Now our caching mechanism becomes active: the returned DataFrame is serialized (converted to bytes) via [pickle](https://docs.python.org/3/library/pickle.html) and stored in the cache (together with the value of the `url` parameter). 3. On the next run, Streamlit checks the cache for an entry of `load_model` with the specific `url`. There is one! So it retrieves the cached object, deserializes it to a DataFrame, and returns it instead of re-running the function and downloading the data again. This process of serializing and deserializing the cached object creates a copy of our original DataFrame. While this copying behavior may seem unnecessary, it's what we want when caching data objects since it effectively prevents mutation and concurrency issues. Read the section “[Mutation and concurrency issues](#mutation-and-concurrency-issues)” below to understand this in more detail. #### Examples **Database connections** `st.cache_resource` is useful for connecting to databases. Usually, you're creating a connection object that you want to reuse globally for every query. Creating a new connection object at each run would be inefficient and might lead to connection errors. That's exactly what `st.cache_resource` can do, e.g., for a Postgres database: ```python @st.cache_resource def init_connection(): host = "hh-pgsql-public.ebi.ac.uk" database = "pfmegrnargs" user = "reader" password = "NWDMCE5xdipIjRrp" return psycopg2.connect(host=host, database=database, user=user, password=password) ``` Connection to a Postgres database: ```python connection = init_connection() ``` #### Loading ML models Your app should always cache ML models, so they are not loaded into memory again for every new session. See the [example](#example-1) above for how this works with 🤗 Hugging Face models. You can do the same thing for PyTorch, TensorFlow, etc. Here's an example for PyTorch: ```python @st.cache_resource def load_model(): model = torchvision.models.resnet50(weights=ResNet50_Weights.DEFAULT) model.eval() return model ``` #### Deciding which caching decorator to use The sections above showed many common examples for each caching decorator. But there are edge cases for which it's less trivial to decide which caching decorator to use. Eventually, it all comes down to the difference between “data” and “resource”: - Data are serializable objects (objects that can be converted to bytes via [pickle](https://docs.python.org/3/library/pickle.html)) that you could easily save to disk. Imagine all the types you would usually store in a database or on a file system – basic types like str, int, and float, but also arrays, DataFrames, images, or combinations of these types (lists, tuples, dicts, and so on). - Resources are unserializable objects that you usually would not save to disk or a database. They are often more complex, non-permanent objects like database connections, ML models, file handles, threads, etc. From the types listed above, it should be obvious that most objects in Python are “data.” That's also why `st.cache_data` is the correct command for almost all use cases. `st.cache_resource` is a more exotic command that you should only use in specific situations. Or if you're lazy and don't want to think too much, look up your use case or return type in the table below 😉: | Use case | Typical return types | Caching decorator | | --- | --- | --- | | Reading a CSV file with pd.read_csv | pandas.DataFrame | `st.cache_data` | | Reading a text file | str, list of str | `st.cache_data` | | Transforming pandas dataframes | pandas.DataFrame, pandas.Series | `st.cache_data` | | Computing with numpy arrays | numpy.ndarray | `st.cache_data` | | Simple computations with basic types | str, int, float, … | `st.cache_data` | | Querying a database | pandas.DataFrame | `st.cache_data` | | Querying an API | pandas.DataFrame, str, dict | `st.cache_data` | | Running an ML model (inference) | pandas.DataFrame, str, int, dict, list | `st.cache_data` | | Creating or processing images | PIL.Image.Image, numpy.ndarray | `st.cache_data` (but some libraries require `st.cache_resource`, since the chart object is not serializable – make sure not to mutate the chart after creation!) | | Creating charts | matplotlib.figure.Figure, plotly.graph_objects.Figure, altair.Chart | `st.cache_data` (but may be better to use `st.cache_data` on the collected results) | | Initializing database connections | pyodbc.Connection, sqlalchemy.engine.base.Engine, psycopg2.connection, mysql.connector.MySQLConnection, sqlite3.Connection | `st.cache_resource` (but may be better to use `st.cache_data` on the collected results) | | Opening persistent file handles | _io.TextIOWrapper | `st.cache_resource` | | Opening persistent threads | threading.Thread | `st.cache_resource` | ## Advanced usage ### Controlling cache size and duration If your app runs for a long time and constantly caches functions, you might run into two problems: - The app runs out of memory because the cache is too large. - Objects in the cache become stale, e.g., because you cached old data from a database. You can combat these problems with the `ttl` and `max_entries` parameters, which are available for both caching decorators. #### The `ttl` (time-to-live) parameter `ttl` sets a time to live on a cached function. If that time is up and you call the function again, the app will discard any old, cached values, and the function will be rerun. The newly computed value will then be stored in the cache. This behavior is useful for preventing stale data (problem 2) and the cache from growing too large (problem 1). Especially when pulling data from a database or API, you should always set a `ttl` so you are not using old data. Here's an example: ```python @st.cache_data(ttl=3600) # 👈 Cache data for 1 hour (=3600 seconds) def get_api_data(): data = api.get(...) return data ``` #### The `max_entries` parameter `max_entries` sets the maximum number of entries in the cache. An upper bound on the number of cache entries is useful for limiting memory (problem 1), especially when caching large objects. The oldest entry will be removed when a new entry is added to a full cache. Here's an example: ```python @st.cache_data(max_entries=1000) # 👈 Maximum 1000 entries in the cache def get_large_array(seed): np.random.seed(seed) arr = np.random.rand(100000) return arr ``` ### Customizing the spinner By default, Streamlit shows a small loading spinner in the app when a cached function is running. You can modify it easily with the `show_spinner` parameter, which is available for both caching decorators: ```python @st.cache_data(show_spinner=False) # 👈 Disable the spinner def get_api_data(): data = api.get(...) return data @st.cache_data(show_spinner="Fetching data from API...") # 👈 Use custom text for spinner def get_api_data(): data = api.get(...) return data ``` ### Excluding input parameters In a cached function, all input parameters must be hashable. Let's quickly explain why and what it means. When the function is called, Streamlit looks at its parameter values to determine if it was cached before. Therefore, it needs a reliable way to compare the parameter values across function calls. Trivial for a string or int – but complex for arbitrary objects! Streamlit uses [hashing](https://en.wikipedia.org/wiki/Hash_function) to solve that. It converts the parameter to a stable key and stores that key. At the next function call, it hashes the parameter again and compares it with the stored hash key. Unfortunately, not all parameters are hashable! E.g., you might pass an unhashable database connection or ML model to your cached function. In this case, you can exclude input parameters from caching. Simply prepend the parameter name with an underscore (e.g., `_param1`, `_param2`, etc.), and it will not be used for caching. Even if it changes, Streamlit will return a cached result if all the other parameters match up. Here's an example: ```python @st.cache_data def fetch_data(_db_connection, num_rows): data = _db_connection.fetch(num_rows) return data connection = init_connection() fetch_data(connection, 10) ``` But what if you want to cache a function that takes an unhashable parameter? For example, you might want to cache a function that takes an ML model as input and returns the layer names of that model. Since the model is the only input parameter, you cannot exclude it from caching. In this case you can use the `hash_funcs` parameter to specify a custom hashing function for the model. ### The `hash_funcs` parameter As described above, Streamlit's caching decorators hash the input parameters and cached function's signature to determine whether the function has been run before and has a return value stored (\"cache hit\") or needs to be run (\"cache miss\"). Input parameters that are not hashable by Streamlit's hashing implementation can be ignored by prepending an underscore to their name. But there are two rare cases where this is undesirable. i.e. where you want to hash the parameter that Streamlit is unable to hash: - When Streamlit's hashing mechanism fails to hash a parameter, resulting in a `UnhashableParamError` being raised. - When you want to override Streamlit's default hashing mechanism for a parameter. Let's discuss each of these cases in turn with examples. #### Example 1: Hashing a custom class Streamlit does not know how to hash custom classes. If you pass a custom class to a cached function, Streamlit will raise a `UnhashableParamError`. For example, let's define a custom class `MyCustomClass` that accepts an initial integer score. Let's also define a cached function `multiply_score` that multiplies the score by a multiplier: ```python import streamlit as st class MyCustomClass: def __init__(self, initial_score: int): self.my_score = initial_score @st.cache_data def multiply_score(obj: MyCustomClass, multiplier: int) -> int: return obj.my_score * multiplier initial_score = st.number_input("Enter initial score", value=15) score = MyCustomClass(initial_score) multiplier = 2 st.write(multiply_score(score, multiplier)) ``` If you run this app, you'll see that Streamlit raises a `UnhashableParamError` since it does not know how to hash `MyCustomClass`: ```python UnhashableParamError: Cannot hash argument 'obj' (of type __main__.MyCustomClass) in 'multiply_score'. ``` To fix this, we can use the `hash_funcs` parameter to tell Streamlit how to hash `MyCustomClass`. We do this by passing a dictionary to `hash_funcs` that maps the name of the parameter to a hash function. The choice of hash function is up to the developer. In this case, let's define a custom hash function `hash_func` that takes the custom class as input and returns the score. We want the score to be the unique identifier of the object, so we can use it to deterministically hash the object: ```python import streamlit as st from pydantic import BaseModel class MyCustomClass: def __init__(self, initial_score: int): self.my_score = initial_score def hash_func(obj: MyCustomClass) -> int: return obj.my_score # or any other value that uniquely identifies the object @st.cache_data(hash_funcs={MyCustomClass: hash_func}) def multiply_score(obj: MyCustomClass, multiplier: int) -> int: return obj.my_score * multiplier initial_score = st.number_input("Enter initial score", value=15) score = MyCustomClass(initial_score) multiplier = 2 st.write(multiply_score(score, multiplier)) ``` Now if you run the app, you'll see that Streamlit no longer raises a `UnhashableParamError` and the app runs as expected. Let's now consider the case where `multiply_score` is an attribute of `MyCustomClass` and we want to hash the entire object: ```python import streamlit as st from pydantic import BaseModel class MyCustomClass: def __init__(self, initial_score: int): self.my_score = initial_score @st.cache_data def multiply_score(self, multiplier: int) -> int: return self.my_score * multiplier initial_score = st.number_input("Enter initial score", value=15) score = MyCustomClass(initial_score) multiplier = 2 st.write(score.multiply_score(multiplier)) ``` If you run this app, you'll see that Streamlit raises a `UnhashableParamError` since it cannot hash the argument `'self'` (of type `__main__.MyCustomClass`). A simple fix here could be to use Python's `hash()` function to hash the object: ```python import streamlit as st from pydantic import BaseModel from hashlib import sha256 class MyCustomClass: def __init__(self, initial_score: int): self.my_score = initial_score @st.cache_data(hash_funcs={self: sha256}) def multiply_score(self, multiplier: int) -> int: return self.my_score * multiplier initial_score = st.number_input("Enter initial score", value=15) score = MyCustomClass(initial_score) multiplier = 2 st.write(score.multiply_score(multiplier)) ``` #### Example 2: Hashing a Pydantic model Your app should always cache ML models, so they are not loaded into memory again for every new session. See also [our guides on connecting Streamlit to different databases](https://docs.streamlit.io/develop/tutorials/databases) for in-depth examples. ```python connection = database.connect() @st.cache_data def query(): return pd.read_sql_query("SELECT * from table", connection) option = st.radio("Model 1 or 2", [1, 2]) base_model = load_base_model(option) layers = load_layers(base_model) st.write(layers) ``` #### Example 3: Hashing a ML model Running complex machine learning models can use significant time and memory. To avoid rerunning the same computations over and over, use caching. ```python @st.cache_data def run_model(inputs): return model(inputs) ``` #### Example 4: Overriding Streamlit's default caching mechanism Let's consider another example where we want to override Streamlit's default caching mechanism for a pytz-localized datetime object: ```python from datetime import datetime import pytz import streamlit as st tz = pytz.timezone("Europe/Berlin") @st.cache_data def load_data(dt): return dt now = datetime.now() st.text(load_data(dt=now)) now_tz = tz.localize(datetime.now()) st.text(load_data(dt=now_tz)) ``` It may be surprising to see that although `now` and `now_tz` are of the same `class 'datetime.datetime'` type, Streamlit does not know how to hash `now_tz` and raises a `UnhashableParamError`. In this case, we can override Streamlit's default caching mechanism for `datetime` objects by passing a custom hash function to the `hash_funcs` parameter: ```python from datetime import datetime import pytz import streamlit as st tz = pytz.timezone("Europe/Berlin") @st.cache_data(hash_funcs={datetime: lambda x: x.strftime("%a %d %b %Y, %I:%M%p")}) def load_data(dt): return dt now = datetime.now() st.text(load_data(dt=now)) now_tz = tz.localize(datetime.now()) st.text(load_data(dt=now_tz)) ``` Let's now consider a case where we want to override Streamlit's default caching mechanism for NumPy arrays. While Streamlit natively hashes Pandas and NumPy objects, there may be cases where you want to override Streamlit's default caching mechanism for these objects. For example, let's say we create a cache-decorated `show_data` function that accepts a NumPy array and returns it without modification. In the below app, `data = df[\"str\"].unique()` (which is a NumPy array) is passed to the `show_data` function. ```python import time import numpy as np import pandas as pd import streamlit as st @st.cache_data def get_data(): df = pd.DataFrame({"num": [112, 112, 2, 3], "str": ["be", "a", "be", "c"]}) return df @st.cache_data def show_data(data): time.sleep(2) # This makes the function take 2s to run return data df = get_data() data = df["str"].unique() st.dataframe(show_data(data)) st.button("Re-run") ``` Since `data` is always the same, we expect the `show_data` function to return the cached value. However, if you run the app, and click the "Re-run" button, you'll notice that the `show_data` function is re-run each time. We can assume this behavior is a consequence of Streamlit's default hashing mechanism for NumPy arrays. To work around this, let's define a custom hash function `hash_func` that takes a NumPy array as input and returns a string representation of the array: ```python import time import numpy as np import pandas as pd import streamlit as st @st.cache_data def get_data(): df = pd.DataFrame({"num": [112, 112, 2, 3], "str": ["be", "a", "be", "c"]}) return df @st.cache_data(hash_funcs={np.ndarray: str}) def show_data(data): time.sleep(2) # This makes the function take 2s to run return data df = get_data() data = df["str"].unique() st.dataframe(show_data(data)) st.button("Re-run") ``` Now if you run the app, and click the "Re-run" button, you'll notice that the `show_data` function is no longer re-run each time. It's important to note here that our choice of hash function was very naive and not necessarily the best choice. For example, if the NumPy array is large, converting it to a string representation may be expensive. In such cases, it is up to you as the developer to define what a good hash function is for your use case. #### Static elements Since version 1.16.0, cached functions can contain Streamlit commands! For example, you can do this: ```python @st.cache_data def get_api_data(): data = api.get(...) st.success("Fetched data from API!") # 👈 Show a success message return data ``` As we know, Streamlit only runs this function if it hasn't been cached before. On this first run, the `st.success` message will appear in the app. But what happens on subsequent runs? It still shows up! Streamlit realizes that there is an `st.``-command inside the cached function, saves it during the first run, and replays it on subsequent runs. Replaying static elements works for both caching decorators. You can also use this functionality to cache entire parts of your UI: ```python @st.cache_data def show_data(): st.header("Data analysis") data = api.get(...) st.success("Fetched data from API!") st.write("Here is a plot of the data:") st.line_chart(data) st.write("And here is the raw data:") st.dataframe(data) ``` #### Input widgets You can also use [interactive input widgets](https://docs.streamlit.io/develop/api-reference/widgets) like `st.slider` or `st.text_input` in cached functions. Widget replay is an experimental feature at the moment. To enable it, you need to set the `experimental_allow_widgets` parameter: ```python @st.cache_data(experimental_allow_widgets=True) # 👈 Set the parameter def get_data(): num_rows = st.slider("Number of rows to get") # 👈 Add a slider data = api.get(..., num_rows) return data ``` Streamlit treats the slider like an additional input parameter to the cached function. If you change the slider position, Streamlit will see if it has already cached the function for this slider value. If yes, it will return the cached value. If not, it will rerun the function using the new slider value. Using widgets in cached functions is extremely powerful because it lets you cache entire parts of your app. But it can be dangerous! Since Streamlit treats the widget value as an additional input parameter, it can easily lead to excessive memory usage. Imagine your cached function has five sliders and returns a 100 MB DataFrame. Then we'll add 100 MB to the cache for every permutation of these five slider values – even if the sliders do not influence the returned data! These additions can make your cache explode very quickly. Please be aware of this limitation if you use widgets in cached functions. We recommend using this feature only for isolated parts of your UI where the widgets directly influence the cached return value. Two widgets are currently not supported in cached functions: `st.file_uploader` and `st.camera_input`. We may support them in the future. Feel free to [open a GitHub issue](https://github.com/streamlit/streamlit/issues) if you need them! ## Dealing with large data As we explained, you should cache data objects with `st.cache_data`. But this can be slow for extremely large data, e.g., DataFrames or arrays with >100 million rows. That's because of the copying behavior of `st.cache_data`: on the first run, it serializes the return value to bytes and deserializes it on subsequent runs. Both operations take time. If you're dealing with extremely large data, it can make sense to use `st.cache_resource` instead. It does not create a copy of the return value via serialization/deserialization and is almost instant. But watch out: any mutation to the function's return value (such as dropping a column from a DataFrame or setting a value in an array) directly manipulates the object in the cache. You must ensure this doesn't corrupt your data or lead to crashes. See the section on [Mutation and concurrency issues](#mutation-and-concurrency-issues) below. When benchmarking `st.cache_data` on pandas DataFrames with four columns, we found that it becomes slow when going beyond 100 million rows. The table shows runtimes for both caching decorators at different numbers of rows (all with four columns): | | 10M rows | 50M rows | 100M rows | 200M rows | | --- | --- | --- | --- | --- | | `st.cache_data` | First run* | 0.4 s | 3 s | 14 s | 28 s | | Subsequent runs | 0.2 s | 1 s | 2 s | 7 s | | `st.cache_resource` | First run* | 0.01 s | 0.1 s | 0.2 s | 1 s | | Subsequent runs | 0 s | 0 s | 0 s | 0 s | *For the first run, the table only shows the overhead time of using the caching decorator. It does not include the runtime of the cached function itself. ## Mutation and concurrency issues In the sections above, we talked a lot about issues when mutating return objects of cached functions. This topic is complicated! But it's central to understanding the behavior differences between `st.cache_data` and `st.cache_resource`. So let's dive in a bit deeper. First, we should clearly define what we mean by mutations and concurrency: - By **mutations**, we mean any changes made to a cached function's return value after that function has been called. I.e. something like this: ```python @st.cache_data def create_list(): l = [1, 2, 3] l[0] = 2 # 👈 Mutate its return value ``` - By **concurrency**, we mean that multiple sessions can cause these mutations at the same time. Streamlit is a web framework that needs to handle many users and sessions connecting to an app. If two people view an app at the same time, they will both cause the Python script to rerun, which may manipulate cached return objects at the same time – concurrently. Mutating cached return objects can be dangerous. It can lead to exceptions in your app and even corrupt your data (which can be worse than a crashed app!). Below, we'll first explain the copying behavior of `st.cache_data` and show how it can avoid mutation issues. Then, we'll show how concurrent mutations can lead to data corruption and how to prevent it. ### Copying behavior `st.cache_data` creates a copy of the cached return value each time the function is called. This avoids most mutations and concurrency issues. To understand it in detail, let's go back to the [Uber ridesharing example](#usage) from the section on `st.cache_data` above. We are making two modifications to it: 1. We are using `st.cache_resource` instead of `st.cache_data`. `st.cache_resource` does not create a copy but stores the original DataFrame. 2. After loading the data, we manipulate the returned DataFrame (in place!) by dropping the column `Lat`. Here's the code: ```python @st.cache_resource # 👈 Turn off copying behavior def load_data(url): df = pd.read_csv(url) return df df = load_data("https://raw.githubusercontent.com/plotly/datasets/master/uber-rides-data1.csv") st.dataframe(df) df.drop(columns=['Lat'], inplace=True) # 👈 Mutate the dataframe inplace st.button("Rerun") ``` Let's run it and see what happens! The first run should work fine. But in the second run, you see an exception: `KeyError: 'Lat' not found in axis`. Why is that happening? Let's go step by step: 1. On the first run, Streamlit runs `load_data` and stores the resulting DataFrame in the cache. Since we're using `st.cache_resource`, it does not create a copy but stores the original DataFrame. 2. Then we drop the column `Lat` from the DataFrame. Note that this is dropping the column from the original DataFrame stored in the cache. We are manipulating it! 3. On the second run, Streamlit returns that exact same manipulated DataFrame from the cache. It does not have the column `Lat` anymore! So our call to `df.drop` results in --- # Source: https://docs.streamlit.io/develop/api-reference/charts # Chart elements Streamlit supports several different charting libraries, and our goal is to continually add support for more. Right now, the most basic library in our arsenal is [Matplotlib](https://matplotlib.org/). Then there are also interactive charting libraries like [Vega Lite](https://vega.github.io/vega-lite/) (2D charts) and [deck.gl](https://github.com/uber/deck.gl) (maps and 3D charts). And finally we also provide a few chart types that are "native" to Streamlit, like `st.line_chart` and `st.area_chart`. ## Simple chart elements ### Simple area charts Display an area chart. ```python st.area_chart(my_data_frame) ``` ### Simple bar charts Display a bar chart. ```python st.bar_chart(my_data_frame) ``` ### Simple line charts Display a line chart. ```python st.line_chart(my_data_frame) ``` ### Simple scatter charts Display a line chart. ```python st.scatter_chart(my_data_frame) ``` ### Scatterplots on maps Display a map with points on it. ```python st.map(my_data_frame) ``` ## Advanced chart elements ### Matplotlib Display a matplotlib.pyplot figure. ```python st.pyplot(my_mpl_figure) ``` ### Altair Display a chart using the Altair library. ```python st.altair_chart(my_altair_chart) ``` ### Vega-Lite Display a chart using the Vega-Lite library. ```python st.vega_lite_chart(my_vega_lite_chart) ``` ### Plotly Display an interactive Plotly chart. ```python st.plotly_chart(my_plotly_chart) ``` ### Bokeh Display an interactive Bokeh chart. ```python st.bokeh_chart(my_bokeh_chart) ``` ### PyDeck Display a chart using the PyDeck library. ```python st.pydeck_chart(my_pydeck_chart) ``` ### GraphViz Display a graph using the dagre-d3 library. ```python st.graphviz_chart(my_graphviz_spec) ``` ### Third-party components These are featured components created by our lovely community. For more examples and inspiration, check out our [Components Gallery](https://streamlit.io/components) and [Streamlit Extras](https://extras.streamlit.app/)! ### Streamlit Lottie Integrate [Lottie](https://lottiefiles.com/) animations inside your Streamlit app. Created by [@andfanilo](https://github.com/andfanilo). ```python import plost plost.line_chart(my_dataframe, x='time', y='stock_value', color='stock_name') ``` ### Plotly Events Make Plotly charts interactive!. Created by [@null-jones](https://github.com/null-jones/). ```python fig = px.line(x=[1], y=[1]) selected_points = plotly_events(fig) ``` ### Streamlit Folium Streamlit Component for rendering Folium maps. Created by [@randyzwitch](https://github.com/randyzwitch/). ```python m = folium.Map(location=[39.949610, -75.150282], zoom_start=16) st_data = st_folium(m, width=725) ``` ### Spacy-Streamlit spaCy building blocks and visualizers for Streamlit apps. Created by [@explosion](https://github.com/explosion/). ```python models = ['en_core_web_sm', 'en_core_web_md'] spacy_streamlit.visualize(models, 'Sundar Pichai is the CEO of Google.') ``` ### Streamlit Agraph A Streamlit Graph Vis, based on [react-grah-vis](https://github.com/crubier/react-graph-vis). Created by [@ChrisDelClea](https://github.com/ChrisDelClea/). ```python from streamlit_agraph import agraph, Node, Edge, Config agraph(nodes=nodes, edges=edges, config=config) ``` ### Streamlit Lottie Integrate [Lottie](https://lottiefiles.com/) animations inside your Streamlit app. Created by [@andfanilo](https://github.com/andfanilo/). ```python lottie_hello = load_lottieurl("https://assets5.lottiefiles.com/packages/lf20_V9t630.json") st_lottie(lottie_hello, key="hello") ``` ### Plotly Events Make Plotly charts interactive!. Created by [@null-jones](https://github.com/null-jones/). ```python fig = px.line(x=[1], y=[1]) selected_points = plotly_events(fig) ``` ### Streamlit Folium Streamlit Component for rendering Folium maps. Created by [@randyzwitch](https://github.com/randyzwitch/). ```python m = folium.Map(location=[39.949610, -75.150282], zoom_start=16) st_data = st_folium(m, width=725) ``` ### Spacy-Streamlit spaCy building blocks and visualizers for Streamlit apps. Created by [@explosion](https://github.com/explosion/). ```python models = ['en_core_web_sm', 'en_core_web_md'] spacy_streamlit.visualize(models, 'Sundar Pichai is the CEO of Google.') ``` ### Streamlit Agraph A Streamlit Graph Vis, based on [react-grah-vis](https://github.com/crubier/react-graph-vis). Created by [@ChrisDelClea](https://github.com/ChrisDelClea/). ```python from streamlit_agraph import agraph, Node, Edge, Config agraph(nodes=nodes, edges=edges, config=config) ``` ### Streamlit Lottie Integrate [Lottie](https://lottiefiles.com/) animations inside your Streamlit app. Created by [@andfanilo](https://github.com/andfanilo/). ```python lottie_hello = load_lottieurl("https://assets5.lottiefiles.com/packages/lf20_V9t630.json") st_lottie(lottie_hello, key="hello") ``` ## App Testing Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ## Previous: Data elements [Previous: Data elements](/develop/api-reference/data) ## Next: st.area_chart [Next: st.area_chart](/develop/api-reference/charts/st.area_chart) --- # Source: https://docs.streamlit.io/develop/tutorials/chat-and-llm-apps # Build LLM apps ## Navigation - [Get started](/get-started) - [Installation](/get-started/installation) - [Fundamentals](/get-started/fundamentals) - [First steps](/get-started/tutorials) - [Develop](/develop) - [Concepts](/develop/concepts) - [API reference](/develop/api-reference) - [Tutorials](/develop/tutorials) - [Authentication and personalization](/develop/tutorials/authentication) - [Build a basic LLM chat app](/develop/tutorials/chat-and-llm-apps/build-conversational-apps) - [Build an LLM app using LangChain](/develop/tutorials/chat-and-llm-apps/llm-quickstart) - [Get chat response feedback](/develop/tutorials/chat-and-llm-apps/chat-response-feedback) - [Validate and edit chat responses](/develop/tutorials/chat-and-llm-apps/validate-and-edit-chat-responses) - [Configuration and theming](/develop/tutorials/configuration-and-theming) - [Connect to data sources](/develop/tutorials/databases) - [Elements](/develop/tutorials/elements) - [Execution flow](/develop/tutorials/execution-flow) - [Multipage apps](/develop/tutorials/multipage) - [Quick reference](/develop/quick-reference) - [Deploy](/deploy) - [Concepts](/deploy/concepts) - [Streamlit Community Cloud](/deploy/streamlit-community-cloud) - [Snowflake](/deploy/snowflake) - [Other platforms](/deploy/tutorials) - [Knowledge base](/knowledge-base) - [FAQ](/knowledge-base/using-streamlit) - [Installing dependencies](/knowledge-base/dependencies) - [Deployment issues](/knowledge-base/deploy) ## Main Content ### Build LLM apps [Build a basic chat app](/develop/tutorials/llms/build-conversational-apps) [Build an LLM app using LangChain](/develop/tutorials/llms/llm-quickstart) [Get chat response feedback](/develop/tutorials/chat-and-llm-apps/chat-response-feedback) [Validate and edit chat responses](/develop/tutorials/chat-and-llm-apps/validate-and-edit-chat-responses) [Previous: Authentication and personalization](/develop/tutorials/authentication) [Next: Build a basic LLM chat app](/develop/tutorials/chat-and-llm-apps/build-conversational-apps) ### Forum **Still have questions?** Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Footer © 2025 Snowflake Inc. --- # Source: https://docs.streamlit.io/develop/tutorials/chat-and-llm-apps/chat-response-feedback # Collect user feedback about LLM responses A common task in a chat app is to collect user feedback about an LLM's responses. Streamlit includes `st.feedback` to conveniently collect user sentiment by displaying a group of selectable sentiment icons. This tutorial uses Streamlit's chat commands and `st.feedback` to build a simple chat app that collects user feedback about each response. ## Initialize your app 1. In `your_repository`, create a file named `app.py`. 2. In a terminal, change directories to `your_repository`, and start your app: ```bash streamlit run app.py ``` Your app will be blank because you still need to add code. 3. In `app.py`, write the following: ```python import streamlit as st import time def chat_stream(prompt): response = f'You said, \"{prompt}\" ...interesting.' for char in response: yield char time.sleep(0.02) def save_feedback(index): st.session_state.history[index]["feedback"] = st.session_state[f"feedback_{index}"] if "history" not in st.session_state: st.session_state.history = [] for i, message in enumerate(st.session_state.history): with st.chat_message(message["role"]): st.write(message["content"]) if message["role"] == "assistant": feedback = message.get("feedback", None) st.session_state[f"feedback_{i}"] = feedback st.feedback( "thumbs", key=f"feedback_{i}", disabled=feedback is not None, on_change=save_feedback, args=[i], ) st.session_state.history.append({"role": "assistant", "content": response}) ``` 4. Save your file and go to your browser to try your new app. ## Optional: Change the feedback behavior Your app currently allows users to rate any response once. They can submit their rating at any time, but can't change it. If you want users to rate only the _most recent_ response, you can remove the widgets from the chat history: ```python for i, message in enumerate(st.session_state.history): with st.chat_message(message["role"]): st.write(message["content"]) if message["role"] == "assistant": feedback = message.get("feedback", None) st.session_state[f"feedback_{i}"] = feedback st.feedback( "thumbs", key=f"feedback_{i}", disabled=feedback is not None, on_change=save_feedback, args=[i], ) ``` Or, if you want to allow users to change their responses, you can just remove the `disabled` parameter: ```python for i, message in enumerate(st.session_state.history): with st.chat_message(message["role"]): st.write(message["content"]) if message["role"] == "assistant": feedback = message.get("feedback", None) st.session_state[f"feedback_{i}"] = feedback st.feedback( "thumbs", key=f"feedback_{i}", on_change=save_feedback, args=[i], ) --- # Source: https://docs.streamlit.io/develop/api-reference/chat # Chat elements Streamlit provides a few commands to help you build conversational apps. These chat elements are designed to be used in conjunction with each other, but you can also use them separately. `st.chat_message` lets you insert a chat message container into the app so you can display messages from the user or the app. Chat containers can contain other Streamlit elements, including charts, tables, text, and more. `st.chat_input` lets you display a chat input widget so the user can type in a message. Remember to check out `st.status` to display output from long-running processes and external API calls. ## Chat input ![screenshot](/images/api/chat_input.jpg) Display a chat input widget. ```python prompt = st.chat_input("Say something") if prompt: st.write(f"The user has sent: {prompt}") ``` ## Chat message ![screenshot](/images/api/chat_message.jpg) Insert a chat message container. ```python import numpy as np with st.chat_message("user"): st.write("Hello 👋") st.line_chart(np.random.randn(30, 3)) ``` ## Status container ![screenshot](/images/api/status.jpg) Display output of long-running tasks in a container. ```python with st.status('Running'): do_something_slow() ``` ## st.write_stream ![screenshot](/images/api/write_stream.jpg) Write generators or streams to the app with a typewriter effect. ```python st.write_stream(my_generator) st.write_stream(my_llm_stream) ``` --- # Source: https://docs.streamlit.io/develop/quick-reference/cheat-sheet # Source: https://docs.streamlit.io/develop/concepts/app-testing/cheat-sheet # App testing cheat sheet ## Text elements ### Headers - Assert "My app" in at.title[0].value - Assert "New topic" in at.header[0].value - Assert "Interesting sub-topic" in at.subheader[0].value - Assert len(at.divider) == 2 ### Body / code - Assert "Hello, world!" in at.markdown[0].value - Assert "import streamlit as st" in at.code[0].value - Assert "A cool diagram" in at.caption[0].value - Assert "Hello again, world!" in at.text[0].value - Assert "\\int a x^2 \\,dx" in at.latex[0].value ## Input widgets ### Button - Assert at.button[0].value == False - at.button[0].click().run() - Assert at.button[0].value == True ### Checkbox - Assert at.checkbox[0].value == False - at.checkbox[0].check().run() # uncheck() is also supported - Assert at.checkbox[0].value == True ### Color_picker - Assert at.color_picker[0].value == "#FFFFFF" - at.color_picker[0].pick("#000000").run() ### Date_input - Assert at.date_input[0].value == datetime.date(2019, 7, 6) - at.date_input[0].set_value(datetime.date(2022, 12, 21)).run() ### Form_submit_button - Assert at.button[0].value == False - at.button[0].click().run() - Assert at.button[0].value == True ### Multiselect - Assert at.multiselect[0].value == ["foo", "bar"] - at.multiselect[0].select("baz").unselect("foo").run() ### Number_input - Assert at.number_input[0].value == 5 - at.number_input[0].increment().run() ### Radio - Assert at.radio[0].value == "Bar" - Assert at.radio[0].index == 3 - at.radio[0].set_value("Foo").run() ### Selectbox - Assert at.selectbox[0].value == "Bar" - Assert at.selectbox[0].index == 3 - at.selectbox[0].set_value("Foo").run() ### Select_slider - Assert at.select_slider[0].value == "Feb" - at.select_slider[0].set_value("Mar").run() - at.select_slider[0].set_range("Apr", "Jun").run() ### Slider - Assert at.slider[0].value == 2 - at.slider[0].set_value(3).run() - at.slider[0].set_range(4, 6).run() ### Text_area - Assert at.text_area[0].value == "Hello, world!" - at.text_area[0].set_value("Hello, yourself!").run() ### Text_input - Assert at.text_input[0].value == "Hello, world!" - at.text_input[0].set_value("Hello, yourself!").run() ### Time_input - Assert at.time_input[0].value == datetime.time(8, 45) - at.time_input[0].set_value(datetime.time(12, 30)) ### Toggle - Assert at.toggle[0].value == False - Assert at.toggle[0].label == "Debug mode" - at.toggle[0].set_value(True).run() - Assert at.toggle[0].value == True ## Data elements ### DataFrame - Assert at.dataframe[0].value.equals(expected_df) ### Metric - Assert at.metric[0].value == "9500" - Assert at.metric[0].delta == "1000" ### JSON - Assert at.json[0].value == '[\"hi\", {\"foo\": \"bar\"}]' ### Table - Assert at.table[0].value.equals(table_df) ## Layouts and containers ### Sidebar - Assert at.sidebar.text_input[0].set_value("Jane Doe") ### Columns - Assert at.columns[1].markdown[0].value == "Hello, world!" ### Tabs - Assert at.tabs[2].markdown[0].value == "Hello, yourself!" ## Chat elements ### Chat_input - Assert at.chat_input[0].set_value("Do you know any jokes?") - Assert at.chat_message[0].markdown[0].value == "Do you know any jokes?" - Assert at.chat_message[0].avatar == "user" ## Status elements ### Exception - Assert len(at.exception) == 1 - Assert "TypeError" in at.exception[0].value ### Other in-line alerts - Assert at.success[0].value == "Great job!" - Assert at.info[0].value == "Please enter an API key to continue" - Assert at.warning[0].value == "Sorry, the passwords didn't match" - Assert at.error[0].value == "Something went wrong :(" ### Toast - Assert at.toast[0].value == "That was lit!" - Assert at.toast[0].icon == "🔥" ## Limitations As of Streamlit 1.28, the following Streamlit features are not natively supported by `AppTest`. However, workarounds are possible for many of them by inspecting the underlying proto directly using `AppTest.get()`. We plan to regularly add support for missing elements until all features are supported. - Chart elements (st.bar_chart, st.line_chart, etc) - Media elements (st.image, st.video, st.audio) - st.file_uploader - st.data_editor - st.expander - st.status - st.camera_input - st.download_button - st.link_button --- # Source: https://docs.streamlit.io/develop/api-reference/cli # Command-line options When you install Streamlit, a command-line (CLI) tool gets installed as well. The purpose of this tool is to run Streamlit apps, change Streamlit configuration options, and help you diagnose and fix issues. ## Available commands - `streamlit cache clear`: Clear the on-disk cache. - `streamlit config show`: Show all configuration options. - `streamlit docs`: Open the Streamlit docs. - `streamlit hello`: Run an example Streamlit app. - `streamlit help`: Show the available CLI commands. - `streamlit init`: Create the files for a new Streamlit app. - `streamlit run`: Run your Streamlit app. - `streamlit version`: Show the version of Streamlit. ### Run your app The most important command is `streamlit run`, which is summarized for convenience here: ```bash streamlit run your_script.py ``` At any time, in your terminal, you can stop the server with **Ctrl+C**. --- # Source: https://docs.streamlit.io/get-started/installation/command-line # Install Streamlit using command line This page will walk you through creating an environment with `venv` and installing Streamlit with `pip`. These are our recommended tools, but if you are familiar with others you can use your favorite ones too. At the end, you'll build a simple "Hello world" app and run it. If you prefer to have a graphical interface to manage your Python environments, check out how to [Install Streamlit using Anaconda Distribution](/get-started/installation/anaconda-distribution). ## Prerequisites As with any programming tool, in order to install Streamlit you first need to make sure your computer is properly set up. More specifically, you’ll need: 1. **Python** We support [version 3.9 to 3.13](https://www.python.org/downloads/). 2. **A Python environment manager** (recommended) Environment managers create virtual environments to isolate Python package installations between projects. We recommend using virtual environments because installing or upgrading a Python package may cause unintentional effects on another package. For a detailed introduction to Python environments, check out [Python Virtual Environments: A Primer](https://realpython.com/python-virtual-environments-a-primer/). For this guide, we'll be using `venv`, which comes with Python. 3. **A Python package manager** Package managers handle installing each of your Python packages, including Streamlit. For this guide, we'll be using `pip`, which comes with Python. 4. **Only on MacOS: Xcode command line tools** Download Xcode command line tools using [these instructions](https://mac.install.guide/commandlinetools/4.html) in order to let the package manager install some of Streamlit's dependencies. 5. **A code editor** Our favorite editor is [VS Code](https://code.visualstudio.com/download), which is also what we use in all our tutorials. ## Create an environment using `venv` 1. Open a terminal and navigate to your project folder. 2. In your terminal, type: ```bash # Windows command prompt .venv\Scripts\activate.bat # Windows PowerShell .venv\Scripts\Activate.ps1 # macOS and Linux source .venv/bin/activate ``` 3. Once activated, you will see your environment's name in parentheses at the beginning of your terminal prompt. `.venv` 4. Run your Streamlit app. ```bash streamlit run app.py ``` If this doesn't work, use the long-form command: ```bash python -m streamlit run app.py ``` 5. To stop the Streamlit server, press `Ctrl+C` in the terminal. 6. When you're done using this environment, return to your normal shell by typing: ```bash deactivate ``` ## What's next? Read about our [Basic concepts](/get-started/fundamentals/main-concepts) to understand Streamlit's dataflow model. [Previous: Use Streamlit Playground](/get-started/installation/streamlit-playground) [Next: Install via Anaconda Distribution](/get-started/installation/anaconda-distribution) --- # Source: https://docs.streamlit.io/get-started/installation/community-cloud # Use Community Cloud to develop with GitHub Codespaces To use GitHub Codespaces for Streamlit development, you need a properly configured `devcontainer.json` file to set up the environment. Fortunately, Streamlit Community Cloud is here to help! Although Community Cloud is primarily used to deploy and share apps with the rest of the world, we've built in some handy features to make it easy to use GitHub Codespaces. This guide explains how to create a Community Cloud account and use an automated workflow to get you into a GitHub codespace and live-editing a Streamlit app. All this happens right in your browser, no installation required. ## Prerequisites - You must have a GitHub account. ## Sign up for Streamlit Community Cloud 1. Go to [share.streamlit.io](https://share.streamlit.io/). At the bottom of the page, all your codespaces are listed. Click the overflow menu icon (more_horiz) for your codespace. 2. If you want to return to your work later, click "Stop codespace". Otherwise, click "Delete". 3. Congratulations! You just deployed an app to Streamlit Community Cloud. 🎉 Return to your workspace at [share.streamlit.io/](https://share.streamlit.io/) and deploy another Streamlit app. ## Learn Streamlit fundamentals If you haven't learned Streamlit's basic concepts yet, this is a great time to go to [Fundamentals](/get-started/fundamentals). Use your codespace to walk through and try basic Streamlit commands. When finished, come back here to learn how to clean up your codespace. ## Stop or delete your codespace When you stop interacting with your codespace, GitHub will generally stop your codespace for you. However, the surest way to avoid undesired use of your capacity is to stop or delete your codespace when you are done. 1. Go to [github.com/codespaces](https://github.com/codespaces). At the bottom of the page, all your codespaces are listed. Click the overflow menu icon (more_horiz) for your codespace. 2. If you want to return to your work later, click "Stop codespace". Otherwise, click "Delete". 3. If you want to return to your work later, click "Stop codespace". Otherwise, click "Delete". ## Previous and Next Links - [Previous: Install via Anaconda Distribution](/get-started/installation/anaconda-distribution) - [Next: Use Snowflake](/get-started/installation/streamlit-in-snowflake) --- # Component The Streamlit v2 Component signature. ```typescript import { Component } from '@streamlit/component-v2-lib'; ``` This type represents the function signature for the default export from your component's JavaScript or TypeScript code. This function gets called by Streamlit when your component is mounted in the frontend, and it receives all the necessary arguments to build and manage your component's UI and state. ## Arguments - **componentArgs (ComponentArgs)** The inputs and utilities provided by Streamlit to your component. ## Returns - **OptionalComponentCleanupFunction** An optional cleanup function that Streamlit will call when the component is unmounted. [Previous: component-v2-lib](/develop/api-reference/custom-components/component-v2-lib) [Next: ComponentArgs](/develop/api-reference/custom-components/component-v2-lib-componentargs) --- # ComponentArgs The arguments passed to a Streamlit custom component's top-level `export default` function. ```typescript import { ComponentArgs } from '@streamlit/component-v2-lib'; ``` This type provides the interface between your TypeScript component and Streamlit's runtime, including the data payload from Python, utilities for managing component state, and the DOM container for mounting your UI. Component authors typically destructure these arguments for easier access. ## Example Defining strict typing is not required. However, to follow typing best practices, you can declare your component's data and state shapes, then provide them as generic parameters to `ComponentArgs`. The following TypeScript code must be compiled to JavaScript before being passed to the component's `js` parameter in `st.components.v2.component`. ```typescript import { Component, ComponentState } from '@streamlit/component-v2-lib'; interface MyComponentState extends ComponentState { selected_item: string | null; button_clicked: boolean; } interface MyComponentData { label: string; options: string[]; } const MyComponent: Component = (component) => { // Destructure the component args for easier access const { data, setStateValue, setTriggerValue, parentElement } = component; // Set up event handlers with type-safe state management const dropdown = parentElement.querySelector('#dropdown') as HTMLSelectElement; const button = parentElement.querySelector('#submit') as HTMLButtonElement; dropdown.onchange = () => { setStateValue('selected_item', dropdown.value); } button.onclick = () => { setTriggerValue('button_clicked', true); } }; export default MyComponent; ``` ## Methods ### setStateValue ```typescript setStateValue(name: string, value: Any): void; ``` Set a state value by key. This state persists across app reruns. State values are accessible in Python through the component's result. Use this for values that should maintain their state when the user interacts with other parts of the Streamlit app. #### Parameters - **name**: The state key to set. If you are using TypeScript, this should be a key from `TComponentState`. - **value**: The value to associate with the key. Type must match the corresponding property type in your `TComponentState` interface. #### Returns - `None` ### setTriggerValue ```typescript setTriggerValue(name: string, value: Any): void; ``` Set a trigger value by key. This trigger persists for a only single app rerun. Trigger values are one-time events that are consumed during the resulting rerun and reset to `null` afterward. They're accessible in Python through the component's result. Use this for actions like button clicks, form submissions, or other event-based interactions. #### Parameters - **name**: The trigger key to set. If you are using TypeScript, this should be a key from `TComponentState`. - **value**: The value for this trigger. If you are using TypeScript, this should match the corresponding property type in your `TComponentState` interface. #### Returns - `None` --- # ComponentState The base interface for defining a Streamlit custom component's state shape. ```typescript import { ComponentState } from '@streamlit/component-v2-lib'; ``` Component state is a persistent key-value store of state and trigger values. You can extend this type or define your own interface to add type-safe state and trigger key-value pairs. Each key corresponds to an `on__change` callback parameter in Python. ## Type Aliases | Type | Description | | --- | --- | | `ComponentState = Record` | The base interface for defining a Streamlit custom component's state shape. | ## Notes Streamlit Version ## Version Streamlit Version ## Links - [Previous: ComponentArgs](/develop/api-reference/custom-components/component-v2-lib-componentargs) - [Next: OptionalComponentCleanupFunction](/develop/api-reference/custom-components/component-v2-lib-optionalcomponentcleanupfunction) ## Forum ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ## Footer © 2025 Snowflake Inc. --- # ComponentState TypeScript type alias for custom components v2 state management, enabling type-safe state persistence and data flow between component renders and user interactions. ## ComponentCleanupFunction The cleanup function returned by a Streamlit v2 Component. This type alias isn't exported. Use `OptionalComponentCleanupFunction` instead. This type represents the cleanup function that your component can return from its top-level `export default` function. If provided, Streamlit will call this function when your component is unmounted from the app, allowing you to perform any necessary cleanup tasks, such as removing event listeners or canceling network requests. ## Example Usage ```typescript import { OptionalComponentCleanupFunction } from '@streamlit/component-v2-lib'; const cleanupFunction = () => void 0; export default { export default { cleanupFunction, }, }; ``` ## Versioning Streamlit Version - Version 1.52.0 - Version 1.51.0 - Version 1.50.0 - Version 1.49.0 - Version 1.48.0 - Version 1.47.0 - Version 1.46.0 - Version 1.45.0 - Version 1.44.0 - Version 1.43.0 - Version 1.42.0 - Version 1.41.0 - Version 1.40.0 - Version 1.39.0 - Version 1.38.0 - Version 1.37.0 - Version 1.36.0 - Version 1.35.0 - Version 1.34.0 - Version 1.33.0 - Version 1.32.0 - Version 1.31.0 - Version 1.30.0 - Version 1.29.0 - Version 1.28.0 - Version 1.27.0 - Version 1.26.0 - Version 1.25.0 - Version 1.24.0 - Version 1.23.0 - Version 1.22.0 ## Related Links - [Previous: ComponentState](/develop/api-reference/custom-components/component-v2-lib-componentstate) - [Next: declare_component](/develop/api-reference/custom-components/st.components.v1.declare_component) ## Forum ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. --- # Source: https://docs.streamlit.io/develop/api-reference/custom-components/component-v2-lib # Component The [@streamlit/component-v2-lib](https://www.npmjs.com/package/@streamlit/component-v2-lib) package provides TypeScript type definitions and utilities for building Streamlit custom components using the v2 API. ## Installation Install the package from npm: ```bash npm i @streamlit/component-v2-lib ``` ## Package Information - **Package name**: `@streamlit/component-v2-lib` - **Registry**: [npm](https://www.npmjs.com/package/@streamlit/component-v2-lib) - **Purpose**: TypeScript type aliases and utilities for custom components v2 This package enables type-safe development when creating custom Streamlit components with modern JavaScript frameworks. ## Previous and Next Links - [Previous: component](/develop/api-reference/custom-components/st.components.v2.component) - [Next: Component](/develop/api-reference/custom-components/component-v2-lib-component) ## Forum ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. --- # Source: https://docs.streamlit.io/deploy/concepts # Source: https://docs.streamlit.io/develop/concepts # Development concepts This section gives you background on how different parts of Streamlit work. ## Streamlit's architecture and execution model Streamlit's execution model makes it easy to turn your scripts into beautiful, interactive web apps. - Understand how to run your app. - Understand Streamlit's execution and client-server model. - Understand the primary tools to work with Streamlit reruns. ## Multipage apps Streamlit provides an automated way to build multipage apps through directory structure. - Learn how to structure and configure your multipage app. ## App design considerations Bring together Streamlit's architecture and execution model to design your app. Work with Streamlit commands to render dynamic and interactive content for your users. - Learn how to make your apps performant and easy-to-manage. - Learn how to structure and design your project. ## Connections, secrets, and authentication - Learn how to manage connections and secrets with Streamlit's convenient, built-in features. ## Custom components Custom components extend Streamlit's functionality. - Learn how to build your own custom component. - Learn how to install a third-party component. ## Configuration and theming Streamlit provides a variety options to customize and configure your app. - Learn how to work with configuration options, including server settings, client settings, and theming. ## App testing Streamlit app testing enables developers to build and run automated tests. Bring your favorite test automation software and enjoy simple syntax to simulate user input and inspect rendered output. ## Previous and Next - [Previous: Develop](/develop) - [Next: Architecture and execution](/develop/concepts/architecture) --- # Source: https://docs.streamlit.io/develop/api-reference/cli/config # streamlit config show Print all the available configuration options, including their descriptions, default values, and current values. For more information about configuration options, see [config.toml](/develop/api-reference/configuration/config.toml). ## Syntax ```bash streamlit config show ``` ## Previous - [Previous: streamlit cache](/develop/api-reference/cli/cache) - [Next: streamlit docs](/develop/api-reference/cli/docs) ## Forum ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ## Footer © 2025 Snowflake Inc. --- # Source: https://docs.streamlit.io/develop/api-reference/configuration/config.toml # 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](https://docs.streamlit.io/develop/concepts/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](https://toml.io/en/) file. ### 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: ```bash streamlit config show ``` ### Global ```toml [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 ```toml [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 ```toml [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 ``` ### Server ```toml [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. For example, if you set this option to 30, and # you're using a Linux box with DISPLAY set to "localhost", you may experience # disconnections due to the timeout. 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. If you are using load balancing or # replication in your deployment, you must enable session stickiness # in your proxy to guarantee reconnection to the existing session. For # more information, see https://docs.streamlit.io/replication. # # Default: 120 disconnectedSessionTTL = 120 # Server certificate file for connecting via HTTPS. Must be set at the same time as `server.sslKeyFile`. # 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 a production environment, we recommend performing SSL termination through a load balancer or reverse proxy.'] sslCertFile = # Cryptographic key file for connecting via HTTPS. Must be set at the same time as `server.sslCertFile`. # 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 a production environment, we recommend performing SSL termination through a load balancer or reverse proxy.'] sslKeyFile = ``` ### Browser ```toml [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. 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 = "" ``` ### Mapbox ```toml [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 To define switchable light and dark themes, the configuration options in the `[theme]` table can be used in separate `[theme.dark]` and `[theme.light]` tables, except for the following options: - `base` - `fontFaces` - `baseFontSize` - `baseFontWeight` - `showSidebarBorder` - `chartCategoricalColors` - `chartSequentialColors` ```toml [theme] # The theme that your custom theme inherits from. # # This can be one of the following: # - "light": Streamlit's default light theme. # - "dark": Streamlit's default dark theme. # - A local file path to a TOML theme file: A local custom theme, like "themes/custom.toml". # - A URL to a TOML theme file: An externally hosted custom theme, like "https://example.com/theme.toml". # # A TOML theme file must contain a [theme] table with theme options. Any theme options defined in the app's config.toml file will override those defined in the TOML theme file. 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. # This defaults to the resolved value of `blueTextColor`. linkColor = # Whether or not links should be displayed with an underline. linkUnderline = # Text color used for code blocks. # This defaults to the resolved value of `greenTextColor`. codeTextColor = # 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 ":" (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 = # 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 URL to a CSS file in the format of ":" (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 ":" (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. 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 To define switchable light and dark themes, the configuration options in the `[theme.sidebar]` table can be used in separate `[theme.dark.sidebar]` and `[theme.light.sidebar]` tables, except for the following options: - `base` - `fontFaces` - `baseFontSize` - `baseFontWeight` - `showSidebarBorder` - `chartCategoricalColors` - `chartSequentialColors` ```toml [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 --- # Source: https://docs.streamlit.io/develop/tutorials/configuration-and-theming # Customize your theme and configure your app ## Use external font files and fallbacks to customize your font Make a new font available to your app. This tutorial uses externally hosted font files to define an alternative font and declares a built-in fallback. [Learn more](/develop/tutorials/configuration-and-theming/external-fonts) ## Use static font files to customize your font Make a new font available to your app. This tutorial uses static font files to define an alternative font. [Learn more](/develop/tutorials/configuration-and-theming/static-fonts) ## Use variable font files to customize your font Make a new font available to your app. This tutorial uses variable font files to define an alternative font. [Learn more](/develop/tutorials/configuration-and-theming/variable-fonts) [Previous: Chat and LLM apps](/develop/tutorials/chat-and-llm-apps) [Next: Use external font files](/develop/tutorials/configuration-and-theming/external-fonts) ## Forum ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ## Footer © 2025 Snowflake Inc. --- # Source: https://docs.streamlit.io/develop/api-reference/configuration # Source: https://docs.streamlit.io/develop/concepts/configuration # Configure and customize your app ## Configure and customize your app ### Theming #### Theming Understand how you can use theming configuration options to customize the appearance of your app. #### Customize colors and borders Understand the configuration options for customizing your app's color scheme. #### Customize fonts Understand the configuration options for customizing your app's font. [Previous: Custom components](/develop/concepts/custom-components) [Next: Configuration options](/develop/concepts/configuration/options) ### Forum #### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. --- © 2025 Snowflake Inc. --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/get-started/connect-your-github-account # Connect your GitHub account Connecting GitHub to your Streamlit Community Cloud account allows you to deploy apps directly from the files you store in your repositories. It also lets the system check for updates to those files and automatically update your apps. When you first connect your GitHub account to your Community Cloud account, you'll be able to deploy apps from your public repositories to Community Cloud. If you want to deploy from private repositories, you can give Community Cloud additional permissions to do so. For more information about these permissions, see [GitHub OAuth scope](https://docs.streamlit.io/deploy/streamlit-community-cloud/status#github-oauth-scope). ## Prerequisites - You must have a Community Cloud account. See [Create your account](https://docs.streamlit.io/deploy/streamlit-community-cloud/get-started/create-your-account). - You must have a GitHub account. ## Add access to public repositories 1. In the upper-left corner, click "Workspaces **warning**". 2. From the drop down, click "Connect GitHub account". 3. Enter your GitHub credentials and follow GitHub's authentication prompts. 4. Click "Authorize streamlit". This adds the "Streamlit" OAuth application to your GitHub account. This allows Community Cloud to work with your public repositories and create codespaces for you. In the next section, you can allow Community Cloud to access your private repositories, too. For more information about using and reviewing the OAuth applications on your account, see [Using OAuth apps](https://docs.github.com/en/apps/oauth-apps/using-oauth-apps/authorizing-oauth-apps#oauth-apps-and-organizations). ## Organization access To deploy apps from repositories owned by a GitHub organization, Community Cloud must have permission to access the organization's repositories. If you are a member of a GitHub organization when you connect your GitHub account, your OAuth prompts will include a section labeled "Organization access". If you have already connected your GitHub account and need to add access to an organization, follow the steps in [Manage your GitHub connection](https://docs.streamlit.io/deploy/streamlit-community-cloud/manage-your-account/manage-your-github-connection) to disconnect your GitHub account and start over. Alternatively, if you are not the owner of an organization, you can ask the owner to create a Community Cloud account for themselves and add permission directly. ### Organizations you own For any organization you own, if authorization has not been previously granted or denied, you can click "Grant" before you click "Authorize streamlit". ### Organizations owned by others For an organization you don't own, if authorization has not been previously granted or denied, you can click "Request" before you click "Authorize streamlit". If someone has already started the process of authorizing Streamlit for your organization, the OAuth prompt will show the current status. #### Approved access If an organization has already granted Streamlit access, the OAuth prompt shows a green check (check). #### Pending access If a request has been previously sent but not yet approved, the OAuth prompt shows "Access request pending". Follow up with the organization's owner to accept the request in GitHub. #### Denied access If a request has been previously sent and denied, the OAuth prompt shows a red X (close). In this case, the organization owner will need to authorize Streamlit from GitHub. See GitHub's documentation on [OAuth apps and organizations](https://docs.github.com/en/apps/oauth-apps/using-oauth-apps/authorizing-oauth-apps#oauth-apps-and-organizations). ## What's next? Now that you have your account you can [Explore your workspace](https://docs.streamlit.io/deploy/streamlit-community-cloud/get-started/explore-your-workspace). Or if you're ready to go, jump right in and [Deploy your app](https://docs.streamlit.io/deploy/streamlit-community-cloud/deploy-your-app). --- # Source: https://docs.streamlit.io/develop/concepts/connections/connecting-to-data # Connecting to data Most Streamlit apps need some kind of data or API access to be useful - either retrieving data to view or saving the results of some user action. This data or API is often part of some remote service, database, or other data source. **Anything you can do with Python, including data connections, will generally work in Streamlit**. Streamlit's [connections](/develop/api-reference/connections/st.connection) feature provides a simple and efficient way to connect your Streamlit apps to data and APIs. ## Basic usage For basic startup and usage examples, read up on the relevant [data source tutorial](/develop/tutorials/databases). Streamlit has built-in connections to SQL dialects and Snowflake. We also maintain installable connections for [Cloud File Storage](https://github.com/streamlit/files-connection) and [Google Sheets](https://github.com/streamlit/gsheets-connection). If you are just starting, the best way to learn is to pick a data source you can access and get a minimal example working from one of the pages above 👆. Here, we will provide an ultra-minimal usage example for using a SQLite database. From there, the rest of this page will focus on advanced usage. ### A simple starting point - using a local SQLite database A [local SQLite database](https://sqlite.org/) could be useful for your app's semi-persistent data storage. To see the example below running live, check out the interactive demo below: ```html ``` ```python import streamlit as st # Create the SQL connection to pets_db as specified in your secrets file. conn = st.connection("pets_db", type="sql") # Insert some data with conn.session. with conn.session as s: s.execute('CREATE TABLE IF NOT EXISTS pet_owners (person TEXT, pet TEXT);') s.execute('DELETE FROM pet_owners;') pet_owners = {'jerry': 'fish', 'barbara': 'cat', 'alex': 'puppy'} for k in pet_owners: s.execute( 'INSERT INTO pet_owners (person, pet) VALUES (:owner, :pet);', params=dict(owner=k, pet=pet_owners[k]) ) s.commit() # Query and display the data you inserted pet_owners = conn.query('select * from pet_owners') st.dataframe(pet_owners) ``` In this example, we didn't set a `ttl=` value on the call to `st.connection('myconn', type=MyConnection, ttl=1d)` because it is not necessary for most connections. The connection object will be cached without expiration using `st.cache_resource`. If you need to invalidate the cached version, you can use `st.connection('myconn', type=MyConnection, reset=True)`. ## Advanced SQLConnection configuration The `SQLConnection` configuration uses SQLAlchemy `create_engine()` function. It will take a single URL argument or attempt to construct a URL from several parts (username, database, host, and so on) using `SQLAlchemy.engine.URL.create()`. Several popular SQLAlchemy dialects, such as Snowflake and Google BigQuery, can be configured using additional arguments to `create_engine()` besides the URL. These can be passed as `**kwargs` to the `st.connection` call directly or specified in an additional secrets section called `create_engine_kwargs`. ### Example of Snowflake-SQLAlchemy configuration ```python # .streamlit/secrets.toml [connections.snowflake] url = "snowflake://user_login_name@account_identifier/" ``` ```python # streamlit_app.py import streamlit as st # url and connect_args from secrets.toml above are picked up and used here conn = st.connection("snowflake", "sql") # ... ``` Alternatively, this could be specified entirely in `**kwargs`. ```python # streamlit_app.py import streamlit as st # secrets.toml is not needed conn = st.connection( "snowflake", "sql", url="snowflake://user_login_name@account_identifier/", connect_args=dict( authenticator="externalbrowser", warehouse="xxx", role="xxx", ) ) # ... ``` You can also provide both kwargs and secrets.toml values, and they will be merged (typically, kwargs take precedence). ### Connection-building best practices We recommend applying the following best practices to make your Connection consistent with the Connections built into Streamlit and the wider Streamlit ecosystem. These practices are especially important for Connections that you intend to distribute publicly. 1. **Extend existing drivers or SDKs, and default to semantics that makes sense for their existing users.** You should rarely need to implement complex data access logic from scratch when building a Connection. Use existing popular Python drivers and clients whenever possible. Doing so makes your Connection easier to maintain, more secure, and enables users to get the latest features. E.g. [SQLConnection](/develop/api-reference/connections/st.connections.sqlconnection) extends SQLAlchemy, [FileConnection](https://github.com/streamlit/files-connection) extends [fsspec](https://filesystem-spec.readthedocs.io/en/latest/), [GsheetsConnection](https://github.com/streamlit/gsheets-connection) extends [gspread](https://docs.gspread.org/en/latest/), etc. Consider using access patterns, method/argument naming, and return values that are consistent with the underlying package and familiar to existing users of that package. 2. **Intuitive, easy to use read methods.** Much of the power of `st.connection` is providing intuitive, easy-to-use read methods that enable app developers to get started quickly. Most connections should expose at least one read method that is: - Named with a simple verb, like `read()`, `query()`, or `get()` - Wrapped by `st.cache_data` by default, with at least `ttl=` argument supported - If the result is in a tabular format, it returns a pandas DataFrame - Provides commonly used keyword arguments (such as paging or formatting) with sensible defaults - ideally, the common case requires only 1-2 arguments. 3. **Config, secrets, and precedence in `_connect` method.** Every Connection should support commonly used connection parameters provided via Streamlit secrets and keyword arguments. The names should match the ones used when initializing or configuring the underlying package. Additionally, where relevant, Connections should support data source specific configuration through existing standard environment variables or config / credential files. In many cases, the underlying package provides constructors or factory functions that already handle this easily. When you can specify the same connection parameters in multiple places, we recommend using the following precedence order when possible (highest to lowest): - Keyword arguments specified in the code - Streamlit secrets - Data source specific configuration (if relevant) 4. **Handling thread safety and stale connections.** Connections should provide thread-safe operations when practical (which should be most of the time) and clearly document any considerations around this. Most underlying drivers or SDKs should provide thread-safe objects or methods - use these when possible. If the underlying driver or SDK has a risk of stateful connection objects becoming stale or invalid, consider building a low impact health check or reset/retry pattern into the access methods. The SQLConnection built into Streamlit has a good example of this pattern using [tenacity](https://tenacity.readthedocs.io/) and the built-in `Connection.reset()` method. An alternate approach is to encourage developers to set an appropriate TTL on the `st.connection()` call to ensure it periodically reinitializes the connection object. ## Build your own connection Building your own basic connection implementation using an existing driver or SDK is quite straightforward in most cases. However, you can add more complex functionality with further effort. This custom implementation can be a great way to extend support to a new data source and contribute to the Streamlit ecosystem. Maintaining a tailored internal Connection implementation across many apps can be a powerful practice for organizations with frequently used access patterns and data sources. Check out the [Build your own Connection page](https://experimental-connection.streamlit.app/Build_your_own) in the st.experimental connection demo app below for a quick tutorial and working implementation. This demo builds a minimal but very functional Connection on top of DuckDB. ```html ``` The typical steps are: - Declare the Connection class, extending `ExperimentalBaseConnection` with the type parameter bound to the underlying connection object: ```python from streamlit.connections import ExperimentalBaseConnection import duckdb class DuckDBConnection(ExperimentalBaseConnection[duckdb.DuckDBPyConnection]): ``` - Implement the `_connect` method that reads any kwargs, external config/credential locations, and Streamlit secrets to initialize the underlying connection: ```python def _connect(self, **kwargs) -> duckdb.DuckDBPyConnection: if 'database' in kwargs: db = kwargs.pop('database') else: db = self._secrets['database'] return duckdb.connect(database=db, **kwargs) ``` - Add useful helper methods that make sense for your connection (wrapping them in `st.cache_data` where caching is desired): ```python def _cache_data(self, **kwargs): # cache data # ... ``` ## Connection-building best practices We recommend applying the following best practices to make your Connection consistent with the Connections built into Streamlit and the wider Streamlit ecosystem. These practices are especially important for Connections that you intend to distribute publicly. 1. **Extend existing drivers or SDKs, and default to semantics that makes sense for their existing users.** You should rarely need to implement complex data access logic from scratch when building a Connection. Use existing popular Python drivers and clients whenever possible. Doing so makes your Connection easier to maintain, more secure, and enables users to get the latest features. E.g. [SQLConnection](/develop/api-reference/connections/st.connections.sqlconnection) extends SQLAlchemy, [FileConnection](https://github.com/streamlit/files-connection) extends [fsspec](https://filesystem-spec.readthedocs.io/en/latest/), [GsheetsConnection](https://github.com/streamlit/gsheets-connection) extends [gspread](https://docs.gspread.org/en/latest/), etc. Consider using access patterns, method/argument naming, and return values that are consistent with the underlying package and familiar to existing users of that package. 2. **Intuitive, easy to use read methods.** Much of the power of `st.connection` is providing intuitive, easy-to-use read methods that enable app developers to get started quickly. Most connections should expose at least one read method that is: - Named with a simple verb, like `read()`, `query()`, or `get()` - Wrapped by `st.cache_data` by default, with at least `ttl=` argument supported - If the result is in a tabular format, it returns a pandas DataFrame - Provides commonly used keyword arguments (such as paging or formatting) with sensible defaults - ideally, the common case requires only 1-2 arguments. 3. **Config, secrets, and precedence in `_connect` method.** Every Connection should support commonly used connection parameters provided via Streamlit secrets and keyword arguments. The names should match the ones used when initializing or configuring the underlying package. Additionally, where relevant, Connections should support data source specific configuration through existing standard environment variables or config / credential files. In many cases, the underlying package provides constructors or factory functions that already handle this easily. When you can specify the same connection parameters in multiple places, we recommend using the following precedence order when possible (highest to lowest): - Keyword arguments specified in the code - Streamlit secrets - Data source specific configuration (if relevant) 4. **Handling thread safety and stale connections.** Connections should provide thread-safe operations when practical (which should be most of the time) and clearly document any considerations around this. Most underlying drivers or SDKs should provide thread-safe objects or methods - use these when possible. If the underlying driver or SDK has a risk of stateful connection objects becoming stale or invalid, consider building a low impact health check or reset/retry pattern into the access methods. The SQLConnection built into Streamlit has a good example of this pattern using [tenacity](https://tenacity.readthedocs.io/) and the built-in `Connection.reset()` method. An alternate approach is to encourage developers to set an appropriate TTL on the `st.connection()` call to ensure it periodically reinitializes the connection object. ## Build your own connection Building your own basic connection implementation using an existing driver or SDK is quite straightforward in most cases. However, you can add more complex functionality with further effort. This custom implementation can be a great way to extend support to a new data source and contribute to the Streamlit ecosystem. Maintaining a tailored internal Connection implementation across many apps can be a powerful practice for organizations with frequently used access patterns and data sources. Check out the [Build your own Connection page](https://experimental-connection.streamlit.app/Build_your_own) in the st.experimental connection demo app below for a quick tutorial and working implementation. This demo builds a minimal but very functional Connection on top of DuckDB. ```html ``` The typical steps are: - Declare the Connection class, extending `ExperimentalBaseConnection` with the type parameter bound to the underlying connection object: ```python from streamlit.connections import ExperimentalBaseConnection import duckdb class DuckDBConnection(ExperimentalBaseConnection[duckdb.DuckDBPyConnection]): ``` - Implement the `_connect` method that reads any kwargs, external config/credential locations, and Streamlit secrets to initialize the underlying connection: ```python def _connect(self, **kwargs) -> duckdb.DuckDBPyConnection: if 'database' in kwargs: db = kwargs.pop('database') else: db = self._secrets['database'] return duckdb.connect(database=db, **kwargs) ``` - Add useful helper methods that make sense for your connection (wrapping them in `st.cache_data` where caching is desired): ```python def _cache_data(self, **kwargs): # cache data # ... ``` ## Connection-building best practices We recommend applying the following best practices to make your Connection consistent with the Connections built into Streamlit and the wider Streamlit ecosystem. These practices are especially important for Connections that you intend to distribute publicly. 1. **Extend existing drivers or SDKs, and default to semantics that makes sense for their existing users.** You should rarely need to implement complex data access logic from scratch when building a Connection. Use existing popular Python drivers and clients whenever possible. Doing so makes your Connection easier to maintain, more secure, and enables users to get the latest features. E.g. [SQLConnection](/develop/api-reference/connections/st.connections.sqlconnection) extends SQLAlchemy, [FileConnection](https://github.com/streamlit/files-connection) extends [fsspec](https://filesystem-spec.readthedocs.io/en/latest/), [GsheetsConnection](https://github.com/streamlit/gsheets-connection) extends [gspread](https://docs.gspread.org/en/latest/), etc. Consider using access patterns, method/argument naming, and return values that are consistent with the underlying package and familiar to existing users of that package. 2. **Intuitive, easy to use read methods.** Much of the power of `st.connection` is providing intuitive, easy-to-use read methods that enable app developers to get started quickly. Most connections should expose at least one read method that is: - Named with a simple verb, like `read()`, `query()`, or `get()` - Wrapped by `st.cache_data` by default, with at least `ttl=` argument supported - If the result is in a tabular format, it returns a pandas DataFrame - Provides commonly used keyword arguments (such as paging or formatting) with sensible defaults - ideally, the common case requires only 1-2 arguments. 3. **Config, secrets, and precedence in `_connect` method.** Every Connection should support commonly used connection parameters provided via Streamlit secrets and keyword arguments. The names should match the ones used when initializing or configuring the underlying package. Additionally, where relevant, Connections should support data source specific configuration through existing standard environment variables or config / credential files. In many cases, the underlying package provides constructors or factory functions that already handle this easily. When you can specify the same connection parameters in multiple places, we recommend using the following precedence order when possible (highest to lowest): - Keyword arguments specified in the code - Streamlit secrets - Data source specific configuration (if relevant) 4. **Handling thread safety and stale connections.** Connections should provide thread-safe operations when practical (which should be most of the time) and clearly document any considerations around this. Most underlying drivers or SDKs should provide thread-safe objects or methods - use these when possible. If the underlying driver or SDK has a risk of stateful connection objects becoming stale or invalid, consider building a low impact health check or reset/retry pattern into the access methods. The SQLConnection built into Streamlit has a good example of this pattern using [tenacity](https://tenacity.readthedocs.io/) and the built-in `Connection.reset()` method. An alternate approach is to encourage developers to set an appropriate TTL on the `st.connection()` call to ensure it periodically reinitializes the connection object. ## Build your own connection Building your own basic connection implementation using an existing driver or SDK is quite straightforward in most cases. However, you can add more complex functionality with further effort. This custom implementation can be a great way to extend support to a new data source and contribute to the Streamlit ecosystem. Maintaining a tailored internal Connection implementation across many apps can be a powerful practice for organizations with frequently used access patterns and data sources. Check out the [Build your own Connection page](https://experimental-connection.streamlit.app/Build_your_own) in the st.experimental connection demo app below for a quick tutorial and working implementation. This demo builds a minimal but very functional Connection on top of DuckDB. ```html ``` The typical steps are: - Declare the Connection class, extending `ExperimentalBaseConnection` with the type parameter bound to the underlying connection object: ```python from streamlit.connections import ExperimentalBaseConnection import duckdb class DuckDBConnection(ExperimentalBaseConnection[duckdb.DuckDBPyConnection]): ``` - Implement the `_connect` method that reads any kwargs, external config/credential locations, and Streamlit secrets to initialize the underlying connection: ```python def _connect(self, **kwargs) -> duckdb.DuckDBPyConnection: if 'database' in kwargs: db = kwargs.pop('database') else: db = self._secrets['database'] return duckdb.connect(database=db, **kwargs) ``` - Add useful helper methods that make sense for your connection (wrapping them in `st.cache_data` where caching is desired): ```python def _cache_data(self, **kwargs): # cache data # ... ``` ## Connection-building best practices We recommend applying the following best practices to make your Connection consistent with the Connections built into Streamlit and the wider Streamlit ecosystem. These practices are especially important for Connections that you intend to distribute publicly. 1. **Extend existing drivers or SDKs, and default to semantics that makes sense for their existing users.** You should rarely need to implement complex data access logic from scratch when building a Connection. Use existing popular Python drivers and clients whenever possible. Doing so makes your Connection easier to maintain, more secure, and enables users to get the latest features. E.g. [SQLConnection](/develop/api-reference/connections/st.connections.sqlconnection) extends SQLAlchemy, [FileConnection](https://github.com/streamlit/files-connection) extends [fsspec](https://filesystem-spec.readthedocs.io/en/latest/), [GsheetsConnection](https://github.com/streamlit/gsheets-connection) extends [gspread](https://docs.gspread.org/en/latest/), etc. Consider using access patterns, method/argument naming, and return values that are consistent with the underlying package and familiar to existing users of that package. 2. **Intuitive, easy to use read methods.** Much of the power of `st.connection` is providing intuitive, easy-to-use read methods that enable app developers to get started quickly. Most connections should expose at least one read method that is: - Named with a simple verb, like `read()`, `query()`, or `get()` - Wrapped by `st.cache_data` by default, with at least `ttl=` argument supported - If the result is in a tabular format, it returns a pandas DataFrame - Provides commonly used keyword arguments (such as paging or formatting) with sensible defaults - ideally, the common case requires only 1-2 arguments. 3. **Config, secrets, and precedence in `_connect` method.** Every Connection should support commonly used connection parameters provided via Streamlit secrets and keyword arguments. The names should match the ones used when initializing or configuring the underlying package. Additionally, where relevant, Connections should support data source specific configuration through existing standard environment variables or config / credential files. In many cases, the underlying package provides constructors or factory functions that already handle this easily. When you can specify the same connection parameters in multiple places, we recommend using the following precedence order when possible (highest to lowest): - Keyword arguments specified in the code - Streamlit secrets - Data source specific configuration (if relevant) 4. **Handling thread safety and stale connections.** Connections should provide thread-safe operations when practical (which should be most of the time) and clearly document any considerations around this. Most underlying drivers or SDKs should provide thread-safe objects or methods - use these when possible. If the underlying driver or SDK has a risk of stateful connection objects becoming stale or invalid, consider building a low impact health check or reset/retry pattern into the access methods. The SQLConnection built into Streamlit has a good example of this pattern using [tenacity](https://tenacity.readthedocs.io/) and the built-in `Connection.reset()` method. An alternate approach is to encourage developers to set an appropriate TTL on the `st.connection()` call to ensure it periodically reinitializes the connection object. ## Build your own connection Building your own basic connection implementation using an existing driver or SDK is quite straightforward in most cases. However, you can add more complex functionality with further effort. This custom implementation can be a great way to extend support to a new data source and contribute to the Streamlit ecosystem. Maintaining a tailored internal Connection implementation across many apps can be a powerful practice for organizations with frequently used access patterns and data sources. Check out the [Build your own Connection page](https://experimental-connection.streamlit.app/Build_your_own) in the st.experimental connection demo app below for a quick tutorial and working implementation. This demo builds a minimal but very functional Connection on top of DuckDB. ```html ``` The typical steps are: - Declare the Connection class, extending `ExperimentalBaseConnection` with the type parameter bound to the underlying connection object: ```python from streamlit.connections import ExperimentalBaseConnection import duckdb class DuckDBConnection(ExperimentalBaseConnection[duckdb.DuckDBPyConnection]): ``` - Implement the `_connect` method that reads any kwargs, external config/credential locations, and Streamlit secrets to initialize the underlying connection: ```python def _connect(self, **kwargs) -> duckdb.DuckDBPyConnection: if 'database' in kwargs: db = kwargs.pop('database') else: db = self._secrets['database'] return duckdb.connect(database=db, **kwargs) ``` - Add useful helper methods that make sense for your connection (wrapping them in `st.cache_data` where caching is desired): ```python def _cache_data(self, **kwargs): # cache data # ... ``` ## Connection-building best practices We recommend applying the following best practices to make your Connection consistent with the Connections built into Streamlit and the wider Streamlit ecosystem. These practices are especially important for Connections that you intend to distribute publicly. 1. **Extend existing drivers or SDKs, and default to semantics that makes sense for their existing users.** You should rarely need to implement complex data access logic from scratch when building a Connection. Use existing popular Python drivers and clients whenever possible. Doing so makes your Connection easier to maintain, more secure, and enables users to get the latest features. E.g. [SQLConnection](/develop/api-reference/connections/st.connections.sqlconnection) extends SQLAlchemy, [FileConnection](https://github.com/streamlit/files-connection) extends [fsspec](https://filesystem-spec.readthedocs.io/en/latest/), [GsheetsConnection](https://github.com/streamlit/gsheets-connection) extends [gspread](https://docs.gspread.org/en/latest/), etc. Consider using access patterns, method/argument naming, and return values that are consistent with the underlying package and familiar to existing users of that package. 2. **Intuitive, easy to use read methods.** Much of the power of `st.connection` is providing intuitive, easy-to-use read methods that enable app developers to get started quickly. Most connections should expose at least one read method that is: - Named with a simple verb, like `read()`, `query()`, or `get()` - Wrapped by `st.cache_data` by default, with at least `ttl=` argument supported - If the result is in a tabular format, it returns a pandas DataFrame - Provides commonly used keyword arguments (such as paging or formatting) with sensible defaults - ideally, the common case requires only 1-2 arguments. 3. **Config, secrets, and precedence in `_connect` method.** Every Connection should support commonly used connection parameters provided via Streamlit secrets and keyword arguments. The names should match the ones used when initializing or configuring the underlying package. Additionally, where relevant, Connections should support data source specific configuration through existing standard environment variables or config / credential files. In many cases, the underlying package provides constructors or factory functions that already handle this easily. When you can specify the same connection parameters in multiple places, we recommend using the following precedence order when possible (highest to lowest): - Keyword arguments specified in the code - Streamlit secrets - Data source specific configuration (if relevant) 4. **Handling thread safety and stale connections.** Connections should provide thread-safe operations when practical (which should be most of the time) and clearly document any considerations around this. Most underlying drivers or SDKs should provide thread-safe objects or methods - use these when possible. If the underlying driver or SDK has a risk of stateful connection objects becoming stale or invalid, consider building a low impact health check or reset/retry pattern into the access methods. The SQLConnection built into Streamlit has a good example of this pattern using [tenacity](https://tenacity.readthedocs.io/) and the built-in `Connection.reset()` method. An alternate approach is to encourage developers to set an appropriate TTL on the `st.connection()` call to ensure it periodically reinitializes the connection object. ## Build your own connection Building your own basic connection implementation using an existing driver or SDK is quite straightforward in most cases. However, you can add more complex functionality with further effort. This custom implementation can be a great way to extend support to a new data source and contribute to the Streamlit ecosystem. Maintaining a tailored internal Connection implementation across many apps can be a powerful practice for organizations with frequently used access patterns and data sources. Check out the [Build your own Connection page](https://experimental-connection.streamlit.app/Build_your_own) in the st.experimental connection demo app below for a quick tutorial and working implementation. This demo builds a minimal but very functional Connection on top of DuckDB. ```html ``` The typical steps are: - Declare the Connection class, extending `ExperimentalBaseConnection` with the type parameter bound to the underlying connection object: ```python from streamlit.connections import ExperimentalBaseConnection import duckdb class DuckDBConnection(ExperimentalBaseConnection[duckdb.DuckDBPyConnection]): ``` - Implement the `_connect` method that reads any kwargs, external config/credential locations, and Streamlit secrets to initialize the underlying connection: ```python def _connect(self, **kwargs) -> duckdb.DuckDBPyConnection: if 'database' in kwargs: db = kwargs.pop('database') else: db = self._secrets['database'] return duckdb.connect(database=db, **kwargs) ``` - Add useful helper methods that make sense for your connection (wrapping them in `st.cache_data` where caching is desired): ```python def _cache_data(self, **kwargs): # cache data # ... ``` ## Connection-building best practices We recommend applying the following best practices to make your Connection consistent with the Connections built into Streamlit and the wider Streamlit ecosystem. These practices are especially important for Connections that you intend to distribute publicly. 1. **Extend existing drivers or SDKs, and default to semantics that makes sense for their existing users.** You should rarely need to implement complex data access logic from scratch when building a Connection. Use existing popular Python drivers and clients whenever possible. Doing so makes your Connection easier to maintain, more secure, and enables users to get the latest features. E.g. [SQLConnection](/develop/api-reference/connections/st.connections.sqlconnection) extends SQLAlchemy, [FileConnection](https://github.com/streamlit/files-connection) extends [fsspec](https://filesystem-spec.readthedocs.io/en/latest/), [GsheetsConnection](https://github.com/streamlit/gsheets-connection) extends [gspread](https://docs.gspread.org/en/latest/), etc. Consider using access patterns, method/argument naming, and return values that are consistent with the underlying package and familiar to existing users of that package. 2. **Intuitive, easy to use read methods.** Much of the power of `st.connection` is providing intuitive, easy-to-use read methods that enable app developers to get started quickly. Most connections should expose at least one read method that is: - Named with a simple verb, like `read()`, `query()`, or `get()` - Wrapped by `st.cache_data` by default, with at least `ttl=` argument supported - If the result is in a tabular format, it returns a pandas DataFrame - Provides commonly used keyword arguments (such as paging or formatting) with sensible defaults - ideally, the common case requires only 1-2 arguments. 3. **Config, secrets, and precedence in `_connect` method.** Every Connection should support commonly used connection parameters provided via Streamlit secrets and keyword arguments. The names should match the ones used when initializing or configuring the underlying package. Additionally, where relevant, Connections should support data source specific configuration through existing standard environment variables or config / credential files. In many cases, the underlying package provides constructors or factory functions that already handle this easily. When you can specify the same connection parameters in multiple places, we recommend using the following precedence order when possible (highest to lowest): - Keyword arguments specified in the code - Streamlit secrets - Data source specific configuration (if relevant) 4. **Handling thread safety and stale connections.** Connections should provide thread-safe operations when practical (which should be most of the time) and clearly document any considerations around this. Most underlying drivers or SDKs should provide thread-safe objects or methods - use these when possible. If the underlying driver or SDK has a risk of stateful connection objects becoming stale or invalid, consider building a low impact health check or reset/retry pattern into the access methods. The SQLConnection built into Streamlit has a good example of this pattern using [tenacity](https://tenacity.readthedocs.io/) and the built-in `Connection.reset()` method. An alternate approach is to encourage developers to set an appropriate TTL on the `st.connection()` call to ensure it periodically reinitializes the connection object. ## Build your own connection Building your own basic connection implementation using an existing driver or SDK is quite straightforward in most cases. However, you can add more complex functionality with further effort. This custom implementation can be a great way to extend support to a new data source and contribute to the Streamlit ecosystem. Maintaining a tailored internal Connection implementation across many apps can be a powerful practice for organizations with frequently used access patterns and data sources. Check out the [Build your own Connection page](https://experimental-connection.streamlit.app/Build_your_own) in the st.experimental connection demo app below for a quick tutorial and working implementation. This demo builds a minimal but very functional Connection on top of DuckDB. ```html ``` The typical steps are: - Declare the Connection class, extending `ExperimentalBaseConnection` with the type parameter bound to the underlying connection object: ```python from streamlit.connections import ExperimentalBaseConnection import duckdb class DuckDBConnection(ExperimentalBaseConnection[duckdb.DuckDBPyConnection]): ``` - Implement the `_connect` method that reads any kwargs, external config/credential locations, and Streamlit secrets to initialize the underlying connection: ```python def _connect(self, **kwargs) -> duckdb.DuckDBPyConnection: if 'database' in kwargs: db = kwargs.pop('database') else: db = self._secrets['database'] return duckdb.connect(database=db, **kwargs) ``` - Add useful helper methods that make sense for your connection (wrapping them in `st.cache_data` where caching is desired): ```python def _cache_data(self, **kwargs): # cache data # ... ``` ## Connection-building best practices We recommend applying the following best practices to make your Connection consistent with the Connections built into Streamlit and the wider Streamlit ecosystem. These practices are especially important for Connections that you intend to distribute publicly. 1. **Extend existing drivers or SDKs, and default to semantics that makes sense for their existing users.** You should rarely need to implement complex data access logic from scratch when building a Connection. Use existing popular Python drivers and clients whenever possible. Doing so makes your Connection easier to maintain, more secure, and enables users to get the latest features. E.g. [SQLConnection](/develop/api-reference/connections/st.connections.sqlconnection) extends SQLAlchemy, [FileConnection](https://github.com/streamlit/files-connection) extends [fsspec](https://filesystem-spec.readthedocs.io/en/latest/), [GsheetsConnection](https://github.com/streamlit/gsheets-connection) extends [gspread](https://docs.gspread.org/en/latest/), etc. Consider using access patterns, method/argument naming, and return values that are consistent with the underlying package and familiar to existing users of that package. 2. **Intuitive, easy to use read methods.** Much of the power of `st.connection` is providing intuitive, easy-to-use read methods that enable app developers to get started quickly. Most connections should expose at least one read method that is: - Named with a simple verb, like `read()`, `query()`, or `get()` - Wrapped by `st.cache_data` by default, with at least `ttl=` argument supported - If the result is in a tabular format, it returns a pandas DataFrame - Provides commonly used keyword arguments (such as paging or formatting) with sensible defaults - ideally, the common case requires only 1-2 arguments. 3. **Config, secrets, and precedence in `_connect` method.** Every Connection should support commonly used connection parameters provided via Streamlit secrets and keyword arguments. The names should match the ones used when initializing or configuring the underlying package. Additionally, where relevant, Connections should support data source specific configuration through existing standard environment variables or config / credential files. In many cases, the underlying package provides constructors or factory functions that already handle this easily. When you can specify the same connection parameters in multiple places, we recommend using the following precedence order when possible (highest to lowest): - Keyword arguments specified in the code - Streamlit secrets - Data source specific configuration (if relevant) 4. **Handling thread safety and stale connections.** Connections should provide thread-safe operations when practical (which should be most of the time) and clearly document any considerations around this. Most underlying drivers or SDKs should provide thread-safe objects or methods - use these when possible. If the underlying driver or SDK has a risk of stateful connection objects --- # Source: https://docs.streamlit.io/develop/api-reference/connections # Source: https://docs.streamlit.io/develop/concepts/connections # Working with connections, secrets, and user authentication ## Connecting to data Connect your app to remote data or a third-party API. ## Secrets management Set up your development environment and design your app to handle secrets securely. ## User authentication Use an OpenID Connect provider to authenticate users and personalize your app. ## Security reminders Check out a few reminders to follow best practices and avoid security mistakes. ## Previous: App design [Previous: App design](/develop/concepts/design) ## Next: Connecting to data [Next: Connecting to data](/develop/concepts/connections/connecting-to-data) ## Forum ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ## Navigation * [Home](/) * [Get started](/get-started) * [Installation](/get-started/installation) * [Fundamentals](/get-started/fundamentals) * [Core](/get-started/concepts/architecture) * [Architecture and execution](/get-started/concepts/architecture) * [Multipage apps](/get-started/concepts/multipage-apps) * [App design](/get-started/concepts/design) * [Additional features](/get-started/concepts/advanced-concepts) * [Summary](/get-started/concepts/summary) * [First steps](/get-started/tutorials) * [Create an app](/get-started/tutorials/create-an-app) * [Create a multipage app](/get-started/tutorials/create-a-multipage-app) * [Develop](/develop) * [Concepts](/develop/concepts) * [CORE](/develop/concepts/concepts/core) * [Architecture and execution](/develop/concepts/concepts/architecture) * [Multipage apps](/develop/concepts/concepts/multipage-apps) * [App design](/develop/concepts/concepts/app-design) * [ADDITIONAL](/develop/concepts/concepts/additional-features) * [Connections, secrets, and authentication](/develop/concepts/concepts/connections) * [Connecting to data](/develop/concepts/concepts/connections/connecting-to-data) * [Secrets management](/develop/concepts/concepts/connections/secrets-management) * [User authentication](/develop/concepts/concepts/connections/authentication) * [Security reminders](/develop/concepts/concepts/connections/security-reminders) * [Custom components](/develop/concepts/concepts/custom-components) * [Intro to custom components](/develop/concepts/concepts/custom-components/intro) * [Create a Component](/develop/concepts/concepts/custom-components/create) * [Publish a Component](/develop/concepts/concepts/custom-components/publish) * [Limitations](/develop/concepts/concepts/custom-components/limitations) * [Component gallery](https://streamlit.io/components) * [Configuration and theming](/develop/concepts/concepts/configuration) * [Configuration options](/develop/concepts/concepts/configuration/options) * [HTTPS support](/develop/concepts/concepts/configuration/https-support) * [Serving static files](/develop/concepts/concepts/configuration/serving-static-files) * [THEMING](/develop/concepts/concepts/configuration/theming) * [Customize your theme](/develop/concepts/concepts/configuration/theming-customize-colors-and-borders) * [Customize fonts](/develop/concepts/concepts/configuration/theming-customize-fonts) * [App testing](/develop/concepts/concepts/app-testing) * [Get started](/develop/concepts/concepts/app-testing/get-started) * [Beyond the basics](/develop/concepts/concepts/app-testing/beyond-the-basics) * [Automate your tests](/develop/concepts/concepts/app-testing/automate-tests) * [Example](/develop/concepts/concepts/app-testing/examples) * [Cheat sheet](/develop/concepts/concepts/app-testing/cheat-sheet) * [API reference](/develop/concepts/concepts/api-reference) * [Tutorials](/develop/concepts/concepts/tutorials) * [Quick reference](/develop/concepts/concepts/quick-reference) * [Deploy](/deploy) * [Concepts](/develop/concepts/concepts/dependencies) * [Streamlit Community Cloud](/develop/concepts/concepts/streamlit-community-cloud) * [Snowflake](/develop/concepts/concepts/snowflake) * [Other platforms](/develop/concepts/concepts/tutorials) * [Knowledge base](/knowledge-base) * [FAQ](/knowledge-base/using-streamlit) * [Installing dependencies](/knowledge-base/dependencies) * [Deployment issues](/knowledge-base/deploy) --- # Source: https://docs.streamlit.io/get-started/tutorials/create-a-multipage-app # Create a multipage app In [Additional features](/get-started/fundamentals/additional-features), we introduced multipage apps, including how to define pages, structure and run multipage apps, and navigate between pages in the user interface. You can read more details in our guide to [Multipage apps](/develop/concepts/multipage-apps). In this guide, let’s put our understanding of multipage apps to use by converting the previous version of our `streamlit hello` app to a multipage app! ## Motivation Before Streamlit 1.10.0, the `streamlit hello` command was a large single-page app. As there was no support for multiple pages, we resorted to splitting the app's content using `st.selectbox` in the sidebar to choose what content to run. The content is comprised of three demos for plotting, mapping, and dataframes. Here's what the code and single-page app looked like: ```python import streamlit as st def intro(): import streamlit as st st.write("# Welcome to Streamlit! 👋") st.sidebar.success("Select a demo above.") st.markdown( "Streamlit is an open-source app framework built specifically for Machine Learning and Data Science projects. **👈 Select a demo from the dropdown on the left** to see some examples of what Streamlit can do! ### Want to learn more? - Check out [streamlit.io](https://streamlit.io) - Jump into our [documentation](https://docs.streamlit.io) - Ask a question in our [community forums](https://discuss.streamlit.io) ### See more complex demos - Use a neural net to [analyze the Udacity Self-driving Car Image Dataset](https://github.com/streamlit/demo-self-driving) - Explore a [New York City rideshare dataset](https://github.com/streamlit/demo-uber-nyc-pickups)" ) def mapping_demo(): import streamlit as st import pandas as pd import pydeck as pdk from urllib.error import URLError st.markdown(f"# {list(page_names_to_funcs.keys())[2]}") st.write( "This demo shows how to use [`st.pydeck_chart`](https://docs.streamlit.io/develop/api-reference/charts/st.pydeck_chart) to display geospatial data." ) @st.cache_data def from_data_file(filename): url = ( "http://raw.githubusercontent.com/streamlit/" "example-data/master/hello/v1/%s" % filename ) return pd.read_json(url) try: ALL_LAYERS = { "Bike Rentals": pdk.Layer( "HexagonLayer", data=from_data_file("bike_rental_stats.json"), get_position=["lon", "lat"], radius=200, elevation_scale=4, elevation_range=[0, 1000], extruded=True, ), "Bart Stop Exits": pdk.Layer( "ScatterplotLayer", data=from_data_file("bart_stop_stats.json"), get_position=["lon", "lat"], get_color=[200, 30, 0, 160], get_radius="[exits]", radius_scale=0.05, ), "Bart Stop Names": pdk.Layer( "TextLayer", data=from_data_file("bart_stop_stats.json"), get_position=["lon", "lat"], get_text="name", get_color=[0, 0, 0, 200], get_size=15, get_alignment_baseline="'bottom'", ), "Outbound Flow": pdk.Layer( "ArcLayer", data=from_data_file("bart_path_stats.json"), get_source_position=["lon", "lat"], get_target_position=["lon2", "lat2"], get_source_color=[200, 30, 0, 160], get_target_color=[200, 30, 0, 160], auto_highlight=True, width_scale=0.0001, get_width="outbound", width_min_pixels=3, width_max_pixels=30, ), } st.sidebar.markdown("### Map Layers") selected_layers = [ layer for layer_name, layer in ALL_LAYERS.items() if st.sidebar.checkbox(layer_name, True) ] if selected_layers: st.pydeck_chart( pdk.Deck( map_style="mapbox://styles/mapbox/light-v9", initial_view_state={ "latitude": 37.76, "longitude": -122.4, "zoom": 11, "pitch": 50, }, layers=selected_layers, ) ) else: st.error("Please choose at least one layer above.") except URLError as e: st.error( "**This demo requires internet access.** Connection error: %s %s" % e.reason ) def plotting_demo(): import streamlit as st import time import numpy as np st.markdown(f"# {list(page_names_to_funcs.keys())[1]}") st.write( "This demo illustrates a combination of plotting and animation with Streamlit. We're generating a bunch of random numbers in a loop for around 5 seconds. Enjoy!" ) progress_bar = st.sidebar.progress(0) status_text = st.sidebar.empty() last_rows = np.random.randn(1, 1) chart = st.line_chart(last_rows) for i in range(1, 101): new_rows = last_rows[-1, :] + np.random.randn(5, 1).cumsum(axis=0) status_text.text("%i%% Complete" % i) chart.add_rows(new_rows) progress_bar.progress(i) last_rows = new_rows time.sleep(0.05) progress_bar.empty() # Streamlit widgets automatically run the script from top to bottom. Since # this button is not connected to any other logic, it just causes a plain # rerun. st.button("Re-run") def data_frame_demo(): import streamlit as st import pandas as pd import altair as alt from urllib.error import URLError st.markdown(f"# {list(page_names_to_funcs.keys())[3]}") st.write( "This demo shows how to use `st.write` to visualize Pandas DataFrames. (Data courtesy of the [UN Data Explorer](http://data.un.org/Explorer.aspx).)" ) @st.cache_data def get_UN_data(): AWS_BUCKET_URL = "http://streamlit-demo-data.s3-us-west-2.amazonaws.com" df = pd.read_csv(AWS_BUCKET_URL + "/agri.csv.gz") return df.set_index("Region") try: df = get_UN_data() countries = st.multiselect( "Choose countries", list(df.index), ["China", "United States of America"] ) if not countries: st.error("Please select at least one country.") else: data = df.loc[countries] data /= 1000000.0 st.write("### Gross Agricultural Production ($B)", data.sort_index()) data = data.T.reset_index() data = pd.melt(data, id_vars=["index"]).rename( columns={"index": "year", "value": "Gross Agricultural Product ($B)"} ) chart = ( alt.Chart(data) .mark_area(opacity=0.3) .encode( x="year:T", y=alt.Y("Gross Agricultural Product ($B):Q", stack=None), color="Region:N", ) ) st.altair_chart(chart, use_container_width=True) except URLError as e: st.error( "**This demo requires internet access.** Connection error: %s %s" % e.reason ) page_names_to_funcs = { "--": intro, "Plotting Demo": plotting_demo, "Mapping Demo": mapping_demo, "DataFrame Demo": data_frame_demo } demo_name = st.sidebar.selectbox("Choose a demo", page_names_to_funcs.keys()) page_names_to_funcs[demo_name]() ``` Notice how large the file is! Each app “page” is written as a function, and the selectbox is used to pick which page to display. As our app grows, maintaining the code requires a lot of additional overhead. Moreover, we’re limited by the `st.selectbox` UI to choose which “page” to run, we cannot customize individual page titles with `st.set_page_config`, and we’re unable to navigate between pages using URLs. ## Convert an existing app into a multipage app Now that we've identified the limitations of a single-page app, what can we do about it? Armed with our knowledge from the previous section, we can convert the existing app to be a multipage app, of course! At a high level, we need to perform the following steps: 1. Create a new `pages` folder in the same folder where the “entrypoint file” (e.g., `hello.py`) lives. 2. Rename our entrypoint file to `Hello.py`, so that the title in the sidebar is capitalized. 3. Create three new files inside of `pages`: `pages/1_📈_Plotting_Demo.py`, `pages/2_🌍_Mapping_Demo.py`, and `pages/3_📊_DataFrame_Demo.py`. 4. Move the contents of the `plotting_demo`, `mapping_demo`, and `data_frame_demo` functions into their corresponding new files from Step 3. 5. Run `streamlit run Hello.py` to view your newly converted multipage app! Now, let’s walk through each step of the process and view the corresponding changes in code. ### Create the entrypoint file ```python import streamlit as st st.set_page_config( page_title="Hello", page_icon="👋", ) st.write("# Welcome to Streamlit! 👋") st.sidebar.success("Select a demo above.") st.markdown( "Streamlit is an open-source app framework built specifically for Machine Learning and Data Science projects. **👈 Select a demo from the sidebar** to see some examples of what Streamlit can do! ### Want to learn more? - Check out [streamlit.io](https://streamlit.io) - Jump into our [documentation](https://docs.streamlit.io) - Ask a question in our [community forums](https://discuss.streamlit.io) ### See more complex demos - Use a neural net to [analyze the Udacity Self-driving Car Image Dataset](https://github.com/streamlit/demo-self-driving) - Explore a [New York City rideshare dataset](https://github.com/streamlit/demo-uber-nyc-pickups)" ) ``` We rename our entrypoint file to `Hello.py`, so that the title in the sidebar is capitalized and only the code for the intro page is included. Additionally, we’re able to customize the page title and favicon — as it appears in the browser tab with `st.set_page_config`. Notice how the sidebar does not contain page labels as we haven’t created any pages yet. ### Create multiple pages A few things to remember here: 1. We can change the ordering of pages in our MPA by adding numbers to the beginning of each Python file. If we add a 1 to the front of our file name, Streamlit will put that file first in the list. 2. The name of each Streamlit app is determined by the file name, so to change the app name you need to change the file name! 3. We can add some fun to our app by adding emojis to our file names that will render in our Streamlit app. 4. Each page will have its own URL, defined by the name of the file. Check out how we do all this below! For each new page, we create a new file inside the pages folder, and add the appropriate demo code into it. ```python import streamlit as st st.set_page_config(page_title="Plotting Demo", page_icon="📈") st.markdown("This demo illustrates a combination of plotting and animation with Streamlit. We're generating a bunch of random numbers in a loop for around 5 seconds. Enjoy!") progress_bar = st.sidebar.progress(0) status_text = st.sidebar.empty() last_rows = np.random.randn(1, 1) chart = st.line_chart(last_rows) for i in range(1, 101): new_rows = last_rows[-1, :] + np.random.randn(5, 1).cumsum(axis=0) status_text.text("%i%% Complete" % i) chart.add_rows(new_rows) progress_bar.progress(i) last_rows = new_rows time.sleep(0.05) progress_bar.empty() # Streamlit widgets automatically run the script from top to bottom. Since # this button is not connected to any other logic, it just causes a plain # rerun. st.button("Re-run") ``` ```python import streamlit as st st.set_page_config(page_title="Mapping Demo", page_icon="🌍") st.markdown("This demo shows how to use `st.pydeck_chart` to display geospatial data.") @st.cache_data def from_data_file(filename): url = ( "http://raw.githubusercontent.com/streamlit/" "example-data/master/hello/v1/%s" % filename ) return pd.read_json(url) try: ALL_LAYERS = { "Bike Rentals": pdk.Layer( "HexagonLayer", data=from_data_file("bike_rental_stats.json"), get_position=["lon", "lat"], radius=200, elevation_scale=4, elevation_range=[0, 1000], extruded=True, ), "Bart Stop Exits": pdk.Layer( "ScatterplotLayer", data=from_data_file("bart_stop_stats.json"), get_position=["lon", "lat"], get_color=[200, 30, 0, 160], get_radius="[exits]", radius_scale=0.05, ), "Bart Stop Names": pdk.Layer( "TextLayer", data=from_data_file("bart_stop_stats.json"), get_position=["lon", "lat"], get_text="name", get_color=[0, 0, 0, 200], get_size=15, get_alignment_baseline="'bottom'", ), "Outbound Flow": pdk.Layer( "ArcLayer", data=from_data_file("bart_path_stats.json"), get_source_position=["lon", "lat"], get_target_position=["lon2", "lat2"], get_source_color=[200, 30, 0, 160], get_target_color=[200, 30, 0, 160], auto_highlight=True, width_scale=0.0001, get_width="outbound", width_min_pixels=3, width_max_pixels=30, ), } st.sidebar.markdown("### Map Layers") selected_layers = [ layer for layer_name, layer in ALL_LAYERS.items() if st.sidebar.checkbox(layer_name, True) ] if selected_layers: st.pydeck_chart( pdk.Deck( map_style="mapbox://styles/mapbox/light-v9", initial_view_state={ "latitude": 37.76, "longitude": -122.4, "zoom": 11, "pitch": 50, }, layers=selected_layers, ) ) else: st.error("Please choose at least one layer above.") except URLError as e: st.error( "**This demo requires internet access.** Connection error: %s %s" % e.reason ) ``` ```python import streamlit as st st.set_page_config(page_title="DataFrame Demo", page_icon="📊") st.markdown("This demo shows how to use `st.write` to visualize Pandas DataFrames. (Data courtesy of the [UN Data Explorer](http://data.un.org/Explorer.aspx).)") @st.cache_data def get_UN_data(): AWS_BUCKET_URL = "http://streamlit-demo-data.s3-us-west-2.amazonaws.com" df = pd.read_csv(AWS_BUCKET_URL + "/agri.csv.gz") return df.set_index("Region") try: df = get_UN_data() countries = st.multiselect( "Choose countries", list(df.index), ["China", "United States of America"] ) if not countries: st.error("Please select at least one country.") else: data = df.loc[countries] data /= 1000000.0 st.write("### Gross Agricultural Production ($B)", data.sort_index()) data = data.T.reset_index() data = pd.melt(data, id_vars=["index"]).rename( columns={"index": "year", "value": "Gross Agricultural Product ($B)"} ) chart = ( alt.Chart(data) .mark_area(opacity=0.3) .encode( x="year:T", y=alt.Y("Gross Agricultural Product ($B):Q", stack=None), color="Region:N", ) ) st.altair_chart(chart, use_container_width=True) except URLError as e: st.error( "**This demo requires internet access.** Connection error: %s %s" % e.reason ) ``` With our additional pages created, we can now put it all together in the final step below. ### Run the multipage app To run your newly converted multipage app, run: ```bash streamlit run Hello.py ``` That’s it! The `Hello.py` script now corresponds to the main page of your app, and other scripts that Streamlit finds in the pages folder will also be present in the new page selector that appears in the sidebar. ## Next steps Congratulations! 🎉 If you've read this far, chances are you've learned to create both single-page and multipage apps. Where you go from here is entirely up to your creativity! We’re excited to see what you’ll build now that adding additional pages to your apps is easier than ever. Try adding more pages to the app we've just built as an exercise. Also, stop by the forum to show off your multipage apps with the Streamlit community! 🎈 Here are a few resources to help you get started: - Deploy your app for free on Streamlit's [Community Cloud](/deploy/streamlit-community-cloud). - Post a question or share your multipage app on our [community forum](https://discuss.streamlit.io/c/streamlit-examples/9). - Check out our documentation on [Multipage apps](/develop/concepts/multipage-apps). - Read through [Concepts](/develop/concepts) for things like caching, theming, and adding statefulness to apps. - Browse our [API reference](/develop/api-reference) for examples of every Streamlit command. --- # Source: https://docs.streamlit.io/develop/tutorials/execution-flow/create-a-multiple-container-fragment # Create a fragment across multiple containers Streamlit lets you turn functions into [fragments](https://docs.streamlit.io/develop/concepts/architecture/fragments), which can rerun independently from the full script. If your fragment doesn't write to outside containers, Streamlit will clear and redraw all the fragment elements with each fragment rerun. However, if your fragment _does_ write elements to outside containers, Streamlit will not clear those elements during a fragment rerun. Instead, those elements accumulate with each fragment rerun until the next full-script rerun. If you want a fragment to update multiple containers in your app, use `st.empty()` containers to prevent accumulating elements. ## Initialize your app 1. In `your_repository`, create a file named `app.py`. 2. In a terminal, change directories to `your_repository`, and start your app: ```bash streamlit run app.py ``` Your app will be blank because you still need to add code. 3. In `app.py`, write the following: ```python import streamlit as st import time st.title("Cats!") row1 = st.columns(3) row2 = st.columns(3) grid = [col.container(height=200) for col in row1 + row2] safe_grid = [card.empty() for card in grid] def black_cats(): time.sleep(1) st.title("🐈‍⬛ 🐈‍⬛") st.markdown("🐾 🐾 🐾 🐾") def orange_cats(): time.sleep(1) st.title("🐈 🐈") st.markdown("🐾 🐾 🐾 🐾") @st.fragment def herd_black_cats(card_a, card_b, card_c): st.button("Herd the black cats") container_a = card_a.container() container_b = card_b.container() with container_a: black_cats() with container_b: black_cats() with container_c: black_cats() @st.fragment def herd_orange_cats(card_a, card_b, card_c): st.button("Herd the orange cats") container_a = card_a.container() container_b = card_b.container() container_c = card_c.container() with container_a: orange_cats() with container_b: orange_cats() with container_c: orange_cats() with st.sidebar: herd_black_cats(grid[0].empty(), grid[2].empty(), grid[4].empty()) herd_orange_cats(grid[1].empty(), grid[3].empty(), grid[5].empty()) st.button("Herd all the cats") ``` ## Frame out your app's containers 1. Add a title to your app and two rows of three containers. ```python st.title("Cats!") row1 = st.columns(3) row2 = st.columns(3) grid = [col.container(height=200) for col in row1 + row2] ``` Save your file to see your updated preview. 2. Define a helper function to draw two black cats. ```python def black_cats(): time.sleep(1) st.title("🐈‍⬛ 🐈‍⬛") st.markdown("🐾 🐾 🐾 🐾") ``` This function represents "herding two cats" and uses `time.sleep()` to simulate a slower process. You will use this to draw two cats in one of your grid cards later on. 3. Define another helper function to draw two orange cats. ```python def orange_cats(): time.sleep(1) st.title("🐈 🐈") st.markdown("🐾 🐾 🐾 🐾") ``` 4. Optional: Test out your functions by calling each one within a grid card. ```python with grid[0]: black_cats() with grid[1]: orange_cats() ``` Save your `app.py` file to see the preview. Delete these four lines when finished. ## Define your fragments Since each fragment will span across the sidebar and three additional containers, you'll use the sidebar to hold the main body of the fragment and pass the three containers as function arguments. 1. Use an `@st.fragment` decorator and start your black-cat fragment definition. ```python @st.fragment def herd_black_cats(card_a, card_b, card_c): st.button("Herd the black cats") container_a = card_a.container() container_b = card_b.container() container_c = card_c.container() with container_a: black_cats() with container_b: black_cats() with container_c: black_cats() ``` 2. Add a button for rerunning this fragment. ```python st.button("Herd the black cats") ``` 3. Write to each container using your helper function. ```python with card_a: black_cats() with card_b: black_cats() with card_c: black_cats() ``` This code above will not behave as desired, but you'll explore and correct this in the following steps. 4. Test out your code. Call your fragment function in the sidebar. ```python with st.sidebar: herd_black_cats(grid[0].empty(), grid[2].empty(), grid[4].empty()) herd_orange_cats(grid[1].empty(), grid[3].empty(), grid[5].empty()) st.button("Herd all the cats") ``` By creating `st.empty()` containers in each card and passing them to your fragments, you prevent elements from accumulating in the cards with each fragment rerun. If you create the `st.empty()` containers earlier in your app, full-script reruns will clear the orange-cat cards while (first) rendering the black-cat cards. 5. Include a button outside of your fragments. When clicked, the button will trigger a full-script rerun since you're calling its widget function outside of any fragment. ```python st.button("Herd all the cats") ``` 6. Save your file and try out the app! When you click "Herd the black cats" or "Herd the orange cats", Streamlit will only redraw the three related cards. When you click "Herd all the cats", Streamlit redraws all six cards. --- # Source: https://docs.streamlit.io/get-started/tutorials/create-an-app # Create an app If you've made it this far, chances are you've [installed Streamlit](/get-started/installation) and run through the basics in [Basic concepts](/get-started/fundamentals/main-concepts) and [Advanced concepts](/get-started/fundamentals/advanced-concepts). If not, now is a good time to take a look. The easiest way to learn how to use Streamlit is to try things out yourself. As you read through this guide, test each method. As long as your app is running, every time you add a new element to your script and save, Streamlit's UI will ask if you'd like to rerun the app and view the changes. This allows you to work in a fast interactive loop: you write some code, save it, review the output, write some more, and so on, until you're happy with the results. The goal is to use Streamlit to create an interactive app for your data or model and along the way to use Streamlit to review, debug, perfect, and share your code. In this guide, you're going to use Streamlit's core features to create an interactive app; exploring a public Uber dataset for pickups and drop-offs in New York City. When you're finished, you'll know how to fetch and cache data, draw charts, plot information on a map, and use interactive widgets, like a slider, to filter results. ## Let's put it all together That's it, you've made it to the end. Here's the complete script for our interactive app. ```python import streamlit as st import pandas as pd import numpy as np st.title('Uber pickups in NYC') DATE_COLUMN = 'date/time' DATA_URL = ('https://s3-us-west-2.amazonaws.com/' 'streamlit-demo-data/uber-raw-data-sep14.csv.gz') @st.cache_data def load_data(nrows): data = pd.read_csv(DATA_URL, nrows=nrows) lowercase = lambda x: str(x).lower() data.rename(lowercase, axis='columns', inplace=True) data[DATE_COLUMN] = pd.to_datetime(data[DATE_COLUMN]) return data data_load_state = st.text('Loading data...') data = load_data(10000) data_load_state.text('Loading data...done!') if st.checkbox('Show raw data'): st.subheader('Raw data') st.write(data) ``` ## Share your app After you’ve built a Streamlit app, it's time to share it! To show it off to the world you can use **Streamlit Community Cloud** to deploy, manage, and share your app for free. It works in 3 simple steps: 1. Put your app in a public GitHub repo (and make sure it has a requirements.txt!) 2. Sign into [share.streamlit.io](https://share.streamlit.io/) 3. Click 'Deploy an app' and then paste in your GitHub URL That's it! 🎈 You now have a publicly deployed app that you can share with the world. Click to learn more about [how to use Streamlit Community Cloud](/deploy/streamlit-community-cloud). ## Get help That's it for getting started, now you can go and build your own apps! If you run into difficulties here are a few things you can do. - Check out our [community forum](https://discuss.streamlit.io/) and post a question - Quick help from command line with `streamlit help` - Go through our [Knowledge Base](/knowledge-base) for tips, step-by-step tutorials, and articles that answer your questions about creating and deploying Streamlit apps. - Read more documentation! Check out: - [Concepts](/develop/concepts) for things like caching, theming, and adding statefulness to apps. - [API reference](/develop/api-reference) for examples of every Streamlit command. --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/get-started/create-your-account # Create your account - Streamlit Docs Create your account ================== Before you can start deploying apps for the world to see, you need to sign up for your Streamlit Community Cloud account. Each Community Cloud account is associated with an email. Two accounts can't have the same email. When sharing a private app, you will assign viewing privileges by email. Additionally, two accounts can't have the same source control (GitHub account). If you try to create a second Community Cloud account with the same source control, Community Cloud will merge the accounts. ### Sign up Community Cloud allows you to sign in using one of the three following methods: 1. Emailed, one-use codes 2. Google 3. GitHub #### Important Even when you sign in through GitHub, the authentication flow returns your email address to Community Cloud. Changing the email on your GitHub account can affect your Community Cloud account if you sign in through GitHub. 1. Click "Continue with Google". 2. Enter your Google credentials, and follow GitHub's authentication prompts. This adds the "Streamlit Community Cloud" OAuth application to your GitHub account. This application is only used to pass your email when you sign in to Community Cloud. On the next page, you'll perform additional steps to allow Community Cloud to access your repositories. For more information about using and reviewing the OAuth applications on your account, see [Using OAuth apps](https://docs.github.com/en/apps/oauth-apps/using-oauth-apps) in GitHub's docs. #### Finish up Congratulations on creating your Streamlit Community Cloud account! A warning icon (warning) next to "Workspaces" in the upper-left corner is expected; this indicates that your account is not yet connected to GitHub. Even if you created your account by signing in through GitHub, your account does not yet have permission to access your repositories. Continue to the next page to connect your GitHub account. --- # Source: https://docs.streamlit.io/develop/concepts/custom-components/create # Create a Component - Streamlit Docs Create a Component ================== **Note** If you are only interested in **using Streamlit Components**, then you can skip this section and head over to the [Streamlit Components Gallery](https://streamlit.io/components) to find and install components created by the community! Developers can write JavaScript and HTML "components" that can be rendered in Streamlit apps. Streamlit Components can receive data from, and also send data to, Streamlit Python scripts. Streamlit Components let you expand the functionality provided in the base Streamlit package. Use Streamlit Components to create the needed functionality for your use-case, then wrap it up in a Python package and share with the broader Streamlit community! **With Streamlit Components you can add new features to your app in the following ways:** - Create your own components to use in place of existing Streamlit elements and widgets. - Create completely new Streamlit elements and widgets by wrapping existing React.js, Vue.js, or other JavaScript widget toolkits. - Render Python objects by constructing HTML representations and styling them to fit your app's theme. - Create convenience functions to embed commonly-used web features like [GitHub gists and Pastebin](https://github.com/randyzwitch/streamlit-embedcode). Check out these Streamlit Components tutorial videos by Streamlit engineer Tim Conkling to get started: [Part 1: Setup and Architecture](#part-1-setup-and-architecture) [Part 2: Make a Slider Widget](#part-2-make-a-slider-widget) [forum](#) ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. --- ### Part 1: Setup and Architecture [arrow_back Previous: Intro to custom components](/develop/concepts/custom-components/intro)[arrow_forward Next: Publish a Component](/develop/concepts/custom-components/publish) --- ### Part 2: Make a Slider Widget [arrow_back Previous: Intro to custom components](/develop/concepts/custom-components/intro)[arrow_forward Next: Publish a Component](/develop/concepts/custom-components/publish) --- ### forum ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. --- © 2025 Snowflake Inc. --- # Source: https://docs.streamlit.io/develop/concepts/design/custom-classes # Using custom Python classes in your Streamlit app If you are building a complex Streamlit app or working with existing code, you may have custom Python classes defined in your script. Common examples include the following: - Defining a `@dataclass` to store related data within your app. - Defining an `Enum` class to represent a fixed set of options or values. - Defining custom interfaces to external services or databases not covered by `st.connection`. Because Streamlit reruns your script after every user interaction, custom classes may be redefined multiple times within the same Streamlit session. This may result in unwanted effects, especially with class and instance comparisons. Read on to understand this common pitfall and how to avoid it. We begin by covering some general-purpose patterns you can use for different types of custom classes, and follow with a few more technical details explaining why this matters. Finally, we go into more detail about [Using `Enum` classes](https://docs.streamlit.io/develop/concepts/design/custom-classes#using-enum-classes-in-streamlit) specifically, and describe a configuration option which can make them more convenient. ## Patterns to define your custom classes ### Pattern 1: Define your class in a separate module This is the recommended, general solution. If possible, move class definitions into their own module file and import them into your app script. As long as you are not editing the files that define your app, Streamlit will not re-import those classes with each rerun. Therefore, if a class is defined in an external file and imported into your script, the class will not be redefined during the session, unless you are actively editing your app. #### Example: Move your class definition Try running the following Streamlit app where `MyClass` is defined within the page's script. `isinstance()` will return `True` on the first script run then return `False` on each rerun thereafter. ```python # app.py import streamlit as st # MyClass gets redefined every time app.py reruns class MyClass: def __init__(self, var1, var2): self.var1 = var1 self.var2 = var2 if "B" not in st.session_state: st.session_state.B = MyClass(1, "Marshall") # Displays True on the first run then False on every rerun st.write(isinstance(st.session_state.B, MyClass)) st.button("Rerun") ``` If you move the class definition out of `app.py` into another file, you can make `isinstance()` consistently return `True`. Consider the following file structure: ```python myproject/ ├── my_class.py └── app.py ``` ```python # my_class.py class MyClass: def __init__(self, var1, var2): self.var1 = var1 self.var2 = var2 ``` ```python # app.py import streamlit as st from my_class import MyClass # MyClass doesn't get redefined with each rerun if "B" not in st.session_state: st.session_state.B = MyClass(1, "Marshall") # Displays True on every rerun st.write(isinstance(st.session_state.B, MyClass)) st.button("Rerun") ``` Streamlit only reloads code in imported modules when it detects the code has changed. Thus, if you are actively editing your app code, you may need to start a new session or restart your Streamlit server to avoid an undesirable class redefinition. ### Pattern 2: Force your class to compare internal values For classes that store data (like `dataclasses`), you may be more interested in comparing the internally stored values rather than the class itself. If you define a custom `__eq__` method, you can force comparisons to be made on the internally stored values. #### Example: Define `__eq__` Try running the following Streamlit app and observe how the comparison is `True` on the first run then `False` on every rerun thereafter. ```python import streamlit as st from dataclasses import dataclass @dataclass class MyDataclass: var1: int var2: float if "my_dataclass" not in st.session_state: st.session_state.my_dataclass = MyDataclass(1, 5.5) # Displays True on the first run the False on every rerun st.session_state.my_dataclass == MyDataclass(1, 5.5) st.button("Rerun") ``` Since `MyDataclass` gets redefined with each rerun, the instance stored in Session State will not be equal to any instance defined in a later script run. You can fix this by forcing a comparison of internal values as follows: ```python import streamlit as st from dataclasses import dataclass @dataclass class MyDataclass: var1: int var2: float def __eq__(self, other): # An instance of MyDataclass is equal to another object if the object # contains the same fields with the same values return (self.var1, self.var2) == (other.var1, other.var2) if "my_dataclass" not in st.session_state: st.session_state.my_dataclass = MyDataclass(1, 5.5) # Displays True on every rerun st.session_state.my_dataclass == MyDataclass(1, 5.5) st.button("Rerun") ``` The default Python `__eq__` implementation for a regular class or `@dataclass` depends on the in-memory ID of the class or class instance. To avoid problems in Streamlit, your custom `__eq__` method should not depend on the `type()` of `self` and `other`. ### Pattern 3: Store your class as serialized data Another option for classes that store data is to define serialization and deserialization methods like `to_str` and `from_str` for your class. You can use these to store class instance data in `st.session_state` rather than storing the class instance itself. Similar to pattern 2, this is a way to force comparison of the internal data and bypass the changing in-memory IDs. #### Example: Save your class instance as a string Using the same example from pattern 2, this can be done as follows: ```python import streamlit as st from dataclasses import dataclass @dataclass class MyDataclass: var1: int var2: float def to_str(self): return f"{self.var1},{self.var2}" @classmethod def from_str(cls, serial_str): values = serial_str.split(",") var1 = int(values[0]) var2 = float(values[1]) return cls(var1, var2) if "my_dataclass" not in st.session_state: st.session_state.my_dataclass = MyDataclass(1, 5.5).to_str() # Displays True on every rerun MyDataclass.from_str(st.session_state.my_dataclass) == MyDataclass(1, 5.5) st.button("Rerun") ``` ### Pattern 4: Use caching to preserve your class For classes that are used as resources (database connections, state managers, APIs), consider using the cached singleton pattern. Use `@st.cache_resource` to decorate a `@staticmethod` of your class to generate a single, cached instance of the class. For example: ```python import streamlit as st class MyResource: def __init__(self, api_url: str): self._url = api_url @st.cache_resource(ttl=300) @staticmethod def get_resource_manager(api_url: str): return MyResource(api_url) # This is cached until Session State is cleared or 5 minutes has elapsed. resource_manager = MyResource.get_resource_manager("http://example.com/api/") ``` When you use one of Streamlit's caching decorators on a function, Streamlit doesn't use the function object to look up cached values. Instead, Streamlit's caching decorators index return values using the function's qualified name and module. So, even though Streamlit redefines `MyResource` with each script run, `st.cache_resource` is unaffected by this. `get_resource_manager()` will return its cached value with each rerun, until the value expires. ## Understanding how Python defines and compares classes So what's really happening here? We'll consider a simple example to illustrate why this is a pitfall. Feel free to skip this section if you don't want to deal more details. You can jump ahead to learn about [Using `Enum` classes](https://docs.streamlit.io/develop/concepts/design/custom-classes#using-enum-classes-in-streamlit). ### Example: What happens when you define the same class twice? Set aside Streamlit for a moment and think about this simple Python script: ```python from dataclasses import dataclass @dataclass class Student: student_id: int name: str Marshall_A = Student(1, "Marshall") Marshall_B = Student(1, "Marshall") # This is True (because a dataclass will compare two of its instances by value) Marshall_A == Marshall_B # Redefine the class @dataclass class Student: student_id: int name: str Marshall_C = Student(1, "Marshall") # This is False Marshall_A == Marshall_C ``` In this example, the dataclass `Student` is defined twice. All three Marshalls have the same internal values. If you compare `Marshall_A` and `Marshall_B` they will be equal because they were both created from the first definition of `Student`. However, if you compare `Marshall_A` and `Marshall_C` they will not be equal because `Marshall_C` was created from the second definition of `Student`. Even though both `Student` dataclasses are defined exactly the same, they have different in-memory IDs and are therefore different. ### What's happening in Streamlit? In Streamlit, you probably don't have the same class written twice in your page script. However, the rerun logic of Streamlit creates the same effect. Let's use the above example for an analogy. If you define a class in one script run and save an instance in Session State, then a later rerun will redefine the class and you may end up comparing a `Mashall_C` in your rerun to a `Marshall_A` in Session State. Since widgets rely on Session State under the hood, this is where things can get confusing. ## How Streamlit widgets store options Several Streamlit UI elements, such as `st.selectbox` or `st.radio`, accept multiple-choice options via an `options` argument. The user of your application can typically select one or more of these options. The selected value is returned by the widget function. For example: ```python number = st.selectbox("Pick a number, any number", options=[1, 2, 3]) # number == whatever value the user has selected from the UI. ``` When you call a function like `st.selectbox` and pass an `Iterable` to `options`, the `Iterable` and current selection are saved into a hidden portion of `Session State` called the Widget Metadata. When the user of your application interacts with the `st.selectbox` widget, the browser sends the index of their selection to your Streamlit server. This index is used to determine which values from the original `options` list, saved in the Widget Metadata from the previous page execution, are returned to your application. The key detail is that the value returned by `st.selectbox` (or similar widget function) is from an `Iterable` saved in Session State during a previous execution of the page, NOT the values passed to `options` on the current execution. There are a number of architectural reasons why Streamlit is designed this way, which we won't go into here. However, this is how we end up comparing instances of different classes when we think we are comparing instances of the same class. ### A pathological example The above explanation might be a bit confusing, so here's a pathological example to illustrate the idea. ```python import streamlit as st from dataclasses import dataclass @dataclass class MyDataclass: var1: int var2: float Marshall_A = MyDataclass(1, "Marshall") if "B" not in st.session_state: st.session_state.B = MyDataclass(1, "Marshall") Marshall_B = st.session_state.B options = [Marshall_A, Marshall_B] selected = st.selectbox("Pick", options) # This comparison does not return expected results: selected == Marshall_A # This comparison evaluates as expected: selected == Marshall_B ``` As a final note, we used `@dataclass` in the example for this section to illustrate a point, but in fact it is possible to encounter these same problems with classes, in general. Any class which checks class identity inside of a comparison operator—such as `__eq__` or `__gt__`—can exhibit these issues. ## Using `Enum` classes in Streamlit The `Enum` class from the Python standard library is a powerful way to define custom symbolic names that can be used as options for `st.multiselect` or `st.selectbox` in place of `str` values. For example, you might add the following to your streamlit page: ```python from enum import Enum import streamlit as st # class syntax class Color(Enum): RED = 1 GREEN = 2 BLUE = 3 selected_colors = set(st.multiselect("Pick colors", options=Color)) if selected_colors == {Color.RED, Color.GREEN}: st.write("Hooray, you found the color YELLOW!") ``` If you're using the latest version of Streamlit, this Streamlit page will work as it appears it should. When a user picks both `Color.RED` and `Color.GREEN`, they are shown the special message. However, if you've read the rest of this page you might notice something tricky going on. Specifically, the `Enum` class `Color` gets redefined every time this script is run. In Python, if you define two `Enum` classes with the same class name, members, and values, the classes and their members are still considered unique from each other. This should cause the above `if` condition to always evaluate to `False`. In any script rerun, the `Color` values returned by `st.multiselect` would be of a different class than the `Color` defined in that script run. If you run the snippet above with Streamlit version 1.28.0 or less, you will not be able see the special message. Thankfully, as of version 1.29.0, Streamlit introduced a configuration option to greatly simplify the problem. That's where the enabled-by-default `enumCoercion` configuration option comes in. ### Understanding the `enumCoercion` configuration option When `enumCoercion` is enabled, Streamlit tries to recognize when you are using an element like `st.multiselect` or `st.selectbox` with a set of `Enum` members as options. If Streamlit detects this, it will convert the widget's returned values to members of the `Enum` class defined in the latest script run. This is something we call automatic `Enum` coercion. This behavior is configurable via the `enumCoercion` setting in your Streamlit `config.toml` file. It is enabled by default, and may be disabled or set to a stricter set of matching criteria. If you find that you still encounter issues with `enumCoercion` enabled, consider using the custom class patterns described above, such as moving your `Enum` class definition to a separate module file. --- # Source: https://docs.streamlit.io/develop/api-reference/custom-components # Source: https://docs.streamlit.io/develop/concepts/custom-components # Components Components are third-party Python modules that extend what's possible with Streamlit. ## How to use a Component Components are super easy to use: 1. Start by finding the Component you'd like to use. Two great resources for this are: - The [Component gallery](https://streamlit.io/components) - [This thread](https://discuss.streamlit.io/t/streamlit-components-community-tracker/4634), by Fanilo A. from our forums. 2. Install the Component using your favorite Python package manager. This step and all following steps are described in your component's instructions. For example, to use the fantastic [AgGrid Component](https://github.com/PablocFonseca/streamlit-aggrid), you first install it with: ```bash pip install streamlit-aggrid ``` 3. In your Python code, import the Component as described in its instructions. For AgGrid, this step is: ```python from st_aggrid import AgGrid ``` 4. ...now you're ready to use it! For AgGrid, that's: ```python AgGrid(my_dataframe) ``` ## Making your own Component If you're interested in making your own component, check out the following resources: - [Create a Component](/develop/concepts/custom-components/create) - [Publish a Component](/develop/concepts/custom-components/publish) - [Components API](/develop/concepts/custom-components/intro) - [Blog post for when we launched Components!](https://blog.streamlit.io/introducing-streamlit-components/) Alternatively, if you prefer to learn using videos, our engineer Tim Conkling has put together some amazing tutorials: ### Video tutorial, part 1 ### Video tutorial, part 2 --- # Source: https://docs.streamlit.io/develop/api-reference/data # Data elements When you're working with data, it is extremely valuable to visualize that data quickly, interactively, and from multiple different angles. That's what Streamlit is actually built and optimized for. You can display data via [charts](/develop/api-reference/data#display-charts), and you can display it in raw form. These are the Streamlit commands you can use to display and interact with raw data. ## Dataframes Display a dataframe as an interactive table. ```python st.dataframe(my_data_frame) ``` ## Data editor Display a data editor widget. ```python edited = st.data_editor(df, num_rows="dynamic") ``` ## Column configuration Configure the display and editing behavior of dataframes and data editors. ```python st.column_config.NumberColumn("Price (in USD)", min_value=0, format="$%d") ``` ## Static tables Display a static table. ```python st.table(my_data_frame) ``` ## Metrics Display a metric in big bold font, with an optional indicator of how the metric changed. ```python st.metric("My metric", 42, 2) ``` ## Dicts and JSON Display object or string as a pretty-printed JSON string. ```python st.json(my_dict) ``` ## Third-party components These are featured components created by our lovely community. For more examples and inspiration, check out our [Components Gallery](https://streamlit.io/components) and [Streamlit Extras](https://extras.streamlit.app/)! ## App testing Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [FAQ](https://discuss.streamlit.io) is full of helpful information and Streamlit experts. ### Previous: Text elements ### Next: st.dataframe --- # Source: https://docs.streamlit.io/develop/tutorials/databases # Connect to data sources These step-by-step guides demonstrate how to connect Streamlit apps to various databases & APIs. They use Streamlit's [Secrets management](/develop/concepts/connections/secrets-management) and [caching](/develop/concepts/architecture/caching) to provide secure and fast data access. ## AWS S3 ![AWS S3](/images/databases/s3.png) ## BigQuery ![BigQuery](/images/databases/bigquery.png) ## Firestore (blog) ![Firestore (blog)](/images/databases/firestore.png) ## Google Cloud Storage ![Google Cloud Storage](/images/databases/gcs.png) ## Microsoft SQL Server ![Microsoft SQL Server](/images/databases/mssql.png) ## MongoDB ![MongoDB](/images/databases/mongodb.png) ## MySQL ![MySQL](/images/databases/mysql.png) ## Neon ![Neon](/images/databases/neon-logo.png) ## PostgreSQL ![PostgreSQL](/images/databases/postgresql.png) ## Private Google Sheet ![Private Google Sheet](/images/databases/gsheet.png) ## Public Google Sheet ![Public Google Sheet](/images/databases/gsheet.png) ## Snowflake ![Snowflake](/images/databases/snowflake.png) ## Supabase ![Supabase](/images/databases/supabase.png) ## Tableau ![Tableau](/images/databases/tableau.png) ## TiDB ![TiDB](/images/databases/tidb.png) ## TigerGraph ![TigerGraph](/images/databases/tigergraph.png) [Previous: Configuration and theming](/develop/tutorials/configuration-and-theming) [Next: AWS S3](/develop/tutorials/databases/aws-s3) --- # Source: https://docs.streamlit.io/develop/tutorials/elements/dataframe-row-selections # Get dataframe row-selections from users Streamlit offers two commands for rendering beautiful, interactive dataframes in your app. If you need users to edit data, add rows, or delete rows, use `st.data_editor`. If you don't want users to change the data in your dataframe, use `st.dataframe`. Users can sort and search through data rendered with `st.dataframe`. Additionally, you can activate selections to work with users' row and column selections. This tutorial uses row selections, which were introduced in Streamlit version 1.35.0. For an older workaround using `st.data_editor`, see [Get dataframe row-selections (streamlit<1.35.0)](/develop/tutorials/elements/dataframe-row-selections-old). ## Applied concepts - Use dataframe row selections to filter a dataframe. ## Prerequisites - This tutorial requires the following version of Streamlit: ```text streamlit>=1.35.0 ``` - You should have a clean working directory called `your-repository`. - You should have a basic understanding of caching and `st.dataframe`. ## Summary In this example, you'll build an app that displays a table of members and their activity for an imaginary organization. Within the table, a user can select one or more rows to create a filtered view. Your app will show a combined chart that compares the selected employees. Here's a look at what you'll build: ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Combine activity data for the selected rows 1. Create an empty dictionary to store (yearly) activity data. ```python activity_df = {} ``` 2. Iterate through selected rows and save each member's activity in the dictionary indexed by their name. ```python for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] ``` 3. Convert the activity dictionary into a `pandas.DataFrame`. ```python activity_df = pd.DataFrame(activity_df) ``` 4. Repeat the previous three steps similarly for daily activity. ```python daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) ``` 5. Optional: Test out your combined data by displaying it. ```python st.dataframe(activity_df) st.dataframe(daily_activity_df) ``` ## Use charts to visualize the activity comparison 1. Start a conditional block to check if anyone is currently selected. ```python if len(people) > 0: # Since no members are selected when the app loads, this check will prevent empty charts from being displayed. ``` 2. Add a header to identify your first chart. ```python st.header("Daily activity comparison") ``` 3. Show the daily activity comparison in a bar chart. ```python st.bar_chart(daily_activity_df) ``` 4. Similarly, for yearly activity, add a header and line chart. ```python st.header("Yearly activity comparison") st.line_chart(activity_df) ``` 5. Complete the conditional block with a default message to show when no members are selected. ```python else: st.markdown("No members selected.") ``` ## Make it pretty You should have a functioning app at this point. Now you can beautify it. In this section, you'll separate the selection UI from the comparison by using `st.tabs`. 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: daily_activity_df[df.iloc[person]["name"]] = df.iloc[person]["daily_activity"] daily_activity_df = pd.DataFrame(daily_activity_df) if len(people) > 0: st.header("Daily activity comparison") st.bar_chart(daily_activity_df) st.header("Yearly activity comparison") st.line_chart(activity_df) else: st.markdown("No members selected.") ``` ## Build the example 1. Immediately after the column configuration definition, insert two tabs. ```python select, compare = st.tabs(["Select members", "Compare selected"]) ``` 2. Indent the code following the line in the previous step and group it into the two new tabs. ```python with select: # Add select tab st.header("All members") df = get_profile_dataset() event = st.dataframe( df, column_config=column_configuration, use_container_width=True, hide_index=True, on_select="rerun", selection_mode="multi-row", ) st.header("Selected members") people = event.selection.rows filtered_df = df.iloc[people] st.dataframe( filtered_df, column_config=column_configuration, use_container_width=True, ) with compare: # Add compare tab activity_df = {} for person in people: activity_df[df.iloc[person]["name"]] = df.iloc[person]["activity"] activity_df = pd.DataFrame(activity_df) daily_activity_df = {} for person in people: --- # Source: https://docs.streamlit.io/develop/concepts/design/dataframes # Dataframes Dataframes are a great way to display and edit data in a tabular format. Working with Pandas DataFrames and other tabular data structures is key to data science workflows. If developers and data scientists want to display this data in Streamlit, they have multiple options: `st.dataframe` and `st.data_editor`. If you want to solely display data in a table-like UI, `st.dataframe` is the way to go. If you want to interactively edit data, use `st.data_editor`. ## Display dataframes with `st.dataframe` Streamlit can display dataframes in a table-like UI via `st.dataframe`: ```python import streamlit as st import pandas as pd df = pd.DataFrame( [ {"command": "st.selectbox", "rating": 4, "is_widget": True}, {"command": "st.balloons", "rating": 5, "is_widget": False}, {"command": "st.time_input", "rating": 3, "is_widget": True}, ] ) st.dataframe(df, use_container_width=True) ``` ## `st.data_editor` UI features `st.data_editor` provides additional functionality by using `glide-data-grid` under the hood: - **Column sorting**: To sort columns, select their headers, or select "Sort ascending" or "Sort descending" from the header menu (more_vert). - **Column resizing**: To resize columns, drag and drop column header borders, or select "Autosize" from the header menu. - **Column hiding**: To hide columns, select "Hide column" from the header menu. - **Reorder and pin columns**: To reorder columns or pin them on the left, drag and drop column headers or select "Pin column" from the header menu, respectively. - **Format numbers, dates, and times**: To change the format of numeric columns, select an option under "Format" in the header menu. - **Dataframe resizing**: To resize dataframes, drag and drop the bottom right corner. - **Fullscreen view**: To enlarge dataframes to fullscreen, select the fullscreen icon (fullscreen) in the toolbar. - **Search**: To search through the data, select the search icon (search) in the toolbar or use hotkeys (⌘+F or Ctrl+F). - **Download**: To download the data as a CSV file, select the download icon (download) in the toolbar. ## `st.data_editor` UI features `st.data_editor` also supports a few additional things: - **Add and delete rows**: You can do this by setting `num_rows="dynamic"` when calling `st.data_editor`. This will allow users to add and delete rows as needed. - **Copy and paste support**: Copy and paste both between `st.data_editor` and spreadsheet software like Google Sheets and Excel. - **Access edited data**: Access only the individual edits instead of the entire edited data structure via Session State. - **Bulk edits**: Similar to Excel, just drag a handle to edit neighboring cells. - **Automatic input validation**: Column Configuration provides strong data type support and other configurable options. For example, there's no way to enter letters into a number cell. Number cells can have a designated min and max. - **Edit common data structures**: `st.data_editor` supports lists, dicts, NumPy ndarray, and more! ## `st.data_editor` UI features ### Add and delete rows With `st.data_editor`, viewers can add or delete rows via the table UI. This mode can be activated by setting `num_rows="dynamic"` when calling `st.data_editor`. This will allow users to add and delete rows as needed. - To add new rows, click the plus icon (add) in the toolbar. Alternatively, click inside a shaded cell below the bottom row of the table. - To delete rows, select one or more rows using the checkboxes on the left. Click the delete icon (delete) or press the delete key on your keyboard. ### Copy and paste support The data editor supports pasting in tabular data from Google Sheets, Excel, Notion, and many other similar tools. You can also copy-paste data between `st.data_editor` instances. This functionality, powered by the `Clipboard API`, can be a huge time saver for users who need to work with data across multiple platforms. To try it out: - Copy data from this Google Sheets document to your clipboard. - Single click any cell in the name column in the app above. Paste it in using hotkeys (⌘+V or Ctrl+V). Every cell of the pasted data will be evaluated individually and inserted into the cells if the data is compatible with the column type. For example, pasting in non-numerical text data into a number column will be ignored. If you embed your apps with iframes, you'll need to allow the iframe to access the clipboard if you want to use the copy-paste functionality. To do so, give the iframe `allow="clipboard-write;clipboard-read;" ... src="https://your-app-url">` in the iframe. As developers, ensure the app is served with a valid, trusted certificate when using TLS. If users encounter issues with copying and pasting data, direct them to check if their browser has activated clipboard access permissions for the Streamlit application, either when prompted or through the browser's site settings. ### Access edited data Sometimes, it is more convenient to know which cells have been changed rather than getting the entire edited dataframe back. Streamlit makes this easy through the use of `Session State`. If a `key` parameter is set, Streamlit will store any changes made to the dataframe in Session State. This snippet shows how you can access changed data using Session State: ```python st.data_editor(df, key="my_key", num_rows="dynamic") # 👈 Set a key st.write("Here's the value in Session State:") st.write(st.session_state["my_key"]) # 👈 Show the value in Session State ``` In this code snippet, the `key` parameter is set to `my_key`. After the data editor is created, the value associated to `my_key` in Session State is displayed in the app using `st.write`. This shows the additions, edits, and deletions that were made. This can be useful when working with large dataframes and you only need to know which cells have changed, rather than access the entire edited dataframe. ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### `st.data_editor` UI features ### ` --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/manage-your-account/delete-your-account # Delete your account Deleting your Streamlit Community Cloud account is just as easy as creating it. When you delete your account, your information, account, and all your hosted apps are deleted as well. Read more about data deletion in [Streamlit trust and security](/deploy/streamlit-community-cloud/get-started/trust-and-security#data-deletion). ## Warning Deleting your account is permanent and cannot be undone. Make sure you really want to delete your account and all hosted apps before proceeding. Any app you've deployed will be deleted, regardless of the workspace it was deployed from. ## How to delete your account Follow these steps to delete your account: 1. Sign in to Streamlit Community Cloud at [share.streamlit.io](https://share.streamlit.io/) and access your [Workspace settings](/deploy/streamlit-community-cloud/manage-your-account/workspace-settings). 2. From the "Linked accounts" section, click "Delete account". 3. In the confirmation dialog, follow the prompt and click "Delete account forever". All your information and apps will be permanently deleted. It's that simple! If you have any questions or run into issues deleting your account, please reach out to us on [our forum](https://discuss.streamlit.io/c/community-cloud/13). We're happy to help! 🎈 --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/manage-your-app/delete-your-app # Delete your app If you need to delete your app, it's simple and easy. There are several cases where you may need to delete your app: - You have finished playing around with an example app. - You want to deploy from a private repository but already have a private app. - You want to [change the Python version](/deploy/streamlit-community-cloud/manage-your-app/upgrade-python) for your app. - You want to [rename your repository](/deploy/streamlit-community-cloud/manage-your-app/rename-your-app) or move your entrypoint file. If you delete your app and intend to immediately redploy it, your custom subdomain should be immediately available for reuse. Read more about data deletion in [Streamlit trust and security](/deploy/streamlit-community-cloud/get-started/trust-and-security#data-deletion). You can delete your app: - [From your workspace](#delete-your-app-from-your-workspace). - [From your Cloud logs](#delete-your-app-from-your-cloud-logs). ## Delete your app from your workspace 1. From your workspace at [share.streamlit.io](https://share.streamlit.io/), click the overflow icon (more_vert) next to your app. Click "Delete". ![Delete your app from your workspace](/images/streamlit-community-cloud/workspace-app-delete.png) 2. A confirmation will display. Enter the required confirmation string and click "Delete". ![Confirm deleting your app from Streamlit Community Cloud](/images/streamlit-community-cloud/workspace-app-delete-confirm.png) ## Delete your app from your Cloud logs 1. From your app at `.streamlit.app`, click "Manage app" in the lower-right corner. ![Access Streamlit Community Cloud logs from your app](/images/streamlit-community-cloud/cloud-logs-open.png) 2. Click the overflow menu icon (more_vert) and click "Delete app". ![Delete your app from your Cloud logs](/images/streamlit-community-cloud/cloud-logs-menu-delete.png) 3. A confirmation will display. Enter the required confirmation string and click "Delete". --- # Source: https://docs.streamlit.io/knowledge-base/dependencies # Source: https://docs.streamlit.io/deploy/concepts/dependencies # Managing dependencies when deploying your app Before you began developing your app, you set up and configured your development environment by installing Python and Streamlit. When you deploy your app, you need to set up and configure your deployment environment in the same way. When you deploy your app to a cloud service, your app's [Python server](/develop/concepts/architecture/architecture#python-backend-server) will be running on a remote machine. This remote machine will not have access all the files and programs on your personal computer. All Streamlit apps have at least two dependencies: Python and Streamlit. Your app may have additional dependencies in the form of Python packages or software that must be installed to properly execute your script. If you are using a service like Streamlit Community Cloud which is designed for Streamlit apps, we'll take care of Python and Streamlit for you! ## Install Python and other software If you are using Streamlit Community Cloud, Python is already installed. You can just pick the version in the deployment dialog. If you need to install Python yourself or you have other non-Python software to install, follow your platform's instructions to install additional software. You will commonly use a package management tool to do this. For example, Streamlit Community Cloud uses Advanced Package Tool (`apt`) for Debian-based Linux systems. For more information about installing non-Python depencies on Streamlit Community Cloud, see [`apt-get` dependencies](/deploy/streamlit-community-cloud/deploy-your-app/app-dependencies#apt-get-dependencies). ## Install Python packages Once you have Python installed in your deployment environment, you'll need to install all the necessary Python packages, including Streamlit! With each `import` of an installed package, you add a Python dependency to your script. You need to install those dependencies in your deployment environment through a Python package manager. If you are using Streamlit Community Cloud, you'll have the latest version of Streamlit and all of its dependencies installed by default. So, if you're making a simple app and don't need additional dependencies, you won't have to do anything at all! ### `pip` and `requirements.txt` Since `pip` comes by default with Python, the most common way to configure your Python environment is with a `requirements.txt` file. Each line of a `requirements.txt` file is a package to `pip install`. You should _not_ include [built-in Python libraries](https://docs.python.org/3/py-modindex.html) like `math`, `random`, or `distutils` in your `requirements.txt` file. These are a part of Python and aren't installed separately. #### Tip Since dependencies may rely on a specific version of Python, always be aware of the Python version used in your development environment, and select the same version for your deployment environment. If you have a script like the following, you would only need to install Streamlit. No extra dependencies would be needed since `pandas` and `numpy` are installed as direct dependencies of `streamlit`. Similarly, `math` and `random` are built into Python. ```python import streamlit as st import pandas as pd import numpy as np import math import random st.write('Hi!') ``` However, it's a best practice accurately record packages you use, so the recommended `requirements.txt` file would be: ```none streamlit pandas numpy ``` If you needed to specify certain versions, another valid example would be: ```none streamlit==1.24.1 pandas>2.0 numpy<=1.25.1 ``` A `requirements.txt` file is commonly saved in the root of your repository or file directory. If you are using Streamlit Community Cloud, see [Add Python dependencies](/deploy/streamlit-community-cloud/deploy-your-app/app-dependencies#add-python-dependencies) for more information. Otherwise, check your platform's documentation. --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/get-started/deploy-from-a-template # Deploy an app from a template Streamlit Community Cloud makes it easy to get started with several convenient templates. Just pick a template, and Community Cloud will fork it to your account and deploy it. Any edits you push to your new fork will immediately show up in your deployed app. Additionally, if you don't want to use a local development environment, Community Cloud makes it easy to create a GitHub codespace that's fully configured for Streamlit app development. ## Access the template picker There are two ways to begin deploying a template: the "Create app" button and the template gallery at the bottom of your workspace. - If you click the "Create app" button, Community Cloud will ask you "Do you already have an app?". Select "Nope, create one from a template". - If you scroll to the bottom of your workspace in the "My apps" section, you can see the most popular templates. Click on one directly, or select "View all templates". The template picker shows a list of available templates on the left. A preview for the current, selected template shows on the right. ![Deploy from a template page on Community Cloud](https://docs.streamlit.io/sharing-image-facebook.jpg) ## Select a template 1. From the list of templates on the left, select "GDP dashboard". 2. Optional: For "Name of new GitHub repository", enter a name for your new, forked repository. When you deploy a template, Community Cloud forks the template repository into your GitHub account. Community Cloud chooses a default name for this repository based on the selected template. If you have previously deployed the same template with its default name, Community Cloud will append an auto-incrementing number to the name. _Note: Even if you have another user's or organization's workspace selected, Community Cloud will always deploy a template app from your personal workspace. That is, Community Cloud will always fork a template into your GitHub user account. If you want to deploy a template app from an organization, manually fork the template in GitHub, and deploy it from your fork in the associated workspace._ 3. Optional: In the "App URL" field, choose a subdomain for your new app. Every Community Cloud app is deployed to a subdomain on `streamlit.app`, but you can change your app's subdomain at any time. For more information, see [App settings](https://docs.streamlit.io/deploy/streamlit-community-cloud/manage-your-app/app-settings). 4. Optional: To edit the template in a GitHub codespace immediately, select the option to "Open GitHub Codespaces..." You can create a codespace for your app at any time. To learn how to create a codespace after you've deployed an app, see [Edit your app](https://docs.streamlit.io/deploy/streamlit-community-cloud/manage-your-app/edit-your-app). 5. Optional: To change the version of Python, at the bottom of the screen, click "Advanced settings", select a Python version, and then click "Save". After an app is deployed, you can't change the version of Python without deleting and redeploying the app. 6. At the bottom, click "Deploy". ## View your app - If you didn't select the option to open GitHub Codespaces, you are redirected to your new app. ![GDP dashboard template app](https://docs.streamlit.io/images/streamlit-community-cloud/deploy-template-GDP.png) - If you selected the option to open GitHub Codespaces, you are redirected to your new codespace, which can take several minutes to be fully initialized. After the Visual Studio Code editor appears in your codespace, it can take several minutes to install Python and start the Streamlit server. When complete, a split screen view displays a code editor on the left and a running app on the right. The code editor opens two tabs by default: the repository's readme file and the app's entrypoint file. ![GDP dashboard template app in a codespace](https://docs.streamlit.io/images/streamlit-community-cloud/deploy-template-GDP-codespace.png) _The app displayed in your codespace is not the same instance you deployed on Community Cloud. Your codespace is a self-contained development environment. When you make edits inside a codespace, those edits don't leave the codespace until you commit them to your repository. When you commit your changes to your repository, Community Cloud detects the changes and updates your deployed app. To learn more, see [Edit your app](https://docs.streamlit.io/deploy/streamlit-community-cloud/manage-your-app/edit-your-app)._ ## Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/deploy-your-app # Prep and deploy your app on Community Cloud Streamlit Community Cloud lets you deploy your apps in just one click, and most apps will be deployed in only a few minutes. If you don't have an app ready to deploy, you can fork or clone one from our [App gallery](https://streamlit.io/gallery)—you can find apps for machine learning, data visualization, data exploration, A/B testing, and more. You can also [Deploy an app from a template](/deploy/streamlit-community-cloud/get-started/deploy-from-a-template). After you've deployed your app, check out how you can [Edit your app with GitHub Codespaces](/deploy/streamlit-community-cloud/manage-your-app/edit-your-app#edit-your-app-with-github-codespaces). ## Summary The pages that follow explain how to organize your app and provide complete information for Community Cloud to run it correctly. When your app has everything it needs, deploying is easy. Just go to your workspace and click "Create app" in the upper-right corner. Follow the prompts to fill in your app's information, and then click "Deploy". ### File organization [Learn how Community Cloud initializes your app and interprets paths. Learn where to put your configuration files.](/deploy/streamlit-community-cloud/deploy-your-app/file-organization) ### App dependencies [Learn how to install dependencies and other Python libraries into your deployment environment.](/deploy/streamlit-community-cloud/deploy-your-app/app-dependencies) ### Secrets management [Learn about the interface Community Cloud provides to securely upload your `secrets.toml` data.](/deploy/streamlit-community-cloud/deploy-your-app/secrets-management) ### Deploy your app [Put it all together to deploy your app for the whole world to see.](/deploy/streamlit-community-cloud/deploy-your-app/deploy) ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ## Previous and Next [Previous: Get started](/deploy/streamlit-community-cloud/get-started) [Next: File organization](/deploy/streamlit-community-cloud/deploy-your-app/file-organization) --- # Source: https://docs.streamlit.io/knowledge-base/deploy # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/deploy-your-app/deploy # Source: https://docs.streamlit.io/deploy # Deploy Get all the information you need to deploy your app and share it with your users. ## Concepts [Concepts.](/deploy/concepts) Understand the basics of app deployment. ## Streamlit Community Cloud [Streamlit Community Cloud.](/deploy/streamlit-community-cloud) Deploy your app on our free platform and join a community of developers who share their apps around the world. This is a great place for your non-commercial, personal, and educational apps. ## Snowflake [Snowflake.](/deploy/snowflake) Deploy your app in Snowflake for a secure, enterprise-grade environment. This is a great place for your business apps. ## Other platforms [Other platforms.](/deploy/tutorials) Learn how to deploy your app on a variety of platforms with our convenient collection of tutorials. ## Deployment issues [Deployment issues.](/deploy/deploy-your-app) Get comprehensive guides for deploying your Streamlit apps to various platforms including Community Cloud, Snowflake, and other cloud providers. ## Quick reference [Quick reference.](/develop/quick-reference) Get a quick reference for the Streamlit API, including cheat sheets, release notes, and pre-release features. ## Knowledge base [Knowledge base.](/knowledge-base) Find answers to common questions about deploying and using Streamlit, including installation, configuration, and troubleshooting. ## Deploy [Deploy](/deploy) Get all the information you need to deploy your app and share it with your users. ### Deploy - [Get started](/deploy/get-started) - [Quickstart](/deploy/get-started/quickstart) - [Create your account](/deploy/get-started/create-your-account) - [Connect your GitHub account](/deploy/get-started/connect-your-github-account) - [Explore your workspace](/deploy/get-started/explore-your-workspace) - [Deploy from a template](/deploy/get-started/deploy-from-a-template) - [Fork and edit a public app](/deploy/get-started/fork-and-edit-a-public-app) - [Trust and security](/deploy/get-started/trust-and-security) - [Deploy your app](/deploy/deploy-your-app) - [File organization](/deploy/deploy-your-app/file-organization) - [App dependencies](/deploy/deploy-your-app/app-dependencies) - [Secrets management](/deploy/deploy-your-app/secrets-management) - [Deploy!](/deploy/deploy-your-app/deploy) - [Manage your app](/deploy/manage-your-app) - [App analytics](/deploy/manage-your-app/app-analytics) - [App settings](/deploy/manage-your-app/app-settings) - [Delete your app](/deploy/manage-your-app/delete-your-app) - [Edit your app](/deploy/manage-your-app/edit-your-app) - [Favorite your app](/deploy/manage-your-app/favorite-your-app) - [Reboot your app](/deploy/manage-your-app/reboot-your-app) - [Rename your app in GitHub](/deploy/manage-your-app/rename-your-app) - [Upgrade Python](/deploy/manage-your-app/upgrade-python) - [Upgrade Streamlit](/deploy/manage-your-app/upgrade-streamlit) - [Share your app](/deploy/share-your-app) - [Embed your app](/deploy/share-your-app/embed-your-app) - [Search indexability](/deploy/share-your-app/indexability) - [Share previews](/deploy/share-your-app/share-previews) - [Manage your account](/deploy/manage-your-account) - [Sign in and sign out](/deploy/manage-your-account/sign-in-sign-out) - [Workspace settings](/deploy/manage-your-account/workspace-settings) - [Manage your GitHub connection](/deploy/manage-your-account/manage-your-github-connection) - [Update your email](/deploy/manage-your-account/update-your-email) - [Delete your account](/deploy/manage-your-account/delete-your-account) - [Status and limitations](/deploy/status) ## Deploy - [Concepts](/deploy/concepts) - [Dependencies](/deploy/concepts/dependencies) - [Secrets](/deploy/concepts/secrets) - [Streamlit Community Cloud](/deploy/streamlit-community-cloud) - [Get started](/deploy/streamlit-community-cloud/get-started) - [Quickstart](/deploy/streamlit-community-cloud/get-started/quickstart) - [Create your account](/deploy/streamlit-community-cloud/get-started/create-your-account) - [Connect your GitHub account](/deploy/streamlit-community-cloud/get-started/connect-your-github-account) - [Explore your workspace](/deploy/streamlit-community-cloud/get-started/explore-your-workspace) - [Deploy from a template](/deploy/streamlit-community-cloud/get-started/deploy-from-a-template) - [Fork and edit a public app](/deploy/streamlit-community-cloud/get-started/fork-and-edit-a-public-app) - [Trust and security](/deploy/streamlit-community-cloud/get-started/trust-and-security) - [Deploy your app](/deploy/streamlit-community-cloud/deploy-your-app) - [File organization](/deploy/streamlit-community-cloud/deploy-your-app/file-organization) - [App dependencies](/deploy/streamlit-community-cloud/deploy-your-app/app-dependencies) - [Secrets management](/deploy/streamlit-community-cloud/deploy-your-app/secrets-management) - [Deploy!](/deploy/streamlit-community-cloud/deploy-your-app/deploy) - [Manage your app](/deploy/streamlit-community-cloud/manage-your-app) - [App analytics](/deploy/streamlit-community-cloud/manage-your-app/app-analytics) - [App settings](/deploy/streamlit-community-cloud/manage-your-app/app-settings) - [Delete your app](/deploy/streamlit-community-cloud/manage-your-app/delete-your-app) - [Edit your app](/deploy/streamlit-community-cloud/manage-your-app/edit-your-app) - [Favorite your app](/deploy/streamlit-community-cloud/manage-your-app/favorite-your-app) - [Reboot your app](/deploy/streamlit-community-cloud/manage-your-app/reboot-your-app) - [Rename your app in GitHub](/deploy/streamlit-community-cloud/manage-your-app/rename-your-app) - [Upgrade Python](/deploy/streamlit-community-cloud/manage-your-app/upgrade-python) - [Upgrade Streamlit](/deploy/streamlit-community-cloud/manage-your-app/upgrade-streamlit) - [Share your app](/deploy/streamlit-community-cloud/share-your-app) - [Embed your app](/deploy/streamlit-community-cloud/share-your-app/embed-your-app) - [Search indexability](/deploy/streamlit-community-cloud/share-your-app/indexability) - [Share previews](/deploy/streamlit-community-cloud/share-your-app/share-previews) - [Manage your account](/deploy/streamlit-community-cloud/manage-your-account) - [Sign in and sign out](/deploy/streamlit-community-cloud/manage-your-account/sign-in-sign-out) - [Workspace settings](/deploy/streamlit-community-cloud/manage-your-account/workspace-settings) - [Manage your GitHub connection](/deploy/streamlit-community-cloud/manage-your-account/manage-your-github-connection) - [Update your email](/deploy/streamlit-community-cloud/manage-your-account/update-your-email) - [Delete your account](/deploy/streamlit-community-cloud/manage-your-account/delete-your-account) - [Status and limitations](/deploy/streamlit-community-cloud/status) - [Snowflake](/deploy/snowflake) - [Other platforms](/deploy/tutorials) - [Docker](/deploy/tutorials/docker) - [Kubernetes](/deploy/tutorials/kubernetes) ## Knowledge base - [FAQ](/knowledge-base/using-streamlit) - [How do I create an anchor link?](/knowledge-base/using-streamlit/create-anchor-link) - [Enabling camera access in your browser](/knowledge-base/using-streamlit/enable-camera) - [How to download a file in Streamlit?](/knowledge-base/using-streamlit/how-download-file-streamlit) - [How to download a Pandas DataFrame as a CSV?](/knowledge-base/using-streamlit/how-download-pandas-dataframe-csv) - [How do I upgrade to the latest version of Streamlit?](/knowledge-base/using-streamlit/how-upgrade-latest-version-streamlit) - [How to insert elements out of order?](/knowledge-base/using-streamlit/insert-elements-out-of-order) - [How can I make st.pydeck_chart use custom Mapbox styles?](/knowledge-base/using-streamlit/pydeck-chart-custom-mapbox-styles) - [How to remove "· Streamlit" from the app title?](/knowledge-base/using-streamlit/remove-streamlit-app-title) - [How do you retrieve the filename of a file uploaded with st.file_uploader?](/knowledge-base/using-streamlit/retrieve-filename-uploaded) - [Sanity checks](/knowledge-base/using-streamlit/sanity-checks) - [How can I make Streamlit watch for changes in other modules I'm importing in my app?](/knowledge-base/using-streamlit/streamlit-watch-changes-other-modules-importing-app) - [What browsers does Streamlit support?](/knowledge-base/using-streamlit/supported-browsers) - [Where does st.file_uploader store uploaded files and when do they get deleted?](/knowledge-base/using-streamlit/where-file-uploader-store-when-deleted) - [Widget updating for every second input when using session state](/knowledge-base/using-streamlit/widget-updating-session-state) - [Why does Streamlit restrict nested st.columns?](/knowledge-base/using-streamlit/why-streamlit-restrict-nested-columns) - [What is serializable session state?](/knowledge-base/using-streamlit/serializable-session-state) - [Installing dependencies](/knowledge-base/dependencies) - [How to install a package not on PyPI or Conda but available on GitHub](/knowledge-base/dependencies/install-package-not-pypi-conda-available-github) - [ImportError libGL.so.1 cannot open shared object file No such file or directory](/knowledge-base/dependencies/libgl) - [ModuleNotFoundError No module named](/knowledge-base/dependencies/module-not-found-error) - [Deployment issues](/knowledge-base/deploy) - [How can I deploy multiple Streamlit apps on different subdomains?](/knowledge-base/deploy/deploy-multiple-streamlit-apps-different-subdomains) - [How do I deploy Streamlit on a domain so it appears to run on a regular port (i.e. port 80)?](/knowledge-base/deploy/deploy-streamlit-domain-port-80) - [Does Streamlit support the WSGI Protocol? (aka Can I deploy Streamlit with gunicorn)?](/knowledge-base/deploy/does-streamlit-support-wsgi-protocol) - [How do I increase the upload limit of st.file_uploader on Streamlit Community Cloud?](/knowledge-base/deploy/increase-file-uploader-limit-streamlit-cloud) - [Invoking a Python subprocess in a deployed Streamlit app](/knowledge-base/deploy/invoking-python-subprocess-deployed-streamlit-app) - [App is not loading when running remotely](/knowledge-base/deploy/remote-start) - [Argh. This app has gone over its resource limits](/knowledge-base/deploy/resource-limits) - [How do I share apps with viewers outside my organization?](/knowledge-base/deploy/share-apps-with-viewers-outside-organization) - [Upgrade the Streamlit version of your app on Streamlit Community Cloud](/knowledge-base/deploy/upgrade-streamlit-version-on-streamlit-cloud) - [Huh. This is isn't supposed to happen message after trying to log in](/knowledge-base/deploy/huh-this-isnt-supposed-to-happen-message-after-trying-to-log-in) - [Login attempt to Streamlit Community Cloud fails with error 403](/knowledge-base/deploy/login-attempt-to-streamlit-community-cloud-fails-with-error-403) - [How to submit a support case for Streamlit Community Cloud](/knowledge-base/deploy/how-to-submit-a-support-case-for-streamlit-community-cloud) ## Deploy - [Concepts](/deploy/concepts) - [Dependencies](/deploy/concepts/dependencies) - [Secrets](/deploy/concepts/secrets) - [Streamlit Community Cloud](/deploy/streamlit-community-cloud) - [Get started](/deploy/streamlit-community-cloud/get-started) - [Quickstart](/deploy/streamlit-community-cloud/get-started/quickstart) - [Create your account](/deploy/streamlit-community-cloud/get-started/create-your-account) - [Connect your GitHub account](/deploy/streamlit-community-cloud/get-started/connect-your-github-account) - [Explore your workspace](/deploy/streamlit-community-cloud/get-started/explore-your-workspace) - [Deploy from a template](/deploy/streamlit-community-cloud/get-started/deploy-from-a-template) - [Fork and edit a public app](/deploy/streamlit-community-cloud/get-started/fork-and-edit-a-public-app) - [Trust and security](/deploy/streamlit-community-cloud/get-started/trust-and-security) - [Deploy your app](/deploy/streamlit-community-cloud/deploy-your-app) - [File organization](/deploy/streamlit-community-cloud/deploy-your-app/file-organization) - [App dependencies](/deploy/streamlit-community-cloud/deploy-your-app/app-dependencies) - [Secrets management](/deploy/streamlit-community-cloud/deploy-your-app/secrets-management) - [Deploy!](/deploy/streamlit-community-cloud/deploy-your-app/deploy) - [Manage your app](/deploy/streamlit-community-cloud/manage-your-app) - [App analytics](/deploy/streamlit-community-cloud/manage-your-app/app-analytics) - [App settings](/deploy/streamlit-community-cloud/manage-your-app/app-settings) - [Delete your app](/deploy/streamlit-community-cloud/manage-your-app/delete-your-app) - [Edit your app](/deploy/streamlit-community-cloud/manage-your-app/edit-your-app) - [Favorite your app](/deploy/streamlit-community-cloud/manage-your-app/favorite-your-app) - [Reboot your app](/deploy/streamlit-community-cloud/manage-your-app/reboot-your-app) - [Rename your app in GitHub](/deploy/streamlit-community-cloud/manage-your-app/rename-your-app) - [Upgrade Python](/deploy/streamlit-community-cloud/manage-your-app/upgrade-python) - [Upgrade Streamlit](/deploy/streamlit-community-cloud/manage-your-app/upgrade-streamlit) - [Share your app](/deploy/streamlit-community-cloud/share-your-app) - [Embed your app](/deploy/streamlit-community-cloud/share-your-app/embed-your-app) - [Search indexability](/deploy/streamlit-community-cloud/share-your-app/indexability) - [Share previews](/deploy/streamlit-community-cloud/share-your-app/share-previews) - [Manage your account](/deploy/streamlit-community-cloud/manage-your-account) - [Sign in and sign out](/deploy/streamlit-community-cloud/manage-your-account/sign-in-sign-out) - [Workspace settings](/deploy/streamlit-community-cloud/manage-your-account/workspace-settings) - [Manage your GitHub connection](/deploy/streamlit-community-cloud/manage-your-account/manage-your-github-connection) - [Update your email](/deploy/streamlit-community-cloud/manage-your-account/update-your-email) - [Delete your account](/deploy/streamlit-community-cloud/manage-your-account/delete-your-account) - [Status and limitations](/deploy/streamlit-community-cloud/status) - [Snowflake](/deploy/snowflake) - [Other platforms](/deploy/tutorials) - [Docker](/deploy/tutorials/docker) - [Kubernetes](/deploy/tutorials/kubernetes) ## Knowledge base - [FAQ](/knowledge-base/using-streamlit) - [How do I create an anchor link?](/knowledge-base/using-streamlit/create-anchor-link) - [Enabling camera access in your browser](/knowledge-base/using-streamlit/enable-camera) - [How to download a file in Streamlit?](/knowledge-base/using-streamlit/how-download-file-streamlit) - [How to download a Pandas DataFrame as a CSV?](/knowledge-base/using-streamlit/how-download-pandas-dataframe-csv) - [How do I upgrade to the latest version of Streamlit?](/knowledge-base/using-streamlit/how-upgrade-latest-version-streamlit) - [How to insert elements out of order?](/knowledge-base/using-streamlit/insert-elements-out-of-order) - [How can I make st.pydeck_chart use custom Mapbox styles?](/knowledge-base/using-streamlit/pydeck-chart-custom-mapbox-styles) - [How to remove "· Streamlit" from the app title?](/knowledge-base/using-streamlit/remove-streamlit-app-title) - [How do you retrieve the filename of a file uploaded with st.file_uploader?](/knowledge-base/using-streamlit/retrieve-filename-uploaded) - [Sanity checks](/knowledge-base/using-streamlit/sanity-checks) - [How can I make Streamlit watch for changes in other modules I'm importing in my app?](/knowledge-base/using-streamlit/streamlit-watch-changes-other-modules-importing-app) - [What browsers does Streamlit support?](/knowledge-base/using-streamlit/supported-browsers) - [Where does st.file_uploader store uploaded files and when do they get deleted?](/knowledge-base/using-streamlit/where-file-uploader-store-when-deleted) - [Widget updating for every second input when using session state](/knowledge-base/using-streamlit/widget-updating-session-state) - [Why does Streamlit restrict nested st.columns?](/knowledge-base/using-streamlit/why-streamlit-restrict-nested-columns) - [What is serializable session state?](/knowledge-base/using-streamlit/serializable-session-state) - [Installing dependencies](/knowledge-base/dependencies) - [How to install a package not on PyPI or Conda but available on GitHub](/knowledge-base/dependencies/install-package-not-pypi-conda-available-github) - [ImportError libGL.so.1 cannot open shared object file No such file or directory](/knowledge-base/dependencies/libgl) - [ModuleNotFoundError No module named](/knowledge-base/dependencies/module-not-found-error) - [Deployment issues](/knowledge-base/deploy) - [How can I deploy multiple Streamlit apps on different subdomains?](/knowledge-base/deploy/deploy-multiple-streamlit-apps-different-subdomains) - [How do I deploy Streamlit on a domain so it appears to run on a regular port (i.e. port 80)?](/knowledge-base/deploy/deploy-streamlit-domain-port-80) - [Does Streamlit support the WSGI Protocol? (aka Can I deploy Streamlit with gunicorn)?](/knowledge-base/deploy/does-streamlit-support-wsgi-protocol) - [How do I increase the upload limit of st.file_uploader on Streamlit Community Cloud?](/knowledge-base/deploy/increase-file-uploader-limit-streamlit-cloud) - [Invoking a Python subprocess in a deployed Streamlit app](/knowledge-base/deploy/invoking-python-subprocess-deployed-streamlit-app) - [App is not loading when running remotely](/knowledge-base/deploy/remote-start) - [Argh. This app has gone over its resource limits](/knowledge-base/deploy/resource-limits) - [How do I share apps with viewers outside my organization?](/knowledge-base/deploy/share-apps-with-viewers-outside-organization) - [Upgrade the Streamlit version of your app on Streamlit Community Cloud](/knowledge-base/deploy/upgrade-streamlit-version-on-streamlit-cloud) - [Huh. This is isn't supposed to happen message after trying to log in](/knowledge-base/deploy/huh-this-isnt-supposed-to-happen-message-after-trying-to-log-in) - [Login attempt to Streamlit Community Cloud fails with error 403](/knowledge-base/deploy/login-attempt-to-streamlit-community-cloud-fails-with-error-403) - [How to submit a support case for Streamlit Community Cloud](/knowledge-base/deploy/how-to-submit-a-support-case-for-streamlit-community-cloud) ## Deploy - [Concepts](/deploy/concepts) - [Dependencies](/deploy/concepts/dependencies) - [Secrets](/deploy/concepts/secrets) - [Streamlit Community Cloud](/deploy/streamlit-community-cloud) - [Get started](/deploy/streamlit-community-cloud/get-started) - [Quickstart](/deploy/streamlit-community-cloud/get-started/quickstart) - [Create your account](/deploy/streamlit-community-cloud/get-started/create-your-account) - [Connect your GitHub account](/deploy/streamlit-community-cloud/get-started/connect-your-github-account) - [Explore your workspace](/deploy/streamlit-community-cloud/get-started/explore-your-workspace) - [Deploy from a template](/deploy/streamlit-community-cloud/get-started/deploy-from-a-template) - [Fork and edit a public app](/deploy/streamlit-community-cloud/get-started/fork-and-edit-a-public-app) - [Trust and security](/deploy/streamlit-community-cloud/get-started/trust-and-security) - [Deploy your app](/deploy/streamlit-community-cloud/deploy-your-app) - [File organization](/deploy/streamlit-community-cloud/deploy-your-app/file-organization) - [App dependencies](/deploy/streamlit-community-cloud/deploy-your-app/app-dependencies) - [Secrets management](/deploy/streamlit-community-cloud/deploy-your-app/secrets-management) - [Deploy!](/deploy/streamlit-community-cloud/deploy-your-app/deploy) - [Manage your app](/deploy/streamlit-community-cloud/manage-your-app) - [App analytics](/deploy/streamlit-community-cloud/manage-your-app/app-analytics) - [App settings](/deploy/streamlit-community-cloud/manage-your-app/app-settings) - [Delete your app](/deploy/streamlit-community-cloud/manage-your-app/delete-your-app) - [Edit your app](/deploy/streamlit-community-cloud/manage-your-app/edit-your-app) - [Favorite your app](/deploy/streamlit-community-cloud/manage-your-app/favorite-your-app) - [Reboot your app](/deploy/streamlit-community-cloud/manage-your-app/reboot-your-app) - [Rename your app in GitHub](/deploy/streamlit-community-cloud/manage-your-app/rename-your-app) - [Upgrade Python](/deploy/streamlit-community-cloud/manage-your-app/upgrade-python) - [Upgrade Streamlit](/deploy/streamlit-community-cloud/manage-your-app/upgrade-streamlit) - [Share your app](/deploy/streamlit-community-cloud/share-your-app) - [Embed your app](/deploy/streamlit-community-cloud/share-your-app/embed-your-app) - [Search indexability](/deploy/streamlit-community-cloud/share-your-app/indexability) - [Share previews](/deploy/streamlit-community-cloud/share-your-app/share-previews) - [Manage your account](/deploy/streamlit-community-cloud/manage-your-account) - [Sign in and sign out](/deploy/streamlit-community-cloud/manage-your-account/sign-in-sign-out) - [Workspace settings](/deploy/streamlit-community-cloud/manage-your-account/workspace-settings) - [Manage your GitHub connection](/deploy/streamlit-community-cloud/manage-your-account/manage-your-github-connection) - [Update your email](/deploy/streamlit-community-cloud/manage-your-account/update-your-email) - [Delete your account](/deploy/streamlit-community-cloud/manage-your-account/delete-your-account) - [Status and limitations](/deploy/streamlit-community-cloud/status) - [Snowflake](/deploy/snowflake) - [Other platforms](/deploy/tutorials) - [Docker](/deploy/tutorials/docker) - [Kubernetes](/deploy/tutorials/kubernetes) ## Knowledge base - [FAQ](/knowledge-base/using-streamlit) - [How do I create an anchor link?](/knowledge-base/using-streamlit/create-anchor-link) - [Enabling camera access in your browser](/knowledge-base/using-streamlit/enable-camera) - [How to download a file in Streamlit?](/knowledge-base/using-streamlit/how-download-file-streamlit) - [How to download a Pandas DataFrame as a CSV?](/knowledge-base/using-streamlit/how-download-pandas-dataframe-csv) - [How do I upgrade to the latest version of Streamlit?](/knowledge-base/using-streamlit/how-upgrade-latest-version-streamlit) - [How to insert elements out of order?](/knowledge-base/using-streamlit/insert-elements-out-of-order) - [How can I make st.pydeck_chart use custom Mapbox styles?](/knowledge-base/using-streamlit/pydeck-chart-custom-mapbox-styles) - [How to remove "· Streamlit" from the app title?](/knowledge-base/using-streamlit/remove-streamlit-app-title) - [How do you retrieve the filename of a file uploaded with st.file_uploader?](/knowledge-base/using-streamlit/retrieve-filename-uploaded) - [Sanity checks](/knowledge-base/using-streamlit/sanity-checks) - [How can I make Streamlit watch for changes in other modules I'm importing in my app?](/knowledge-base/using-streamlit/streamlit-watch-changes-other-modules-importing-app) - [What browsers does Streamlit support?](/knowledge-base/using-streamlit/supported-browsers) - [Where does st.file_uploader store uploaded files and when do they get deleted?](/knowledge-base/using-streamlit/where-file-uploader-store-when-deleted) - [Widget updating for every second input when using session state](/knowledge-base/using-streamlit/widget-updating-session-state) - [Why does Streamlit restrict nested st.columns?](/knowledge-base/using-streamlit/why-streamlit-restrict-nested-columns) - [What is serializable session state?](/knowledge-base/using-streamlit/serializable-session-state) - [Installing dependencies](/knowledge-base/dependencies) - [How to install a package not on PyPI or Conda but available on GitHub](/knowledge-base/dependencies/install-package-not-pypi-conda-available-github) - [ImportError libGL.so.1 cannot open shared object file No such file or directory](/knowledge-base/dependencies/libgl) - [ModuleNotFoundError No module named](/knowledge-base/dependencies/module-not-found-error) - [Deployment issues](/knowledge-base/deploy) - [How can I deploy multiple Streamlit apps on different subdomains?](/knowledge-base/deploy/deploy-multiple-streamlit-apps-different-subdomains) - [How do I deploy Streamlit on a domain so it appears to run on a regular port (i.e. port 80)?](/knowledge-base/deploy/deploy-streamlit-domain-port-80) - [Does Streamlit support the WSGI Protocol? (aka Can I deploy Streamlit with gunicorn)?](/knowledge-base/deploy/does-streamlit-support-wsgi-protocol) - [How do I increase the upload limit of st.file_uploader on Streamlit Community Cloud?](/knowledge-base/deploy/increase-file-uploader-limit-streamlit-cloud) - [Invoking a Python subprocess in a deployed Streamlit app](/knowledge-base/deploy/invoking-python-subprocess-deployed-streamlit-app) - [App is not loading when running remotely](/knowledge-base/deploy/remote-start) - [Argh. This app has gone over its resource limits](/knowledge-base/deploy/resource-limits) - [How do I share apps with viewers outside my organization?](/knowledge-base/deploy/share-apps-with-viewers-outside-organization) - [Upgrade the Streamlit version of your app on Streamlit Community Cloud](/knowledge-base/deploy/upgrade-streamlit-version-on-streamlit-cloud) - [Huh. This is isn't supposed to happen message after trying to log in](/knowledge-base/deploy/huh-this-isnt-supposed-to-happen-message-after-trying-to-log-in) - [Login attempt to Streamlit Community Cloud fails with error 403](/knowledge-base/deploy/login-attempt-to-streamlit-community-cloud-fails-with-error-403) - [How to submit a support case for Streamlit Community Cloud](/knowledge-base/deploy/how-to-submit-a-support-case-for-streamlit-community-cloud) --- # Source: https://docs.streamlit.io/develop/concepts/design # App design concepts and considerations ## Explore comprehensive guides about app design including animating elements, button behavior, custom styling, dataframe design, multithreading, and timezone handling. ### [Animate and update elements](/develop/concepts/design/animate) Understand how to create dynamic, animated content or update elements without rerunning your app. ### [Button behavior and examples](/develop/concepts/design/buttons) Understand how buttons work with explanations and examples to avoid common mistakes. ### [Dataframes](/develop/concepts/design/dataframes) Dataframes are a great way to display and edit data in a tabular format. Understand the UI and options available in Streamlit. ### [Using custom Python classes in your Streamlit app](/develop/concepts/design/custom-classes) Understand the impact of defining your own Python classes within Streamlit's rerun model. ### [Multithreading](/develop/concepts/design/multithreading) Understand how to use multithreading within Streamlit apps. ### [Working with timezones](/develop/concepts/design/timezone-handling) Understand how to localize time to your users. [Previous: Multipage apps](/develop/concepts/multipage-apps) [Next: Animate and update elements](/develop/concepts/design/animate) --- # Source: https://docs.streamlit.io/develop # Develop Get all the information you need to build beautiful, performant web apps with Streamlit! ## Concepts [Concepts.](/develop/concepts) Learn how Streamlit works with in-depth guides to our execution model and features. ## API reference [API reference.](/develop/api-reference) Learn about our API with function definitions and examples. ## Tutorials [Tutorials.](/develop/tutorials) Follow step-by-step instructions to build example apps and useful snippets. ## Quick reference [Quick references.](/develop/quick-reference) Check out our quick references for easy access to convenient information like our changelog, cheat sheet, pre-release features, and roadmap. ## Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ## Previous [Previous: Get started](/get-started) ## Next [Next: Concepts](/develop/concepts) --- # Source: https://docs.streamlit.io/deploy/tutorials/docker # Deploy Streamlit using Docker So you have an amazing app and you want to start sharing it with other people, what do you do? You have a few options. First, where do you want to run your Streamlit app, and how do you want to access it? Let’s say you want to run your app on your corporate network. Most corporate networks are closed to the outside world. You typically use a VPN to log onto your corporate network and access resources there. You could run your Streamlit app on a server in your corporate network for security reasons, to ensure that only folks internal to your company can access it. ## Check network port accessibility As you and your users are behind your corporate VPN, you need to make sure all of you can access a certain network port. Let’s say port 8501, as it is the default port used by Streamlit. Contact your IT team and request access to port 8501 for you and your users. ## Create a Dockerfile Docker builds images by reading the instructions from a `Dockerfile`. A `Dockerfile` is a text document that contains all the commands a user could call on the command line to assemble an image. Learn more in the [Dockerfile reference](https://docs.docker.com/engine/reference/builder/). The `docker build` command builds an image from a `Dockerfile`. Run the following command from the `app/` directory on your server to build the image: ```bash docker build -t streamlit . ``` The `-t` flag is used to tag the image. Here, we have tagged the image `streamlit`. If you run: ```bash docker images ``` You should see a `streamlit` image under the REPOSITORY column. For example: ``` REPOSITORY TAG IMAGE ID CREATED SIZE streamlit latest 70b0759a094d About a minute ago 1.02GB ``` ## Run the Docker container Now that you have built the image, you can run the container by executing: ```bash docker run -p 8501:8501 streamlit ``` The `-p` flag publishes the container’s port 8501 to your server’s 8501 port. If all went well, you should see an output similar to the following: ```bash docker run -p 8501:8501 streamlit You can now view your Streamlit app in your browser. URL: http://0.0.0.0:8501 ``` To view your app, users can browse to `http://0.0.0.0:8501` or `http://localhost:8501`. ## Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https --- # Source: https://docs.streamlit.io/develop/api-reference/cli/docs # streamlit docs Open the Streamlit docs in your default browser. ## Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) ## Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. --- ## Get started - [Installation](/get-started/installation) - [Fundamentals](/get-started/fundamentals) - [First steps](/get-started/tutorials) ## Develop - [Concepts](/develop/concepts) - [API reference](/develop/api-reference) - PAGE ELEMENTS - [Write and magic](/develop/api-reference/write-magic) - [Text elements](/develop/api-reference/text) - [Data elements](/develop/api-reference/data) - [Chart elements](/develop/api-reference/charts) - [Input widgets](/develop/api-reference/widgets) - [Media elements](/develop/api-reference/media) - [Layouts and containers](/develop/api-reference/layout) - [Chat elements](/develop/api-reference/chat) - [Status elements](/develop/api-reference/status) - [Third-party components](https://streamlit.io/components) - APPLICATION LOGIC - [Authentication and user info](/develop/api-reference/user) - [Navigation and pages](/develop/api-reference/navigation) - [Execution flow](/develop/api-reference/execution-flow) - [Caching and state](/develop/api-reference/caching-and-state) - [Connections and secrets](/develop/api-reference/connections) - [Custom components](/develop/api-reference/custom-components) - [Configuration](/develop/api-reference/configuration) - TOOLS - [App testing](/develop/api-reference/app-testing) - [Command line](/develop/api-reference/cli) - [streamlit cache](/develop/api-reference/cli/cache) - [streamlit config](/develop/api-reference/cli/config) - [streamlit docs](/develop/api-reference/cli/docs) - [streamlit hello](/develop/api-reference/cli/hello) - [streamlit help](/develop/api-reference/cli/help) - [streamlit init](/develop/api-reference/cli/init) - [streamlit run](/develop/api-reference/cli/run) - [streamlit version](/develop/api-reference/cli/version) - [Tutorials](/develop/tutorials) - [Quick reference](/develop/quick-reference) ## Deploy - [Concepts](/deploy/concepts) - [Streamlit Community Cloud](/deploy/streamlit-community-cloud) - [Snowflake](/deploy/snowflake) - [Other platforms](/deploy/tutorials) ## Knowledge base - [FAQ](/knowledge-base/using-streamlit) - [Installing dependencies](/knowledge-base/dependencies) - [Deployment issues](/knowledge-base/deploy) --- ## streamlit docs Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. --- ## Get started - [Installation](/get-started/installation) - [Fundamentals](/get-started/fundamentals) - [First steps](/get-started/tutorials) ## Develop - [Concepts](/develop/concepts) - [API reference](/develop/api-reference) - PAGE ELEMENTS - [Write and magic](/develop/api-reference/write-magic) - [Text elements](/develop/api-reference/text) - [Data elements](/develop/api-reference/data) - [Chart elements](/develop/api-reference/charts) - [Input widgets](/develop/api-reference/widgets) - [Media elements](/develop/api-reference/media) - [Layouts and containers](/develop/api-reference/layout) - [Chat elements](/develop/api-reference/chat) - [Status elements](/develop/api-reference/status) - [Third-party components](https://streamlit.io/components) - APPLICATION LOGIC - [Authentication and user info](/develop/api-reference/user) - [Navigation and pages](/develop/api-reference/navigation) - [Execution flow](/develop/api-reference/execution-flow) - [Caching and state](/develop/api-reference/caching-and-state) - [Connections and secrets](/develop/api-reference/connections) - [Custom components](/develop/api-reference/custom-components) - [Configuration](/develop/api-reference/configuration) - TOOLS - [App testing](/develop/api-reference/app-testing) - [Command line](/develop/api-reference/cli) - [streamlit cache](/develop/api-reference/cli/cache) - [streamlit config](/develop/api-reference/cli/config) - [streamlit docs](/develop/api-reference/cli/docs) - [streamlit hello](/develop/api-reference/cli/hello) - [streamlit help](/develop/api-reference/cli/help) - [streamlit init](/develop/api-reference/cli/init) - [streamlit run](/develop/api-reference/cli/run) - [streamlit version](/develop/api-reference/cli/version) - [Tutorials](/develop/tutorials) - [Quick reference](/develop/quick-reference) ## Deploy - [Concepts](/deploy/concepts) - [Streamlit Community Cloud](/deploy/streamlit-community-cloud) - [Snowflake](/deploy/snowflake) - [Other platforms](/deploy/tutorials) ## Knowledge base - [FAQ](/knowledge-base/using-streamlit) - [Installing dependencies](/knowledge-base/dependencies) - [Deployment issues](/knowledge-base/deploy) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. --- ## Get started - [Installation](/get-started/installation) - [Fundamentals](/get-started/fundamentals) - [First steps](/get-started/tutorials) ## Develop - [Concepts](/develop/concepts) - [API reference](/develop/api-reference) - PAGE ELEMENTS - [Write and magic](/develop/api-reference/write-magic) - [Text elements](/develop/api-reference/text) - [Data elements](/develop/api-reference/data) - [Chart elements](/develop/api-reference/charts) - [Input widgets](/develop/api-reference/widgets) - [Media elements](/develop/api-reference/media) - [Layouts and containers](/develop/api-reference/layout) - [Chat elements](/develop/api-reference/chat) - [Status elements](/develop/api-reference/status) - [Third-party components](https://streamlit.io/components) - APPLICATION LOGIC - [Authentication and user info](/develop/api-reference/user) - [Navigation and pages](/develop/api-reference/navigation) - [Execution flow](/develop/api-reference/execution-flow) - [Caching and state](/develop/api-reference/caching-and-state) - [Connections and secrets](/develop/api-reference/connections) - [Custom components](/develop/api-reference/custom-components) - [Configuration](/develop/api-reference/configuration) - TOOLS - [App testing](/develop/api-reference/app-testing) - [Command line](/develop/api-reference/cli) - [streamlit cache](/develop/api-reference/cli/cache) - [streamlit config](/develop/api-reference/cli/config) - [streamlit docs](/develop/api-reference/cli/docs) - [streamlit hello](/develop/api-reference/cli/hello) - [streamlit help](/develop/api-reference/cli/help) - [streamlit init](/develop/api-reference/cli/init) - [streamlit run](/develop/api-reference/cli/run) - [streamlit version](/develop/api-reference/cli/version) - [Tutorials](/develop/tutorials) - [Quick reference](/develop/quick-reference) ## Deploy - [Concepts](/deploy/concepts) - [Streamlit Community Cloud](/deploy/streamlit-community-cloud) - [Snowflake](/deploy/snowflake) - [Other platforms](/deploy/tutorials) ## Knowledge base - [FAQ](/knowledge-base/using-streamlit) - [Installing dependencies](/knowledge-base/dependencies) - [Deployment issues](/knowledge-base/deploy) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli/config) [Next: streamlit hello](/develop/api-reference/cli/hello) --- ## Open the Streamlit docs in your default browser. ### Syntax ```bash streamlit docs ``` [Previous: streamlit config](/develop/api-reference/cli --- # Source: https://docs.streamlit.io/develop/tutorials/multipage/dynamic-navigation # Create a dynamic navigation menu - Streamlit Docs Create a dynamic navigation menu =============================== `st.navigation` makes it easy to build dynamic navigation menus. You can change the set of pages passed to `st.navigation` with each rerun, which changes the navigation menu to match. This is a convenient feature for creating custom, role-based navigation menus. This tutorial uses `st.navigation` and `st.Page`, which were introduced in Streamlit version 1.36.0. For an older workaround using the `pages/` directory and `st.page_link`, see [Build a custom navigation menu with `st.page_link`](/develop/tutorials/multipage/st.page_link-nav). Applied concepts ---------------- 1. Use `st.navigation` and `st.Page` to define a multipage app. 2. Create a dynamic, role-based navigation menu. Prerequisites ------------- 1. This tutorial requires the following version of Streamlit: ```bash streamlit>=1.36.0 ``` 2. You should have a clean working directory called `your-repository`. 3. You should have a basic understanding of `st.navigation` and `st.Page`. Build the example ----------------- 1. Return to `streamlit_app.py` and initialize `role` in Session State. ```python if "role" not in st.session_state: st.session_state.role = None ``` 2. Define your account pages. ```python logout_page = st.Page( "logout", title="Log out", icon=":material/logout:", default=(role == "Requester"), ) settings = st.Page("settings.py", title="Settings", icon=":material/settings:") ``` 3. Define your request pages. ```python request_1 = st.Page( "request/request_1.py", title="Request 1", icon=":material/help:", default=(role == "Requester"), ) request_2 = st.Page( "request/request_2.py", title="Request 2", icon=":material/bug_report:", ) ``` 4. Define your remaining pages. ```python respond_1 = st.Page( "respond/respond_1.py", title="Respond 1", icon=":material/healing:", default=(role == "Responder"), ) respond_2 = st.Page( "respond/respond_2.py", title="Respond 2", icon=":material/handyman:", ) admin_1 = st.Page( "admin/admin_1.py", title="Admin 1", icon=":material/person_add:", default=(role == "Admin"), ) admin_2 = st.Page("admin/admin_2.py", title="Admin 2", icon=":material/security:") ``` 5. Group your pages into convenient lists. ```python account_pages = [logout_page, settings] request_pages = [request_1, request_2] respond_pages = [respond_1, respond_2] admin_pages = [admin_1, admin_2] ``` 6. Define your common elements and navigation. ```python st.title("Request manager") st.logo("images/horizontal_blue.png", icon_image="images/icon_blue.png") page_dict = {} if st.session_state.role in ["Requester", "Admin"]: page_dict["Request"] = request_pages if st.session_state.role in ["Responder", "Admin"]: page_dict["Respond"] = respond_pages if st.session_state.role == "Admin": page_dict["Admin"] = admin_pages if len(page_dict) > 0: pg = st.navigation({"Account": account_pages} | page_dict) pg.run() ``` 7. Save your `streamlit_app.py` file and view your app! Try logging in, switching pages, and logging out. Try again with a different role. --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/manage-your-app/edit-your-app # Edit your app You can edit your app from any development environment of your choice. Streamlit Community Cloud will monitor your repository and automatically copy any file changes you commit. You will immediately see commits reflected in your deployed app for most changes (such as edits to your app's Python files). Community Cloud also makes it easy to skip the work of setting up a development environment. With a few simple clicks, you can configure a development environment using GitHub Codespaces. ## Edit your app with GitHub Codespaces Spin up a cloud-based development environment for your deployed app in minutes. You can run your app within your codespace to enjoy experimenting in a safe, sandboxed environment. When you are done editing your code, you can commit your changes to your repo or just leave them in your codespace to return to later. ### Create a codespace for your deployed app 1. From your workspace at [share.streamlit.io](https://share.streamlit.io/), click the overflow icon (more_vert) next to your app. Click "Edit with Codespaces". Community Cloud will add a `.devcontainer/devcontainer.json` file to your repository. If you already have a file of the same name in your repository, it will not be changed. If you want your repository to receive the instance created by Community Cloud, delete or rename your existing devcontainer configuration. 2. Wait for GitHub to set up your codespace. It can take several minutes to fully initialize your codespace. After the Visual Studio Code editor appears in your codespace, it can take several minutes to install Python and start the Streamlit server. When complete, a split screen view displays a code editor on the left and a running app on the right. The code editor opens two tabs by default: the repository's readme file and the app's entrypoint file. 3. Optional: For more room to work, open the app preview in another tab. If you have multiple monitors and want a little more room to work, open your app preview in another tab instead of using the Simple Browser within Visual Studio Code. Just copy the URL from the Simple Browser into another tab, and then close the Simple Browser. Now you have more room to edit your code. The remaining steps on this page will continue to display the split-screen view in Visual Studio Code. 4. Make a change to your app. When you make changes to your app, the file is automatically saved within your codespace. Your edits do not affect your repository or deployed app until you commit those changes, which is explained in a later step. The app preview shown on the right is local to your codespace. 5. In order to see updates automatically reflected on the right, click "Always rerun" when prompted after your first edit. Alternatively, you can click "Rerun" to avoid unnecessary reruns while writing code. Because your code is continually saved, automatically rerunning the app will raise errors when you pause partway through a line of code. Regardless of which you choose, you can change the setting through the app chrome. Just click the overflow icon (more_vert) in the upper-right corner of your preview app, click "Settings", and then toggle "Run on save". 6. Continue to edit your app. Your codespace will continue to automatically save your files as you work with them, and the preview will continue to update as the app reruns. ## Optional: Publish your changes After making edits to your app, you can choose to commit your edits to your repository to update your deployed app instantly. If you just want to keep your edits in your codespace to return to later, skip to "Stop or delete your codespace". 1. In the left navigation bar, click the source control icon. In the source control sidebar on the left, enter a name for your commit. 2. Click "Commit". Your changes are committed locally in your codespace. 3. To push your commit to GitHub, in the source control sidebar on the left, click "cached 1 arrow_upward". To push commits to "origin/main", in the confirmation dialog, click "OK". Your changes are now saved to your GitHub repository. Community Cloud will immediately reflect the changes in your deployed app. 4. Optional: To see your updated, published app, return to the "My apps" section of your workspace at [share.streamlit.io](https://share.streamlit.io/), and click on your app. ## Stop or delete your codespace When you stop interacting with your codespace, GitHub will generally stop your codespace for you. However, the surest way to avoid undesired use of your capacity is to stop or delete your codespace when you are done. 1. Go to [github.com/codespaces](https://github.com/codespaces). At the bottom of the page, all your codespaces are listed. Click the overflow menu icon (more_horiz) for your codespace. ![Stop or delete your GitHub Codespace](https://docs.streamlit.io/images/streamlit-community-cloud/codespace-menu.png) 2. Click "Stop codespace" if you'd like to return to your work later. Otherwise, click "Delete". 3. Congratulations! You just deployed an app to Community Cloud. 🎉 Head back to your workspace at [share.streamlit.io](https://share.streamlit.io/) and [deploy another Streamlit app](/deploy/streamlit-community-cloud/deploy-your-app). ![See your deployed Streamlit app](https://docs.streamlit.io/images/streamlit-community-cloud/deploy-template-blank-edited.png) --- # Source: https://docs.streamlit.io/develop/tutorials/elements # Work with Streamlit elements ## Work with Streamlit elements ### Annotate an Altair chart Add annotations to an Altair chart. ### Get row selections from dataframes Work with user row-selections in dataframes. [Previous: Connect to data sources](/develop/tutorials/databases) [Next: Annotate an Altair chart](/develop/tutorials/elements/annotate-an-altair-chart) ## Forum ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ## Navigation * [Get started](/get-started) * [Installation](/get-started/installation) * [Fundamentals](/get-started/fundamentals) * [First steps](/get-started/tutorials) * [Develop](/develop) * [Concepts](/develop/concepts) * [API reference](/develop/api-reference) * [Tutorials](/develop/tutorials) * [Authentication and personalization](/develop/tutorials/authentication) * [Chat and LLM apps](/develop/tutorials/chat-and-llm-apps) * [Configuration and theming](/develop/tutorials/configuration-and-theming) * [Connect to data sources](/develop/tutorials/databases) * [Elements](/develop/tutorials/elements) * CHARTS * [Annotate an Altair chart](/develop/tutorials/elements/annotate-an-altair-chart) * [DATAFRAMES](/develop/tutorials/elements/dataframe-row-selections) * DATAFRAMES * [Get dataframe row-selections](/develop/tutorials/elements/dataframe-row-selections) * GET DATAFRAME ROW-SELECTIONS * [Get dataframe row-selections](/develop/tutorials/elements/dataframe-row-selections) * [Execution flow](/develop/tutorials/execution-flow) * [Multipage apps](/develop/tutorials/multipage) * [Deploy](/deploy) * [Concepts](/deploy/concepts) * [Streamlit Community Cloud](/deploy/streamlit-community-cloud) * [Snowflake](/deploy/snowflake) * [Other platforms](/deploy/tutorials) * [Knowledge base](/knowledge-base) * [FAQ](/knowledge-base/using-streamlit) * [Installing dependencies](/knowledge-base/dependencies) * [Deployment issues](/knowledge-base/deploy) ## Work with Streamlit elements ### Annotate an Altair chart Add annotations to an Altair chart. ### Get row selections from dataframes Work with user row-selections in dataframes. [Previous: Connect to data sources](/develop/tutorials/databases) [Next: Annotate an Altair chart](/develop/tutorials/elements/annotate-an-altair-chart) ## Forum ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ## Navigation * [Get started](/get-started) * [Installation](/get-started/installation) * [Fundamentals](/get-started/fundamentals) * [First steps](/get-started/tutorials) * [Develop](/develop) * [Concepts](/develop/concepts) * [API reference](/develop/api-reference) * [Tutorials](/develop/tutorials) * [Authentication and personalization](/develop/tutorials/authentication) * [Chat and LLM apps](/develop/tutorials/chat-and-llm-apps) * [Configuration and theming](/develop/tutorials/configuration-and-theming) * [Connect to data sources](/develop/tutorials/databases) * [Elements](/develop/tutorials/elements) * CHARTS * [Annotate an Altair chart](/develop/tutorials/elements/annotate-an-altair-chart) * [DATAFRAMES](/develop/tutorials/elements/dataframe-row-selections) * DATAFRAMES * [Get dataframe row-selections](/develop/tutorials/elements/dataframe-row-selections) * GET DATAFRAME ROW-SELECTIONS * [Get dataframe row-selections](/develop/tutorials/elements/dataframe-row-selections) * [Execution flow](/develop/tutorials/execution-flow) * [Multipage apps](/develop/tutorials/multipage) * [Deploy](/deploy) * [Concepts](/deploy/concepts) * [Streamlit Community Cloud](/deploy/streamlit-community-cloud) * [Snowflake](/deploy/snowflake) * [Other platforms](/deploy/tutorials) * [Knowledge base](/knowledge-base) * [FAQ](/knowledge-base/using-streamlit) * [Installing dependencies](/knowledge-base/dependencies) * [Deployment issues](/knowledge-base/deploy) ## Work with Streamlit elements ### Annotate an Altair chart Add annotations to an Altair chart. ### Get row selections from dataframes Work with user row-selections in dataframes. [Previous: Connect to data sources](/develop/tutorials/databases) [Next: Annotate an Altair chart](/develop/tutorials/elements/annotate-an-altair-chart) ## Forum ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/share-your-app/embed-your-app # Embed your app Embedding Streamlit Community Cloud apps enriches your content by integrating interactive, data-driven applications directly within your pages. Whether you're writing a blog post, a technical document, or sharing resources on platforms like Medium, Notion, or even StackOverflow, embedding Streamlit apps adds a dynamic component to your content. This allows your audience to interact with your ideas, rather than merely reading about them or looking at screenshots. Streamlit Community Cloud supports both iframe and oEmbed methods for embedding **public** apps. This flexibility enables you to share your apps across a wide array of platforms, broadening your app's visibility and impact. In this guide, we'll cover how to use both methods effectively to share your Streamlit apps with the world. ## Embedding with iframes Streamlit Community Cloud supports embedding **public** apps using the subdomain scheme. To embed a public app, add the query parameter `/?embed=true` to the end of the `*.streamlit.app` URL. For example, say you want to embed the [30DaysOfStreamlit app](https://30days.streamlit.app/). The URL to include in your iframe is: `https://30days.streamlit.app/?embed=true`: ```html ``` Here's an example of [@chrieke](https://github.com/chrieke)'s [Prettymapp app](https://chrieke-prettymapp-streamlit-prettymappapp-1k0qxh.streamlit.app/) embedded in a Medium article: ![Example: Embed an app in a Medium article with oEmbed](https://docs.streamlit.io/images/streamlit-community-cloud/oembed.gif) Ensure the platform hosting the embedded Streamlit app supports oEmbed. ## Embed options When [Embedding with iframes](https://docs.streamlit.io/deploy/streamlit-community-cloud/share-your-app/embed-your-app#embedding-with-iframes), Streamlit allows you to specify one or more instances of the `?embed_options` query parameter for granular control over the embedding behavior. Both `?embed` and `?embed_options` are invisible to `st.query_params` and its precursors, `st.experimental_get_query_params`, and `st.experimental_set_query_params`. You can't get or set their values. The supported values for `?embed_options` are listed below: - Show the toolbar at the top right of the app which includes the app menu (more_vert). - Show padding at the top and bottom of the app. - Show the footer reading "Made with Streamlit." (This doesn't apply to Streamlit versions 1.29.0 and later since the footer was removed from the library.) - Show the colored line at the top of the app. - Hide the "skeleton" that appears while an app is loading. - Disable scrolling for the main body of the app. (The sidebar will still be scrollable.) - Open the app with light theme. - Open the app with dark theme. You can also combine the params: ```html /?embed=true&embed_options=show_toolbar&embed_options=show_padding&embed_options=show_footer&embed_options=show_colored_line&embed_options=disable_scrolling ``` ## Build an embed link You can conveniently build an embed link for your app — right from your app! 1. From your app at `your-custom-subdomain.streamlit.app`, click "Share" in the upper-right corner. 2. Click "Embed" to access a list of selectable embed options. 3. Select your embed options and click "Get embed link" to copy the embed link to your clipboard. ![Access embed options from the share button](https://docs.streamlit.io/images/streamlit-community-cloud/share-menu-embed.png) ![Build a customized embed link for your app from the share button](https://docs.streamlit.io/images/streamlit-community-cloud/share-menu-embed-url.png) --- # Source: https://docs.streamlit.io/develop/concepts/app-testing/examples # App testing example ## Testing a login page Let's consider a login page. In this example, `secrets.toml` is not present. We'll manually declare dummy secrets directly in the tests. To avoid [timing attacks](https://en.wikipedia.org/wiki/Timing_attack), the login script uses `hmac` to compare a user's password to the secret value as a security best practice. ### Project summary #### Login page behavior Before diving into the app's code, let's think about what this page is supposed to do. Whether you use test-driven development or you write unit tests after your code, it's a good idea to think about the functionality that needs to be tested. The login page should behave as follows: - Before a user interacts with the app: - Their status is "unverified." - A password prompt is displayed. - If a user types an incorrect password: - Their status is "incorrect." - An error message is displayed. - The password attempt is cleared from the input. - If a user types a correct password: - Their status is "verified." - A confirmation message is displayed. - A logout button is displayed (without a login prompt). - If a logged-in user clicks the **Log out** button: - Their status is "unverified." - A password prompt is displayed. #### Login page project structure ```none myproject/ ├── app.py └── tests/ └── test_app.py ``` #### Login page Python file The user's status mentioned in the page's specifications are encoded in `st.session_state.status`. This value is initialized at the beginning of the script as "unverified" and is updated through a callback when the password prompt receives a new entry. ```python """app.py""" import streamlit as st import hmac st.session_state.status = st.session_state.get("status", "unverified") st.title("My login page") def check_password(): if hmac.compare_digest(st.session_state.password, st.secrets.password): st.session_state.status = "verified" else: st.session_state.status = "incorrect" st.session_state.password = "" def login_prompt(): st.text_input("Enter password:", key="password", on_change=check_password) if st.session_state.status == "incorrect": st.warning("Incorrect password. Please try again.") def logout(): st.session_state.status = "unverified" def welcome(): st.success("Login successful.") st.button("Log out", on_click=logout) if st.session_state.status != "verified": login_prompt() st.stop() welcome() ``` #### Login page test file These tests closely follow the app's specifications above. In each test, a dummy secret is set before running the app and proceeding with further simulations and checks. ```python from streamlit.testing.v1 import AppTest def test_no_interaction(): at = AppTest.from_file("app.py") at.secrets["password"] = "streamlit" at.run() assert at.session_state["status"] == "unverified" assert len(at.text_input) == 1 assert len(at.warning) == 0 assert len(at.success) == 0 assert len(at.button) == 0 assert at.text_input[0].value == "" def test_incorrect_password(): at = AppTest.from_file("app.py") at.secrets["password"] = "streamlit" at.run() at.text_input[0].input("balloon").run() assert at.session_state["status"] == "incorrect" assert len(at.text_input) == 1 assert len(at.warning) == 1 assert len(at.success) == 0 assert len(at.button) == 0 assert at.text_input[0].value == "" assert "Incorrect password" in at.warning[0].value def test_correct_password(): at = AppTest.from_file("app.py") at.secrets["password"] = "streamlit" at.run() at.text_input[0].input("streamlit").run() assert at.session_state["status"] == "verified" assert len(at.text_input) == 0 assert len(at.warning) == 0 assert len(at.success) == 1 assert len(at.button) == 1 assert "Login successful" in at.success[0].value assert at.button[0].label == "Log out" def test_log_out(): at = AppTest.from_file("app.py") at.secrets["password"] = "streamlit" at.session_state["status"] = "verified" at.run() at.button[0].click().run() assert at.session_state["status"] == "unverified" assert len(at.text_input) == 1 assert len(at.warning) == 0 assert len(at.success) == 0 assert len(at.button) == 0 assert at.text_input[0].value == "" ``` See how Session State was modified in the last test? Instead of fully simulating a user logging in, the test jumps straight to a logged-in state by setting `at.session_state["status"] = "verified"`. After running the app, the test proceeds to simulate the user logging out. ### Automating your tests If `myproject/` was pushed to GitHub as a repository, you could add GitHub Actions test automation with [Streamlit App Action](https://github.com/marketplace/actions/streamlit-app-action). This is as simple as adding a workflow file at `myproject/.github/workflows/`: ```yaml # .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: app.py ``` --- # Source: https://docs.streamlit.io/develop/tutorials/execution-flow # Source: https://docs.streamlit.io/develop/api-reference/execution-flow # Execution flow ## Change execution By default, Streamlit apps execute the script entirely, but we allow some functionality to handle control flow in your applications. ### Modal dialog Insert a modal dialog that can rerun independently from the rest of the script. ```python @st.dialog("Sign up") def email_form(): name = st.text_input("Name") email = st.text_input("Email") st.form_submit_button("Sign up") ``` ### Fragment Define a fragment to rerun independently from the rest of the script. ```python @st.fragment(run_every="10s") def fragment(): df = get_data() st.line_chart(df) ``` ### Rerun script Rerun the script immediately. ```python st.rerun() ``` ### Stop execution Stops execution immediately. ```python st.stop() ``` ## Group multiple widgets By default, Streamlit reruns your script everytime a user interacts with your app. However, sometimes it's a better user experience to wait until a group of related widgets is filled before actually rerunning the script. That's what `st.form` is for! ### Forms Create a form that batches elements together with a “Submit” button. ```python with st.form(key='my_form'): name = st.text_input("Name") email = st.text_input("Email") st.form_submit_button("Sign up") ``` ### Form submit button Display a form submit button. ```python with st.form(key='my_form'): name = st.text_input("Name") email = st.text_input("Email") st.form_submit_button("Sign up") ``` ## Third-party components These are featured components created by our lovely community. For more examples and inspiration, check out our [Components Gallery](https://streamlit.io/components) and [Streamlit Extras](https://extras.streamlit.app/)! ### Autorefresh Force a refresh without tying up a script. Created by [@kmcgrady](https://github.com/kmcgrady). ```python from streamlit_autorefresh import st_autorefresh st_autorefresh(interval=2000, limit=100, key="fizzbuzzcounter") ``` ### Pydantic Auto-generate Streamlit UI from Pydantic Models and Dataclasses. Created by [@lukasmasuch](https://github.com/lukasmasuch). ```python import streamlit_pydantic as sp sp.pydantic_form(key="my_form", model=ExampleModel) ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by [@blackary](https://github.com/blackary). ```python from st_pages import Page, show_pages, add_page_title show_pages([ Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:"), ]) ``` ### Custom components [![Image 1: screenshot](https://docs.streamlit.io/images/api/components/autorefresh.jpg)](https://github.com/kmcgrady/streamlit-autorefresh) #### Autorefresh Force a refresh without tying up a script. Created by [@kmcgrady](https://github.com/kmcgrady). ```python from streamlit_autorefresh import st_autorefresh st_autorefresh(interval=2000, limit=100, key="fizzbuzzcounter") ``` ### Pydantic Auto-generate Streamlit UI from Pydantic Models and Dataclasses. Created by [@lukasmasuch](https://github.com/lukasmasuch). ```python import streamlit_pydantic as sp sp.pydantic_form(key="my_form", model=ExampleModel) ``` ### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by [@blackary](https://github.com/blackary). ```python from st_pages import Page, show_pages, add_page_title show_pages([ Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:"), ]) ``` ### Custom components [![Image 2: screenshot](https://docs.streamlit.io/images/api/components/pages.jpg)](https://github.com/blackary/st_pages) #### Streamlit Pages An experimental version of Streamlit Multi-Page Apps. Created by [@blackary](https://github.com/blackary). ```python from st_pages import Page, show_pages, add_page_title show_pages([ Page("streamlit_app.py", "Home", "🏠"), Page("other_pages/page2.py", "Page 2", ":books:"), ]) ``` ## App testing Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ### Ask AI ### Release notes - 2025 - 2024 - 2023 - 2022 - 2021 - 2020 - 2019 ### Deployment issues - How can I deploy multiple Streamlit apps on different subdomains? - How do I deploy Streamlit on a domain so it appears to run on a regular port (i.e. port 80)? - Does Streamlit support the WSGI Protocol? (aka Can I deploy Streamlit with gunicorn?) - How do I increase the upload limit of st.file_uploader on Streamlit Community Cloud? - How do I share apps with viewers outside my organization? - How can I make Streamlit watch for changes in other modules I'm importing in my app? - What browsers does Streamlit support? - Where does st.file_uploader store uploaded files and when do they get deleted? - Widget updating for every second input when using session state - Why does Streamlit restrict nested st.columns? - What is serializable session state? ### Knowledge base - How do I create an anchor link? - Enabling camera access in your browser - How to download a file in Streamlit? - How to download a Pandas DataFrame as a CSV? - How do I upgrade to the latest version of Streamlit? - How do I insert elements out of order? - How can I make st.pydeck_chart use custom Mapbox styles? - How to remove “· Streamlit” from the app title? - How do you retrieve the filename of a file uploaded with st.file_uploader? - Sanity checks - How can I make Streamlit watch for changes in other modules I'm importing in my app? - What is serializable session state? ### Quick reference - Cheat sheet - Release notes - Pre-release features - Roadmap ### Deploy - Concepts - Streamlit Community Cloud - Snowflake - Other platforms ### Knowledge base - FAQ - Installing dependencies - Deployment issues ### Quick reference - Cheat sheet - Release notes - Pre-release features - Roadmap --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/get-started/explore-your-workspace # Explore your workspace If you just [created your account](/deploy/streamlit-community-cloud/get-started/create-your-account) and [connected your GitHub account](/deploy/streamlit-community-cloud/get-started/connect-your-github-account), congrats! You are now signed in and ready to go. If you are joining someone else's workspace you may already see some apps. ## Workspaces Each GitHub account and organization is associated with a workspace in Community Cloud. When you sign in to Community Cloud for the first time, you will land in your personal workspace associated with your GitHub user account. The upper-left corner of Community Cloud shows your current workspace. ### Switching workspaces To switch between workspaces, click the workspace name in the upper-left corner and select a new workspace. Other workspaces are available to you as follows: - When you have write permissions to a repository and the repository owner has joined Community Cloud, you can select the associated workspace. An owner can be a GitHub user or organization. - If someone has shared an app with you through Community Cloud, you will see the app's associated workspace. This is view-only access. ![This workspace is for the user sammy-streamlit, who has access to their personal workspace and another workspace for the organization we-love-streamlit.](/images/streamlit-community-cloud/workspace-empty-switch.png) ## Invite other developers to your workspace Inviting other developers is simple: Just give them write access to your GitHub repository so that you can code together. When they sign in to [share.streamlit.io](https://share.streamlit.io/), they'll have access to your workspace. Streamlit Community Cloud inherits developer permissions from GitHub. When others sign in to Community Cloud, they will automatically see the workspaces they share with you. From there you can all deploy, manage, and share apps together. When a user is added to a repository on GitHub, it will take at most 15 minutes before they can deploy or manage the app on Community Cloud. If a user is removed from a repository on GitHub, it will take at most 15 minutes before their permission to manage the app from that repository is revoked. And remember, whenever anyone on the team updates the code on GitHub, the app will automatically update for you! ## My apps The "My apps" section of your workspace is your base of operations to deploy and manage your apps. When you deploy an app, it is added to this section of your workspace. ### Deploying apps If you already have an app saved to a GitHub repo, you can deploy it directly. Otherwise, Community Cloud provides templates you can use. When you deploy from a template, Community Cloud will fork a project into your GitHub account and deploy from the new fork. This is a convenient way to get started if you haven't already created a Streamlit app. To get started, just click "Create app" in the upper-right corner. To learn more, see [Deploy your app](/deploy/streamlit-community-cloud/deploy-your-app) and [Deploy from a template](/deploy/streamlit-community-cloud/get-started/deploy-from-a-template). ## My profile The "My profile" section of your workspace lets you customize a personal portfolio of Streamlit apps to share with the world. Curate and feature your Streamlit apps to show off your work. ## Explore For inspiration, check out the "Explore" section. This is a gallery of Streamlit apps created by the Streamlit community. Check out popular and trending apps, or search for apps in an area that interests you. --- # Source: https://docs.streamlit.io/develop/tutorials/configuration-and-theming/external-fonts # Use externally hosted fonts and fallbacks to customize your font Streamlit comes with Source Sans as the default font, but you can configure your app to use another font. This tutorial uses variable font files and is a walkthrough of Example 3 from [Customize fonts in your Streamlit app](/develop/concepts/configuration/theming-customize-fonts#example-1-define-an-alternative-font-with-variable-font-files). For an example that uses self-hosted variable font files, see [Use variable font files to customize your font](/develop/tutorials/configuration-and-theming/variable-fonts). For an example that uses self-hosted static font files, see [Use static font files to customize your font](/develop/tutorials/configuration-and-theming/static-fonts). This tutorial uses inline font definitions, which were introduced in Streamlit version 1.50.0. For an older workaround, see [Use externally hosted fonts and fallbacks to customize your font (streamlit<1.50.0)](/develop/tutorials/configuration-and-theming/external-fonts-old). ## Collect your font CSS URLs 1. To collect your URLs to use in later steps, open a text editor. 2. Remember to label the values as you paste them so you don't mix them up. 3. Go to [Google fonts](https://fonts.google.com/). 4. Search for or follow the link to [Nunito](https://fonts.google.com/specimen/Nunito), and select "Get font". 5. To get a link to a style sheet for your font files, in the upper-right corner, select the shopping bag (shopping_bag), and then select "Get embed code". 6. On the right, in the first code block, copy the `href` URL from the third link, and paste it into your text editor. 7. By default, the "Embed Code" page loads with the "Web" tab and `` radio option selected. The first code block is titled, "Embed code in the of your html". The URL is a link to a style sheet and should look like the following text: 8. To remove Nunito from your list and get a clean URL for Space Mono, select the trash can (delete). Then, repeat the previous three steps for [Space Mono](https://fonts.google.com/specimen/Space+Mono). 9. The URL should look like the following text: 10. In your text editor, modify each URL by prepending its font family and a colon separator: 11. Because Space Mono has a space in its name, use single quotes around the font family. These will be inner quotes when the string is later copied into your configuration file. ## Create your app configuration 1. In `your_repository/`, create a `.streamlit/config.toml` file: 2. To set your alternative fonts as the default font for your app, in `.streamlit/config.toml`, add the following text: 3. This sets Nunito as the default for all text in your app except inline code and code blocks, which will be Space Mono instead. If Google's font service is unavailable, the app will fall back to the indicated built-in fonts. ## Build the example To verify that your font is loaded correctly, create a simple app. ### Initialize your app 1. In your_repository, create a file named `streamlit_app.py`. 2. In a terminal, change directories to your_repository, and start your app: 3. Your app will be blank because you still need to add code. 4. In `streamlit_app.py`, write the following: 5. Save your `streamlit_app.py` file, and view your running app. ### Display some text in your app 1. Create a `streamlit_app.py` file in your working directory. 2. In `streamlit_app.py`, add the following text: 3. The example includes "efg" in each line to better show the typographical differences when you run your app. In Space Mono, the italic "f" descends below baseline, but the normal "f" doesn't. Space Mono also has different serifs on its normal and italic "l". --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/manage-your-app/favorite-your-app # Favorite your app Streamlit Community Cloud supports a "favorite" feature that lets you quickly access your apps from your workspace. Favorited apps appear at the top of their workspace with a yellow star (star) beside them. You can favorite and unfavorite apps in any workspace to which you have access as a developer or invited viewer. ## Favoriting and unfavoriting your app You can favorite your app: 1. From your workspace at [share.streamlit.io](https://share.streamlit.io/), hover over your app. If your app is not yet favorited, a star outline (star_border) will appear on hover. 2. Click on the star (star_border) next to your app name to toggle its favorited status. ![Favorite your app directly from your live app](/images/streamlit-community-cloud/favorite-select.png) [Previous: Edit your app](/deploy/streamlit-community-cloud/manage-your-app/edit-your-app) [Next: Reboot your app](/deploy/streamlit-community-cloud/manage-your-app/reboot-your-app) --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/deploy-your-app/file-organization # File organization for your Community Cloud app Streamlit Community Cloud copies all the files in your repository and executes `streamlit run` from its root directory. Because Community Cloud is creating a new Python environment to run your app, you need to include a declaration of any [App dependencies](/deploy/streamlit-community-cloud/deploy-your-app/app-dependencies) in addition to any [Configuration](/develop/concepts/configuration) options. You can have multiple apps in your repository, and their entrypoint files can be anywhere in your repository. However, you can only have one configuration file. This page explains how to correctly organize your app, configuration, and dependency files. The following examples assume you are using `requirements.txt` to declare your dependencies because it is the most common. As explained on the next page, Community Cloud supports other formats for configuring your Python environment. ## Basic example In the following example, the entrypoint file (`your_app.py`) is in the root of the project directory alongside a `requirements.txt` file to declare the app's dependencies. ``` your_repository/ ├── requirements.txt └── your_app.py ``` If you are including custom configuration, your config file must be located at `.streamlit/config.toml` within your repository. ``` your_repository/ ├── .streamlit/ │ └── config.toml ├── requirements.txt └── your_app.py ``` Additionally, any files that need to be locally available to your app should be included in your repository. ### Tip If you have really big or binary data that you change frequently, and git is running slowly, you might want to check out [Git Large File Store (LFS)](https://git-lfs.github.com/) as a better way to store large files in GitHub. You don't need to make any changes to your app to start using it. If your GitHub repository uses LFS, it will _just work_ with Streamlit Community Cloud. ### Next Steps - [Previous: Deploy your app](/deploy/streamlit-community-cloud/deploy-your-app) - [Next: App dependencies](/deploy/streamlit-community-cloud/deploy-your-app/app-dependencies) --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/get-started/fork-and-edit-a-public-app # Fork and edit a public app Community Cloud is all about learning, sharing, and exploring the world of Streamlit. For apps with public repositories, you can quickly fork copies to your GitHub account, deploy your own version, and jump into a codespace on GitHub to start editing and exploring Streamlit code. 1. From a forkable app, in the upper-right corner, click "Fork". 2. Optional: In the "App URL" field, choose a custom subdomain for your app. Every Community Cloud app is deployed to a subdomain on `streamlit.app`, but you can change your app's subdomain at any time. For more information, see [App settings](/deploy/streamlit-community-cloud/manage-your-app/app-settings). 3. Click "Fork!" The repository will be forked to your GitHub account. If you have already forked the repository, Community Cloud will use the existing fork. If your existing fork already has an associated codespace, the codespace will be reused. ![Click Fork to confirm and deploy your app](/images/streamlit-community-cloud/fork-public-hello-deploy.png) 4. Wait for GitHub to set up your codespace. It can take several minutes to fully initialize your codespace. After the Visual Studio Code editor appears in your codespace, it can take several minutes to install Python and start the Streamlit server. When complete, a split screen view displays a code editor on the left and a running app on the right. The code editor opens two tabs by default: the repository's readme file and the app's entrypoint file. ![Click Fork to confirm and deploy your app](/images/streamlit-community-cloud/fork-public-hello-codespace.png) The app displayed in your codespace is not the same instance you deployed on Community Cloud. Your codespace is a self-contained development environment. When you make edits inside a codespace, those edits don't leave the codespace until you commit them to your repository. When you commit your changes to your repository, Community Cloud detects the changes and updates your deployed app. To learn more, see [Edit your app](/deploy/streamlit-community-cloud/manage-your-app/edit-your-app). 5. Edit your newly forked app as desired. For more instructions on working with GitHub Codespaces, see [Edit your app](/deploy/streamlit-community-cloud/manage-your-app/edit-your-app). --- # Source: https://docs.streamlit.io/develop/concepts/architecture/forms # Using forms When you don't want to rerun your script with each input made by a user, [st.form](https://docs.streamlit.io/develop/api-reference/execution-flow/st.form) is here to help! Forms make it easy to batch user input into a single rerun. This guide to using forms provides examples and explains how users interact with forms. ## Example In the following example, a user can set multiple parameters to update the map. As the user changes the parameters, the script will not rerun and the map will not update. When the user submits the form with the button labeled "Update map", the script reruns and the map updates. If at any time the user clicks "Generate new points" which is outside of the form, the script will rerun. If the user has any unsubmitted changes within the form, these will not be sent with the rerun. All changes made to a form will only be sent to the Python backend when the form itself is submitted. ### Execute the process after the form If you need to execute a one-time process as a result of a form submission, you can condition that process on the `st.form_submit_button` and execute it after the form. If you need results from your process to display above the form, you can use containers to control where the form displays relative to your output. ### Use `st.rerun` If your process affects content above your form, another alternative is using an extra rerun. This can be less resource-efficient though, and may be less desirable that the above options. ## Limitations - Every form must contain a `st.form_submit_button`. - `st.button` and `st.download_button` cannot be added to a form. - `st.form` cannot be embedded inside another `st.form`. - Callback functions can only be assigned to `st.form_submit_button` within a form; no other widgets in a form can have a callback. - Interdependent widgets within a form are unlikely to be particularly useful. If you pass `widget1`'s value into `widget2` when they are both inside a form, then `widget2` will only update when the form is submitted. --- # Source: https://docs.streamlit.io/develop/concepts/architecture/fragments # Working with fragments Reruns are a central part of every Streamlit app. When users interact with widgets, your script reruns from top to bottom, and your app's frontend is updated. Streamlit provides several features to help you develop your app within this execution model. Streamlit version 1.37.0 introduced fragments to allow rerunning a portion of your code instead of your full script. As your app grows larger and more complex, these fragment reruns help your app be efficient and performant. Fragments give you finer, easy-to-understand control over your app's execution flow. Before you read about fragments, we recommend having a basic understanding of [caching](/develop/concepts/architecture/caching), [Session State](/concepts/architecture/session-state), and [forms](/develop/concepts/architecture/forms). ## Use cases for fragments ### Fragments vs forms Here is a comparison between fragments and forms: - **Forms**: allow users to interact with widgets without rerunning your app. Streamlit does not send user actions within a form to your app's Python backend until the form is submitted. Widgets within a form can not dynamically update other widgets (in or out of the form) in real-time. - **Fragments**: run independently from the rest of your code. As your users interact with fragment widgets, their actions are immediately processed by your app's Python backend and your fragment code is rerun. Widgets within a fragment can dynamically update other widgets within the same fragment in real-time. ### Fragments vs custom components Here is a comparison between fragments and custom components: - **Components**: are custom frontend code that can interact with the Python code, native elements, and widgets in your Streamlit app. Custom components extend what’s possible with Streamlit. They follow the normal Streamlit execution flow. - **Fragments**: are parts of your app that can rerun independently of the full app. Fragments can be composed of multiple Streamlit elements, widgets, or any Python code. A fragment can include one or more custom components. A custom component could not easily include a fragment! ## Fragments vs caching Here is a comparison between fragments and caching: - **Caching**: allows you to skip over a function and return a previously computed value. When you use caching, you execute everything except the cached function (if you've already run it before). - **Fragments**: allow you to freeze most of your app and just execute the fragment. When you use fragments, you execute only the fragment (when triggering a fragment rerun). Caching saves you from unnecessarily running a piece of your app while the rest runs. Fragments save you from running your full app when you only want to run one piece. ## Limitations and unsupported behavior - Fragments can't detect a change in input values. It is best to use Session State for dynamic input and output for fragment functions. - Using caching and fragments on the same function is unsupported. - Fragments can't render widgets in externally-created containers; widgets can only be in the main body of a fragment. --- # Source: https://docs.streamlit.io/get-started/fundamentals # Fundamental concepts Are you new to Streamlit and want the grand tour? If so, you're in the right place! ## Basic concepts [Basic concepts.](/get-started/fundamentals/main-concepts) Learn the fundamental concepts of Streamlit. How is a Streamlit app structured? How does it run? How does it magically get your data on a webpage? ## Advanced concepts [Advanced concepts.](/get-started/fundamentals/advanced-concepts) After you understand the rerun logic of Streamlit, learn how to make efficient and dynamic apps with caching and Session State. Get introduced to handling database connections. ## Additional features [Additional features.](/get-started/fundamentals/additional-features) Learn about Streamlit's additional features. You don't need to know these concepts for your first app, but check it out to know what's available. [Previous: Installation](/get-started/installation) [Next: Basic concepts](/get-started/fundamentals/main-concepts) --- # Source: https://docs.streamlit.io/develop/tutorials/databases/gcs # Connect Streamlit to Google Cloud Storage This guide explains how to securely access files on Google Cloud Storage from Streamlit Community Cloud. It uses [Streamlit FilesConnection](https://github.com/streamlit/files-connection), the [gcsfs](https://github.com/fsspec/gcsfs) library, and Streamlit's [Secrets management](/develop/concepts/connections/secrets-management). ## Create a Google Cloud Storage bucket and add a file First, [sign up for Google Cloud Platform](https://console.cloud.google.com/) or log in. Go to the [Google Cloud Storage console](https://console.cloud.google.com/storage/) and create a new bucket. Navigate to the upload section of your new bucket: And upload the following CSV file, which contains some example data: [myfile.csv](/images/databases/myfile.csv) ## Enable the Google Cloud Storage API The Google Cloud Storage API is [enabled by default](https://cloud.google.com/service-usage/docs/enabled-service#default) when you create a project through the Google Cloud Console or CLI. Feel free to [skip to the next step](#create-a-service-account-and-key-file). If you do need to enable the API for programmatic access in your project, head over to the [APIs & Services dashboard](https://console.cloud.google.com/apis/dashboard) (select or create a project if asked). Search for the Cloud Storage API and enable it. The screenshot below has a blue "Manage" button and indicates the "API is enabled" which means no further action needs to be taken. This is very likely what you have since the API is enabled by default. However, if that is not what you see and you have an "Enable" button, you'll need to enable the API: ## Create a service account and key file To use the Google Cloud Storage API from Streamlit, you need a Google Cloud Platform service account (a special type for programmatic data access). Go to the Service Accounts page and create an account with "Viewer" permission. If the button "CREATE SERVICE ACCOUNT" is gray, you don't have the correct permissions. Ask the admin of your Google Cloud project for help. After clicking "DONE", you should be back on the service accounts overview. Create a JSON key file for the new account and download it: ## Add the key to your local app secrets Your local Streamlit app will read secrets from a file `.streamlit/secrets.toml` in your app's root directory. Create this file if it doesn't exist yet and add the access key to it as shown below: ```toml # .streamlit/secrets.toml [connections.gcs] type = "service_account" project_id = "xxx" private_key_id = "xxx" private_key = "xxx" client_email = "xxx" client_id = "xxx" auth_uri = "https://accounts.google.com/o/oauth2/auth" token_uri = "https://oauth2.googleapis.com/token" auth_provider_x509_cert_url = "https://www.googleapis.com/oauth2/v1/certs" client_x509_cert_url = "xxx" ``` Add this file to `.gitignore` and don't commit it to your GitHub repo! ## Copy your app secrets to the cloud As the `secrets.toml` file above is not committed to GitHub, you need to pass its content to your deployed app (on Streamlit Community Cloud) separately. Go to the [app dashboard](https://share.streamlit.io/) and in the app's dropdown menu, click on **Edit Secrets**. Copy the content of `secrets.toml` into the text area. More information is available at [Secrets management](/deploy/streamlit-community-cloud/deploy-your-app/secrets-management). As the `secrets.toml` file above is not committed to GitHub, you need to pass its content to your deployed app (on Streamlit Community Cloud) separately. Go to the [app dashboard](https://share.streamlit.io/) and in the app's dropdown menu, click on **Edit Secrets**. Copy the content of `secrets.toml` into the text area. More information is available at [Secrets management](/deploy/streamlit-community-cloud/deploy-your-app/secrets-management). ## Add FilesConnection and gcsfs to your requirements file Add the [FilesConnection](https://github.com/streamlit/files-connection) and [gcsfs](https://github.com/fsspec/gcsfs) packages to your `requirements.txt` file, preferably pinning the versions (replace `x.x.x` with the version you want installed): ```bash # requirements.txt gcsfs==x.x.x st-files-connection ``` ## Write your Streamlit app Copy the code below to your Streamlit app and run it. Make sure to adapt the name of your bucket and file. Note that Streamlit automatically turns the access keys from your secrets file into environment variables. ```python # streamlit_app.py import streamlit as st from st_files_connection import FilesConnection # Create connection object and retrieve file contents. # Specify input format is a csv and to cache the result for 600 seconds. conn = st.connection('gcs', type=FilesConnection) df = conn.read("streamlit-bucket/myfile.csv", input_format="csv", ttl=600) # Print results. for row in df.itertuples(): st.write(f"{row.Owner} has a :{row.Pet}:") ``` See `st.connection` above? This handles secrets retrieval, setup, result caching and retries. By default, `read()` results are cached without expiring. In this case, we set `ttl=600` to ensure the file contents is cached for no longer than 10 minutes. You can also set `ttl=0` to disable caching. Learn more in [Caching](/develop/concepts/architecture/caching). If everything worked out (and you used the example file given above), your app should look like this: ![Finished app screenshot](/images/databases/streamlit-app.png) --- # Source: https://docs.streamlit.io/deploy/streamlit-community-cloud/get-started # Source: https://docs.streamlit.io/develop/concepts/app-testing/get-started # Source: https://docs.streamlit.io/get-started # Get started with Streamlit This Get Started guide explains how Streamlit works, how to install Streamlit on your preferred operating system, and how to create your first Streamlit app! ## Installation [downloading](/get-started/installation) helps you set up your development environment. Walk through installing Streamlit on Windows, macOS, or Linux. Alternatively, code right in your browser with GitHub Codespaces or Streamlit in Snowflake. ## Fundamentals [description](/get-started/fundamentals) introduces you to Streamlit's data model and development flow. You'll learn what makes Streamlit the most powerful way to build data apps, including the ability to display and style data, draw charts and maps, add interactive widgets, customize app layouts, cache computation, and define themes. ## First steps [auto_awesome](/get-started/tutorials) walks you through creating apps using core features to fetch and cache data, draw charts, plot information on a map, and use interactive widgets to filter results. ## Use GitHub Codespaces [rocket_launch](/get-started/installation/community-cloud) if you want to skip past local installation and code right in your browser. This guide uses Streamlit Community Cloud to help you automatically configure a codespace. ## 30 Days of Streamlit 🎈 30 Days of Streamlit 🎈 is a free, self-paced 30 day challenge that teaches you how to build and deploy data apps with Streamlit. Complete the daily challenges, share your solutions with us on Twitter and LinkedIn, and stop by the forum with any questions! [Start the challenge](https://30days.streamlit.app/) ## Still have questions? Our [forums](https://discuss.streamlit.io) are full of helpful information and Streamlit experts. ## Next: Installation [arrow_forward](/get-started/installation) ## Footer © 2025 Snowflake Inc. --- # Source: https://docs.streamlit.io/develop/tutorials/authentication/google # Use the Google Auth Platform to authenticate users Google is one of the most popular identity providers for social logins. You can use the Google Auth Platform with both private and organizational Google accounts. This tutorial configures authentication for anyone with a Google account. For more information, see Google's overview of the [Google Auth Platform](https://support.google.com/cloud/topic/15540269?hl=en&ref_topic=3473162&sjid=576431444945556851-NC) and [OpenID Connect](https://developers.google.com/identity/openid-connect/openid-connect#discovery). ## Prerequisites - This tutorial requires the following Python libraries: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` - You should have a clean working directory called `your-repository`. - You must have a Google account and accept the terms of [Google Cloud](https://console.cloud.google.com/) to use their authentication service. - You must have a project in Google Cloud within which to create your application. For more information about managing your projects in Google Cloud, see [Creating and managing projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects) in Google's documentation. ## Summary In this tutorial, you'll build an app that users can log in to with their Google accounts. When they log in, they'll see a personalized greeting with their name and have the option to log out. Here's a look at what you'll build: ```text . streamlit/secrets.toml [auth] redirect_uri = "http://localhost:8501/oauth2callback" cookie_secret = "xxx" client_id = "xxx" client_secret = "xxx" server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration" ``` ```python import streamlit as st def login_screen(): st.header("This app is private.") st.subheader("Please log in.") st.button("Log in with Google", on_click=st.login) if not st.user.is_logged_in: login_screen() else: st.header(f"Welcome, {st.user.name}") st.button("Log out", on_click=st.logout) ``` ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Deploy your app on Community Cloud When you are ready to deploy your app, you must update your application on Google Cloud and your secrets. The following steps describe how to deploy your app on Community Cloud. 1. Add a `requirements.txt` file to your repository with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `requirements.txt` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community-cloud/deploy-your-app). 4. In your `app settings` in Community Cloud, select "Secrets". 5. Copy the contents of your local `secrets.toml` file, and paste them into your app settings. 6. Change your `redirect_uri` to reflect your deployed app's URL, which you copied earlier in this tutorial. 7. Save and close your settings. 8. Return to the clients page in the Google Auth Platform, and select your client. 9. Under "Authorized redirect URIs", add or update a URI to match your new `redirect_uri`. 10. At the bottom of the page, select "SAVE". 11. Open your deployed app, and test it. Your Google Cloud application's status is still `Testing`. You should be able to log in and out of your app with the personal Google account you entered on the "Audience" page. ## Configure your secrets 1. In `your_repository`, create a `secrets.toml` file with the following lines: ```text streamlit>=1.42.0 Authlib>=1.3.2 ``` 2. Save your `secrets.toml` file. 3. Deploy your app, and copy your app's URL into your text editor. You'll use your app's URL to update your secrets and client configuration in the following steps. For more information about deploying an app on Community Cloud, see [Deploy your app](https://docs.streamlit.io/develop/deploy/streamlit-community --- # Source: https://docs.streamlit.io/develop/api-reference/cli/hello # streamlit hello Run the Hello app, an example Streamlit app included with the Streamlit library. ## Syntax ```bash streamlit hello ``` ## Options The `hello` command accepts configuration options (just like the `run` command does). Configuration options are passed in the form of `--
.