axiom-coding-agent-setup 1.0.10 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/agent-browser/SKILL.md +55 -0
- package/.agents/skills/developing-with-streamlit/SKILL.md +220 -0
- package/.agents/skills/developing-with-streamlit/skills/building-streamlit-chat-ui/SKILL.md +195 -0
- package/.agents/skills/developing-with-streamlit/skills/building-streamlit-custom-components-v2/SKILL.md +233 -0
- package/.agents/skills/developing-with-streamlit/skills/building-streamlit-custom-components-v2/references/packaged-components.md +212 -0
- package/.agents/skills/developing-with-streamlit/skills/building-streamlit-custom-components-v2/references/state-sync.md +149 -0
- package/.agents/skills/developing-with-streamlit/skills/building-streamlit-custom-components-v2/references/theme-css-variables.md +243 -0
- package/.agents/skills/developing-with-streamlit/skills/building-streamlit-custom-components-v2/references/troubleshooting.md +121 -0
- package/.agents/skills/developing-with-streamlit/skills/building-streamlit-dashboards/SKILL.md +147 -0
- package/.agents/skills/developing-with-streamlit/skills/building-streamlit-multipage-apps/SKILL.md +218 -0
- package/.agents/skills/developing-with-streamlit/skills/choosing-streamlit-selection-widgets/SKILL.md +139 -0
- package/.agents/skills/developing-with-streamlit/skills/connecting-streamlit-to-snowflake/SKILL.md +188 -0
- package/.agents/skills/developing-with-streamlit/skills/creating-streamlit-themes/SKILL.md +486 -0
- package/.agents/skills/developing-with-streamlit/skills/displaying-streamlit-data/SKILL.md +199 -0
- package/.agents/skills/developing-with-streamlit/skills/improving-streamlit-design/SKILL.md +191 -0
- package/.agents/skills/developing-with-streamlit/skills/optimizing-streamlit-performance/SKILL.md +323 -0
- package/.agents/skills/developing-with-streamlit/skills/organizing-streamlit-code/SKILL.md +91 -0
- package/.agents/skills/developing-with-streamlit/skills/setting-up-streamlit-environment/SKILL.md +128 -0
- package/.agents/skills/developing-with-streamlit/skills/using-streamlit-cli/SKILL.md +165 -0
- package/.agents/skills/developing-with-streamlit/skills/using-streamlit-custom-components/SKILL.md +170 -0
- package/.agents/skills/developing-with-streamlit/skills/using-streamlit-layouts/SKILL.md +229 -0
- package/.agents/skills/developing-with-streamlit/skills/using-streamlit-markdown/SKILL.md +207 -0
- package/.agents/skills/developing-with-streamlit/skills/using-streamlit-session-state/SKILL.md +144 -0
- package/.agents/skills/developing-with-streamlit/templates/.gitattributes +3 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/README.md +188 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-companies/pyproject.toml +12 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-companies/streamlit_app.py +365 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-compute/pyproject.toml +12 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-compute/streamlit_app.py +461 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-compute-snowflake/.streamlit/secrets.toml.example +20 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-compute-snowflake/pyproject.toml +11 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-compute-snowflake/snowflake.yml +18 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-compute-snowflake/streamlit_app.py +527 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-feature-usage/pyproject.toml +12 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-feature-usage/streamlit_app.py +307 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-metrics/pyproject.toml +12 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-metrics/streamlit_app.py +426 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-metrics-snowflake/.streamlit/secrets.toml.example +20 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-metrics-snowflake/pyproject.toml +11 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-metrics-snowflake/snowflake.yml +18 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-metrics-snowflake/streamlit_app.py +463 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-seattle-weather/pyproject.toml +12 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-seattle-weather/streamlit_app.py +252 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-stock-peers/pyproject.toml +12 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-stock-peers/streamlit_app.py +342 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-stock-peers-snowflake/.streamlit/secrets.toml.example +20 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-stock-peers-snowflake/pyproject.toml +11 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-stock-peers-snowflake/snowflake.yml +18 -0
- package/.agents/skills/developing-with-streamlit/templates/apps/dashboard-stock-peers-snowflake/streamlit_app.py +384 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/README.md +128 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/_configs/dracula.toml +39 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/_configs/github.toml +37 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/_configs/minimal.toml +39 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/_configs/nord.toml +39 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/_configs/snowflake.toml +42 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/_configs/solarized-light.toml +38 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/_configs/spotify.toml +34 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/_configs/stripe.toml +35 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/_shared/streamlit_app.py +336 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/_templates/pyproject.toml.tmpl +12 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/dracula/.streamlit/config.toml +39 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/dracula/pyproject.toml +10 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/dracula/streamlit_app.py +337 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/github/.streamlit/config.toml +37 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/github/pyproject.toml +10 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/github/streamlit_app.py +337 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/manage.py +332 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/minimal/.streamlit/config.toml +39 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/minimal/pyproject.toml +10 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/minimal/streamlit_app.py +337 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/nord/.streamlit/config.toml +39 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/nord/pyproject.toml +10 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/nord/streamlit_app.py +337 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/snowflake/.streamlit/config.toml +42 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/snowflake/pyproject.toml +10 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/snowflake/streamlit_app.py +337 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/solarized-light/.streamlit/config.toml +38 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/solarized-light/pyproject.toml +10 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/solarized-light/streamlit_app.py +337 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/spotify/.streamlit/config.toml +34 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/spotify/pyproject.toml +10 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/spotify/streamlit_app.py +337 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/stripe/.streamlit/config.toml +35 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/stripe/pyproject.toml +10 -0
- package/.agents/skills/developing-with-streamlit/templates/themes/stripe/streamlit_app.py +337 -0
- package/.agents/skills/fastapi/SKILL.md +436 -0
- package/.agents/skills/fastapi/references/dependencies.md +142 -0
- package/.agents/skills/fastapi/references/other-tools.md +76 -0
- package/.agents/skills/fastapi/references/streaming.md +105 -0
- package/.agents/skills/frontend-design/LICENSE.txt +177 -0
- package/.agents/skills/frontend-design/SKILL.md +42 -0
- package/.agents/skills/gradio/SKILL.md +84 -0
- package/.agents/skills/gradio/references/api-signatures.md +115 -0
- package/.agents/skills/gradio/references/event-listeners.md +130 -0
- package/.agents/skills/gradio/references/examples.md +613 -0
- package/.agents/skills/ui-ux-pro-max/SKILL.md +659 -0
- package/.agents/skills/ui-ux-pro-max/data +1 -0
- package/.agents/skills/ui-ux-pro-max/scripts +1 -0
- package/.env.axiom +8 -0
- package/AGENTS.md +2 -1
- package/README.md +19 -3
- package/bin/cli.js +11 -1
- package/opencode.json +7 -4
- package/package.json +1 -1
- package/skills-lock.json +36 -0
- package/.agents/skills/n8n-patterns/SKILL.md +0 -272
package/.agents/skills/developing-with-streamlit/skills/building-streamlit-multipage-apps/SKILL.md
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: building-streamlit-multipage-apps
|
|
3
|
+
description: Building multi-page Streamlit apps. Use when creating apps with multiple pages, setting up navigation, or managing state across pages.
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Streamlit multi-page apps
|
|
8
|
+
|
|
9
|
+
Structure and navigation for apps with multiple pages.
|
|
10
|
+
|
|
11
|
+
## Directory structure
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
streamlit_app.py # Main entry point
|
|
15
|
+
app_pages/
|
|
16
|
+
home.py
|
|
17
|
+
analytics.py
|
|
18
|
+
settings.py
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Important:** Name your pages directory `app_pages/` (not `pages/`). Using `pages/` conflicts with Streamlit's old auto-discovery API and can cause unexpected behavior.
|
|
22
|
+
|
|
23
|
+
## Main module
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
# streamlit_app.py
|
|
27
|
+
import streamlit as st
|
|
28
|
+
|
|
29
|
+
# Initialize global state (shared across pages)
|
|
30
|
+
if "api_client" not in st.session_state:
|
|
31
|
+
st.session_state.api_client = init_api_client()
|
|
32
|
+
|
|
33
|
+
# Define navigation
|
|
34
|
+
page = st.navigation([
|
|
35
|
+
st.Page("app_pages/home.py", title="Home", icon=":material/home:"),
|
|
36
|
+
st.Page("app_pages/analytics.py", title="Analytics", icon=":material/bar_chart:"),
|
|
37
|
+
st.Page("app_pages/settings.py", title="Settings", icon=":material/settings:"),
|
|
38
|
+
])
|
|
39
|
+
|
|
40
|
+
# App-level UI runs before page content
|
|
41
|
+
# Useful for shared elements like titles
|
|
42
|
+
st.title(f"{page.icon} {page.title}")
|
|
43
|
+
|
|
44
|
+
page.run()
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Note:** When you handle titles in `streamlit_app.py`, individual pages should NOT use `st.title` again.
|
|
48
|
+
|
|
49
|
+
## Navigation position
|
|
50
|
+
|
|
51
|
+
**Few pages (3-7) → Top navigation:**
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
page = st.navigation([...], position="top")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Creates a clean horizontal menu. Great for simple apps. Sections are supported too—they appear as dropdowns in the top nav.
|
|
58
|
+
|
|
59
|
+
**Many pages or nested sections → Sidebar:**
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
page = st.navigation({
|
|
63
|
+
"Main": [
|
|
64
|
+
st.Page("app_pages/home.py", title="Home"),
|
|
65
|
+
st.Page("app_pages/analytics.py", title="Analytics"),
|
|
66
|
+
],
|
|
67
|
+
"Admin": [
|
|
68
|
+
st.Page("app_pages/settings.py", title="Settings"),
|
|
69
|
+
st.Page("app_pages/users.py", title="Users"),
|
|
70
|
+
],
|
|
71
|
+
}, position="sidebar")
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Mixed: Some pages ungrouped:**
|
|
75
|
+
|
|
76
|
+
Use an empty string key `""` for pages that shouldn't be in a section. These ungrouped pages always appear first, before any named groups. Put all ungrouped pages in a single `""` key:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
page = st.navigation({
|
|
80
|
+
"": [
|
|
81
|
+
st.Page("app_pages/home.py", title="Home"),
|
|
82
|
+
st.Page("app_pages/about.py", title="About"),
|
|
83
|
+
],
|
|
84
|
+
"Analytics": [
|
|
85
|
+
st.Page("app_pages/dashboard.py", title="Dashboard"),
|
|
86
|
+
st.Page("app_pages/reports.py", title="Reports"),
|
|
87
|
+
],
|
|
88
|
+
}, position="top")
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Page modules
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# app_pages/analytics.py
|
|
95
|
+
import streamlit as st
|
|
96
|
+
|
|
97
|
+
# Access global state
|
|
98
|
+
api = st.session_state.api_client
|
|
99
|
+
user = st.session_state.user
|
|
100
|
+
|
|
101
|
+
# Page-specific content (title is handled in streamlit_app.py)
|
|
102
|
+
data = api.fetch_analytics(user.id)
|
|
103
|
+
st.line_chart(data)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Global state
|
|
107
|
+
|
|
108
|
+
Initialize state in the main module only if it's needed across multiple pages:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
# streamlit_app.py
|
|
112
|
+
st.session_state.api = init_client()
|
|
113
|
+
st.session_state.user = get_user()
|
|
114
|
+
st.session_state.settings = load_settings()
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Tip:** Use `st.session_state.setdefault("key", default_value)` to initialize values only if they don't exist.
|
|
118
|
+
|
|
119
|
+
**Why main module (for global state):**
|
|
120
|
+
- Runs before every page
|
|
121
|
+
- Ensures state is initialized
|
|
122
|
+
- Single source of truth
|
|
123
|
+
|
|
124
|
+
## Page-specific state
|
|
125
|
+
|
|
126
|
+
Use prefixed keys for page-specific state:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
# app_pages/analytics.py
|
|
130
|
+
if "analytics_date_range" not in st.session_state:
|
|
131
|
+
st.session_state.analytics_date_range = default_range()
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Share elements between pages
|
|
135
|
+
|
|
136
|
+
Put shared UI in the entrypoint (before `page.run()`) so it appears on all pages:
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
# streamlit_app.py
|
|
140
|
+
import streamlit as st
|
|
141
|
+
|
|
142
|
+
pages = [...]
|
|
143
|
+
page = st.navigation(pages)
|
|
144
|
+
|
|
145
|
+
# Shared title
|
|
146
|
+
st.title(f"{page.icon} {page.title}")
|
|
147
|
+
|
|
148
|
+
# Shared sidebar widgets
|
|
149
|
+
with st.sidebar:
|
|
150
|
+
st.selectbox("Theme", ["Light", "Dark"])
|
|
151
|
+
|
|
152
|
+
page.run()
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Programmatic navigation
|
|
156
|
+
|
|
157
|
+
Navigate to another page programmatically:
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
if st.button("Go to Settings"):
|
|
161
|
+
st.switch_page("app_pages/settings.py")
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Create navigation links with `st.page_link`:
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
st.page_link("app_pages/home.py", label="Home", icon=":material/home:")
|
|
168
|
+
st.page_link("https://example.com", label="External", icon=":material/open_in_new:")
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
> **Note:** Prefer `st.navigation` over `st.page_link` for standard navigation. Do not use `st.page_link` to recreate the nav bar you get with `st.navigation`. Only use `st.page_link` when linking to pages from somewhere other than the sidebar, or when building a more complex navigation menu.
|
|
172
|
+
|
|
173
|
+
## Conditional pages
|
|
174
|
+
|
|
175
|
+
Show different pages based on user role, authentication, or any other condition by building the pages list dynamically:
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
# streamlit_app.py
|
|
179
|
+
import streamlit as st
|
|
180
|
+
|
|
181
|
+
pages = [st.Page("app_pages/home.py", title="Home", icon=":material/home:")]
|
|
182
|
+
|
|
183
|
+
if st.user.is_logged_in:
|
|
184
|
+
pages.append(st.Page("app_pages/dashboard.py", title="Dashboard", icon=":material/bar_chart:"))
|
|
185
|
+
|
|
186
|
+
if st.session_state.get("is_admin"):
|
|
187
|
+
pages.append(st.Page("app_pages/admin.py", title="Admin", icon=":material/settings:"))
|
|
188
|
+
|
|
189
|
+
page = st.navigation(pages)
|
|
190
|
+
page.run()
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Common conditions for showing/hiding pages:
|
|
194
|
+
- `st.user.is_logged_in` for authenticated users
|
|
195
|
+
- `st.session_state` flags (roles, permissions, feature flags)
|
|
196
|
+
- Environment variables or secrets
|
|
197
|
+
- Time-based access (e.g., beta features)
|
|
198
|
+
|
|
199
|
+
## Imports from pages
|
|
200
|
+
|
|
201
|
+
When importing from page files in `app_pages/`, always import from the root directory perspective:
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
# app_pages/dashboard.py - GOOD
|
|
205
|
+
from utils.data import load_sales_data
|
|
206
|
+
|
|
207
|
+
# app_pages/dashboard.py - BAD (don't use relative imports)
|
|
208
|
+
from ..utils.data import load_sales_data
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## References
|
|
212
|
+
|
|
213
|
+
- [Multipage apps docs](https://docs.streamlit.io/develop/concepts/multipage-apps)
|
|
214
|
+
- [st.navigation](https://docs.streamlit.io/develop/api-reference/navigation/st.navigation)
|
|
215
|
+
- [st.Page](https://docs.streamlit.io/develop/api-reference/navigation/st.page)
|
|
216
|
+
- [st.session_state](https://docs.streamlit.io/develop/api-reference/caching-and-state/st.session_state)
|
|
217
|
+
- [st.switch_page](https://docs.streamlit.io/develop/api-reference/navigation/st.switch_page)
|
|
218
|
+
- [st.page_link](https://docs.streamlit.io/develop/api-reference/widgets/st.page_link)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: choosing-streamlit-selection-widgets
|
|
3
|
+
description: Choosing the right Streamlit selection widget. Use when deciding between radio buttons, selectbox, segmented control, pills, or other option selection widgets. Helps pick the right widget for the number of options and selection type.
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Streamlit selection widgets
|
|
8
|
+
|
|
9
|
+
The right selection widget for the job. Streamlit has evolved—many old patterns are now anti-patterns.
|
|
10
|
+
|
|
11
|
+
## When to use what
|
|
12
|
+
|
|
13
|
+
Use `st.segmented_control` or `st.pills` when you want all options visible at once. Use `st.selectbox` or `st.multiselect` when options should be hidden in a dropdown.
|
|
14
|
+
|
|
15
|
+
| Widget | Best For |
|
|
16
|
+
|--------|----------|
|
|
17
|
+
| `st.segmented_control` | 2-5 options, single select, all visible |
|
|
18
|
+
| `st.pills` | 2-5 options, multi-select, all visible |
|
|
19
|
+
| `st.selectbox` | Many options, single select, dropdown |
|
|
20
|
+
| `st.multiselect` | Many options, multi-select, dropdown |
|
|
21
|
+
|
|
22
|
+
## Segmented control (options visible, single select)
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
# BAD
|
|
26
|
+
status = st.radio("Status", ["Draft", "Published"], horizontal=True)
|
|
27
|
+
|
|
28
|
+
# GOOD
|
|
29
|
+
status = st.segmented_control("Status", ["Draft", "Published"])
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
For vertical layouts, `st.radio(..., horizontal=False)` is still a great choice.
|
|
33
|
+
|
|
34
|
+
Cleaner, more modern look than horizontal radio buttons.
|
|
35
|
+
|
|
36
|
+
## Pills (options visible, multi-select)
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
# Multi-select with few options
|
|
40
|
+
selected = st.pills(
|
|
41
|
+
"Tags",
|
|
42
|
+
["Python", "SQL", "dbt", "Streamlit"],
|
|
43
|
+
selection_mode="multi"
|
|
44
|
+
)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Can also be used to mimic an "example" widget, especially with `label_visibility="collapsed"`:
|
|
48
|
+
```python
|
|
49
|
+
st.pills("Examples", ["Show me sales data", "Top customers"], label_visibility="collapsed")
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
More visual and easier to use than `st.multiselect` for small option sets.
|
|
53
|
+
|
|
54
|
+
## Selectbox (many options, single select)
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
country = st.selectbox(
|
|
58
|
+
"Select a country",
|
|
59
|
+
["USA", "UK", "Canada", "Germany", "France", ...]
|
|
60
|
+
)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Dropdowns scale better than radio/pills for long lists.
|
|
64
|
+
|
|
65
|
+
## Multiselect (many options, multi-select)
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
countries = st.multiselect(
|
|
69
|
+
"Select countries",
|
|
70
|
+
["USA", "UK", "Canada", "Germany", "France", ...]
|
|
71
|
+
)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Toggle vs checkbox
|
|
75
|
+
|
|
76
|
+
Use `st.toggle` for settings that trigger changes in the app. Reserve `st.checkbox` for forms.
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
# GOOD: Toggle for app settings
|
|
80
|
+
dark_mode = st.toggle("Dark mode")
|
|
81
|
+
show_advanced = st.toggle("Show advanced options")
|
|
82
|
+
|
|
83
|
+
# GOOD: Checkbox in forms
|
|
84
|
+
with st.form("signup"):
|
|
85
|
+
agree = st.checkbox("I agree to the terms")
|
|
86
|
+
st.form_submit_button("Sign up")
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Forms with border=False
|
|
90
|
+
|
|
91
|
+
Remove the default form border for cleaner inline forms. Keep the border for longer forms where visual grouping helps.
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# Inline form without border
|
|
95
|
+
with st.form(key="add_item", border=False):
|
|
96
|
+
with st.container(horizontal=True, vertical_alignment="bottom"):
|
|
97
|
+
st.text_input("New item", label_visibility="collapsed", placeholder="Add item")
|
|
98
|
+
st.form_submit_button("Add", icon=":material/add:")
|
|
99
|
+
|
|
100
|
+
# Longer form - keep the border for visual grouping
|
|
101
|
+
with st.form("signup"):
|
|
102
|
+
st.text_input("Name")
|
|
103
|
+
st.text_input("Email")
|
|
104
|
+
st.selectbox("Role", ["Admin", "User"])
|
|
105
|
+
st.form_submit_button("Submit")
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Custom options in selectbox and multiselect
|
|
109
|
+
|
|
110
|
+
Allow users to add their own options with `accept_new_options`:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
# Works with multiselect
|
|
114
|
+
tickers = st.multiselect(
|
|
115
|
+
"Stock tickers",
|
|
116
|
+
options=["AAPL", "MSFT", "GOOGL", "NVDA"],
|
|
117
|
+
default=["AAPL"],
|
|
118
|
+
accept_new_options=True,
|
|
119
|
+
placeholder="Choose stocks or type your own"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Also works with selectbox
|
|
123
|
+
country = st.selectbox(
|
|
124
|
+
"Country",
|
|
125
|
+
options=["USA", "UK", "Canada"],
|
|
126
|
+
accept_new_options=True,
|
|
127
|
+
placeholder="Select or type a country"
|
|
128
|
+
)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## References
|
|
132
|
+
|
|
133
|
+
- [st.segmented_control](https://docs.streamlit.io/develop/api-reference/widgets/st.segmented_control)
|
|
134
|
+
- [st.pills](https://docs.streamlit.io/develop/api-reference/widgets/st.pills)
|
|
135
|
+
- [st.selectbox](https://docs.streamlit.io/develop/api-reference/widgets/st.selectbox)
|
|
136
|
+
- [st.multiselect](https://docs.streamlit.io/develop/api-reference/widgets/st.multiselect)
|
|
137
|
+
- [st.toggle](https://docs.streamlit.io/develop/api-reference/widgets/st.toggle)
|
|
138
|
+
- [st.checkbox](https://docs.streamlit.io/develop/api-reference/widgets/st.checkbox)
|
|
139
|
+
- [st.form](https://docs.streamlit.io/develop/api-reference/execution-flow/st.form)
|
package/.agents/skills/developing-with-streamlit/skills/connecting-streamlit-to-snowflake/SKILL.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: connecting-streamlit-to-snowflake
|
|
3
|
+
description: Connecting Streamlit apps to Snowflake. Use when setting up database connections, managing secrets, or querying Snowflake from a Streamlit app.
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Streamlit Snowflake connection
|
|
8
|
+
|
|
9
|
+
Connect your Streamlit app to Snowflake the right way.
|
|
10
|
+
|
|
11
|
+
## Use st.connection
|
|
12
|
+
|
|
13
|
+
Always use `st.connection("snowflake")` instead of raw connectors.
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import streamlit as st
|
|
17
|
+
|
|
18
|
+
conn = st.connection("snowflake")
|
|
19
|
+
|
|
20
|
+
# Query data
|
|
21
|
+
df = conn.query("SELECT * FROM my_table LIMIT 100")
|
|
22
|
+
st.dataframe(df)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Why st.connection:**
|
|
26
|
+
- Automatic connection pooling
|
|
27
|
+
- Built-in caching
|
|
28
|
+
- Handles reconnection
|
|
29
|
+
- Works with st.secrets
|
|
30
|
+
|
|
31
|
+
## Caller's rights connection (Streamlit 1.53+)
|
|
32
|
+
|
|
33
|
+
For apps running in Snowflake, use caller's rights to run queries with the viewer's permissions instead of the app owner's:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
conn = st.connection("snowflake", type="snowflake-callers-rights")
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
This is useful when:
|
|
40
|
+
- Different users should see different data based on their Snowflake roles
|
|
41
|
+
- You want row-level security to apply based on the viewer
|
|
42
|
+
- You don't want the app to have elevated permissions
|
|
43
|
+
|
|
44
|
+
## Cached queries
|
|
45
|
+
|
|
46
|
+
Use the built-in `ttl` parameter to cache query results:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from datetime import timedelta
|
|
50
|
+
|
|
51
|
+
conn = st.connection("snowflake")
|
|
52
|
+
|
|
53
|
+
# Cache for 10 minutes
|
|
54
|
+
df = conn.query("SELECT * FROM metrics", ttl=timedelta(minutes=10))
|
|
55
|
+
|
|
56
|
+
# Cache for 1 hour
|
|
57
|
+
df = conn.query("SELECT * FROM reference_data", ttl=3600)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Configure with st.secrets
|
|
61
|
+
|
|
62
|
+
Store credentials in `.streamlit/secrets.toml` (never commit this file).
|
|
63
|
+
|
|
64
|
+
**CRITICAL**: Derive the `account` and `host` values from the user's Snowflake CLI connection config. Run `snow connection list` and use the exact values. A wrong `account` will redirect to the wrong login page.
|
|
65
|
+
|
|
66
|
+
```toml
|
|
67
|
+
# .streamlit/secrets.toml
|
|
68
|
+
[connections.snowflake]
|
|
69
|
+
account = "ORGNAME-ACCTNAME" # from `snow connection list`
|
|
70
|
+
host = "myaccount.snowflakecomputing.com" # from `snow connection list` (include if present)
|
|
71
|
+
user = "your_user"
|
|
72
|
+
authenticator = "externalbrowser"
|
|
73
|
+
warehouse = "your_warehouse"
|
|
74
|
+
database = "your_database"
|
|
75
|
+
schema = "your_schema"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Add to `.gitignore`:
|
|
79
|
+
```
|
|
80
|
+
.streamlit/secrets.toml
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Parameterized queries
|
|
84
|
+
|
|
85
|
+
Use parameters to prevent SQL injection:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
conn = st.connection("snowflake")
|
|
89
|
+
|
|
90
|
+
# Safe: parameterized
|
|
91
|
+
df = conn.query(
|
|
92
|
+
"SELECT * FROM users WHERE region = :region",
|
|
93
|
+
params={"region": selected_region}
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# UNSAFE: string formatting - don't do this
|
|
97
|
+
# df = conn.query(f"SELECT * FROM users WHERE region = '{selected_region}'")
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Write data
|
|
101
|
+
|
|
102
|
+
Use the session for write operations:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
conn = st.connection("snowflake")
|
|
106
|
+
session = conn.session()
|
|
107
|
+
|
|
108
|
+
# Write a dataframe
|
|
109
|
+
session.write_pandas(df, "MY_TABLE", auto_create_table=True)
|
|
110
|
+
|
|
111
|
+
# Execute statements
|
|
112
|
+
session.sql("INSERT INTO logs VALUES (:ts, :msg)", params={...}).collect()
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Multiple connections
|
|
116
|
+
|
|
117
|
+
Define multiple connections in secrets:
|
|
118
|
+
|
|
119
|
+
```toml
|
|
120
|
+
# .streamlit/secrets.toml
|
|
121
|
+
[connections.snowflake]
|
|
122
|
+
account = "prod_account"
|
|
123
|
+
# ... prod credentials
|
|
124
|
+
|
|
125
|
+
[connections.snowflake_staging]
|
|
126
|
+
account = "staging_account"
|
|
127
|
+
# ... staging credentials
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
prod_conn = st.connection("snowflake")
|
|
132
|
+
staging_conn = st.connection("snowflake_staging")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Chat with Cortex
|
|
136
|
+
|
|
137
|
+
Build a chat interface using Snowflake Cortex LLMs:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
import streamlit as st
|
|
141
|
+
from snowflake.cortex import complete
|
|
142
|
+
|
|
143
|
+
st.set_page_config(page_title="AI Assistant", page_icon=":sparkles:")
|
|
144
|
+
|
|
145
|
+
if "messages" not in st.session_state:
|
|
146
|
+
st.session_state.messages = []
|
|
147
|
+
|
|
148
|
+
for msg in st.session_state.messages:
|
|
149
|
+
with st.chat_message(msg["role"]):
|
|
150
|
+
st.write(msg["content"])
|
|
151
|
+
|
|
152
|
+
if prompt := st.chat_input("Ask anything"):
|
|
153
|
+
st.session_state.messages.append({"role": "user", "content": prompt})
|
|
154
|
+
|
|
155
|
+
with st.chat_message("user"):
|
|
156
|
+
st.write(prompt)
|
|
157
|
+
|
|
158
|
+
with st.chat_message("assistant"):
|
|
159
|
+
response = st.write_stream(
|
|
160
|
+
complete(
|
|
161
|
+
"claude-3-5-sonnet",
|
|
162
|
+
prompt,
|
|
163
|
+
session=st.connection("snowflake").session(),
|
|
164
|
+
stream=True,
|
|
165
|
+
)
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
st.session_state.messages.append({"role": "assistant", "content": response})
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
See `building-streamlit-chat-ui` for more chat patterns (avatars, suggestions, history management).
|
|
172
|
+
|
|
173
|
+
## Python 3.12+ dependency caveat
|
|
174
|
+
|
|
175
|
+
`streamlit[snowflake]` gates `snowflake-connector-python` on `python_version < "3.12"`. On Python 3.12+, the connector is silently skipped and you get `No module named 'snowflake'` at runtime. Always add `snowflake-connector-python>=3.3.0` as an explicit dependency in `pyproject.toml`:
|
|
176
|
+
|
|
177
|
+
```toml
|
|
178
|
+
dependencies = [
|
|
179
|
+
"snowflake-connector-python>=3.3.0",
|
|
180
|
+
"streamlit[snowflake]>=1.54.0",
|
|
181
|
+
]
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## References
|
|
185
|
+
|
|
186
|
+
- [st.connection](https://docs.streamlit.io/develop/api-reference/connections/st.connection)
|
|
187
|
+
- [SnowflakeConnection](https://docs.streamlit.io/develop/api-reference/connections/st.connections.snowflakeconnection)
|
|
188
|
+
- [st.secrets](https://docs.streamlit.io/develop/api-reference/connections/st.secrets)
|