Streamlit Supabase Connection
Use Supabase Storage, Database, and Auth from Streamlit with Streamlit-aware caching and browser-session-safe authentication.
Open the interactive demo · Read the guides · View the changelog
Why use it?
- Use
st.connection()and Streamlit secrets for Supabase configuration. - Cache Storage and Database reads with familiar
ttlvalues such as"10m". - Keep Supabase Auth tokens isolated to the current Streamlit browser session.
- Upload
st.file_uploader()results without first writing them to the app server. - Normalize Storage paths and infer common MIME types automatically.
Requirements
| Component | Supported version |
|---|---|
| Python | 3.10 or newer |
| Streamlit | 1.62.0 or newer |
| Supabase Python | 2.22.0 or newer |
Quickstart
Install the package:
pip install st-supabase-connection
Add your project URL and publishable key to .streamlit/secrets.toml:
[connections.supabase_connection]
SUPABASE_URL = "https://your-project.supabase.co"
SUPABASE_PUBLISHABLE_KEY = "sb_publishable_..."
Create the connection and make a cached read:
import streamlit as st
from st_supabase_connection import SupabaseConnection
connection = st.connection(
"supabase_connection",
type=SupabaseConnection,
)
buckets = connection.list_buckets(ttl="10m")
st.write(buckets)
The legacy SUPABASE_KEY setting is still supported. New user-facing apps should use a Supabase publishable key. Never use a secret or service_role key for user-scoped operations because those keys bypass Row Level Security.
You can also supply SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY as environment variables, or pass url= and key= to st.connection().
Choose the right client
Streamlit connection objects are cached resources and may be shared between browser sessions. Choose the client based on whether the operation depends on a signed-in user.
| Use case | Recommended API |
|---|---|
| Public or anonymous cached reads | The shared connection and its cached helpers |
| Supabase Auth | connection.session_client().auth |
| Reads or writes protected by the signed-in user's RLS policies | The same connection.session_client() used for sign-in |
| Privileged administrative work | A separate, secured backend using a secret key—not a user-facing app flow |
Create the session-scoped client inside the Streamlit script:
supabase = connection.session_client()
Reuse that client for Auth and user-specific operations. Do not put it in a module-level variable, st.cache_resource, or another global cache.
Caching behavior
There are two different kinds of ttl:
Where ttl is set |
What it controls |
|---|---|
st.connection(..., ttl=...) |
How long Streamlit keeps the connection object |
connection.list_buckets(ttl=...), connection.download(ttl=...), or execute_query(..., ttl=...) |
How long the returned result is cached |
In most apps, omit ttl from st.connection() and set a finite ttl on reads that can change:
from st_supabase_connection import execute_query
countries = execute_query(
connection.table("countries").select("id, name").order("name"),
ttl="10m",
)
st.dataframe(countries.data)
Do not cache Auth calls. For inserts, updates, upserts, and deletes, call Supabase's .execute() directly or pass ttl=0 to execute_query().
See the caching guide for cache scope, user-specific queries, and invalidation considerations.
Common workflows
Upload from st.file_uploader
The uploaded file is handled in memory; it does not need to be copied to the app server first.
uploaded_file = st.file_uploader("Choose a file")
if uploaded_file is not None and st.button("Upload"):
connection.upload(
bucket_id="documents",
source="local",
file=uploaded_file,
destination_path=f"uploads/{uploaded_file.name}",
overwrite="false",
)
st.success("Upload complete")
Query the database
Use the shared connection for anonymous reads:
from st_supabase_connection import execute_query
response = execute_query(
connection.table("countries").select("id, name").limit(20),
ttl="5m",
)
st.dataframe(response.data)
Use the session client for rows protected by a signed-in user's RLS policies:
supabase = connection.session_client()
response = supabase.table("private_profiles").select("*").execute()
st.dataframe(response.data)
Sign in an existing user
supabase = connection.session_client()
email = st.text_input("Email")
password = st.text_input("Password", type="password")
if st.button("Sign in"):
supabase.auth.sign_in_with_password(
{"email": email, "password": password}
)
st.success("Signed in")
After sign-in, use the same supabase client for all operations that must carry the user's JWT.
Guides and recipes
- Storage recipes: buckets, uploads, downloads, object management, and signed URLs
- Database recipes: cached reads, joins, filters, writes, RLS, and Data API access
- Authentication and security: keys, sign-in, session isolation, sign-out, and user-scoped queries
- Caching: connection lifetime, result lifetime, and cache-safe writes
- Upgrade notes: behavioral changes and migration guidance
Supported functionality
The connection includes Streamlit-friendly wrappers for commonly used Storage operations:
- Bucket management:
list_buckets(),get_bucket(),create_bucket(),update_bucket(),empty_bucket(), anddelete_bucket() - Objects:
upload(),download(),list_objects(),move(), andremove() - URLs:
get_public_url(),create_signed_urls(),create_signed_upload_url(), andupload_to_signed_url() - Database:
table()and the cachedexecute_query()helper - Auth and other user-scoped Supabase APIs:
session_client()
Because session_client() returns the complete Supabase Python client, it can also be used for Functions, Realtime, and other SDK features that must carry the current user's session.
Upgrading to 2.2.0
Version 2.2.0 requires Python 3.10+, Streamlit 1.62.0+, and Supabase Python 2.22.0+.
Apps using Auth should replace process-shared access:
# Deprecated
connection.auth.sign_in_with_password(credentials)
with a session-scoped client:
supabase = connection.session_client()
supabase.auth.sign_in_with_password(credentials)
connection.auth and cached_sign_in_with_password() remain available for compatibility but are deprecated. The latter no longer caches its result and ignores ttl.
See the 2.2.0 changelog for the complete migration notes.
Development
Install the project and demo dependency, then run the library and demo tests:
python -m pip install --editable . streamlit-extras
python -m unittest discover --start-directory tests --verbose
The CI workflow tests Python 3.10–3.14 against the minimum and latest supported Streamlit releases.
Issues and pull requests are welcome in the GitHub repository.
Acknowledgements
This connector builds on Streamlit, Supabase Python, and the work of the Supabase open-source community.
If the project helps you, you can sponsor it on GitHub or buy me a coffee.
Release files for st-supabase-connection 2.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| st_supabase_connection-2.2.0.tar.gz | 35.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| st_supabase_connection-2.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 47.3 kB
Release files / st_supabase_connection-2.2.0.tar.gz
| Download URL | st_supabase_connection-2.2.0.tar.gz |
|---|---|
| Size | 35.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8d3b5f45e5bcead761630d04f2dcab8502c7718bebd74e40c9abf89385af8a1b
|
|
BLAKE2b-256 checksum How to use checksums |
96e08870c0b9dd76820ed92f3f43760994ed2fe204776691c4e27e8b322b2abf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 29, 2026.
Transparency logRelease files / st_supabase_connection-2.2.0-py3-none-any.whl
| Download URL | st_supabase_connection-2.2.0-py3-none-any.whl |
|---|---|
| Size | 11.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
423e4562f9ff9864e64859e7a9358e6fa124f08590c34e80519186f73b278b5a
|
|
BLAKE2b-256 checksum How to use checksums |
eb626d4bc7af333058971b165a43b5a25d9190adce6aef39de03a9f6082c3d72
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 29, 2026.
Transparency log