Streamlit Super App library released (easy multipage, persistent state)

I’m SUPER happy to announce a new library that makes super easy to create a multi app / multi page super app!

I recently found about Streamlit and fell in love instantly. The idea to control React with python is wonderfull, but, the more i tested, the more i ran into issues.

I wanted to create a big application with many apps inside, but i was not happy with the default router Streamlit provides, so i started this new project to make it easy and have a beautiful navigation system.

So with this file structure:
Captura de tela 2023-11-04 221508

This was possible:

demo:

repository:

pypi:

I hope you like it!

9 Likes

Wow! Thanks for this nice library

1 Like

I hope you all like it! The idea is to make things even simpler, i just need to work more on the docs on how to personalize the pages.
for example, if you want a radio/selectbox to navigate, put this in a index page

SIDEBAR = “radio”

1 Like

Hi, really nice library! I’ve been looking into ways to store a dataframe in a session. So i’m certainly going to play with it. Continuing with that idea do you think it would be possible to link a session to a specific user?
My endgoal is for a user to be able to continue their work even after refreshing their browser. Like when they come back into the app, have an overview of the stored sessions and select one to continue.

1 Like

Yes! Actually, the library is just missing a piece of the puzzle to make it work, i’m still finding a good way to save and retrieve a session key in the cookies or the localstorage.
If you want that right now, before running streamlit_superapp.run(), you can store a session_id in the session_state.

for example (version >=1.1.1):

app.py

import streamlit as st
import streamlit_superapp
from streamlit import session_state as ss

users = [
    {
        "user_id": "1",
        "user_name": "wilianzilv",
        "password": "123",
    },
    {
        "user_id": "2",
        "user_name": "NicolasD",
        "password": "321",
    },
]


def authenticate():
    with st.form("auth"):
        username = st.text_input("Username")
        password = st.text_input("Password", type="password")

        if st.form_submit_button("Login"):
            for user in users:
                if user["user_name"] == username and user["password"] == password:
                    ss.session_id = user["user_id"]
                    st.rerun()
                    return
            st.error("Incorrect username or password")


def main():
    if "session_id" not in ss:
        authenticate()
        return

    streamlit_superapp.run()


main()

Hi, thanks for the code snippet an the info!. I’ll certainly try it out!

1 Like

Great project! :smile:

What about integrating a dedicated component for the navigation?

For example you could use this:

It would be nice to give some way to fully customize the navigation, i think this might already work with some coding before superapp.run like the authentication example.

if you import Navigation you can get the root page and its list of children:

root_children = Navigation.root().children

selection_path = # the logic to display streamlit-option-menu and get a new path

current_path = Navigation.current_path()

if selection_path != current_path:
    Navigation.go(selection_path)

streamlit_superapp.run()

@wilianzilv So good. Quick Qs… 1. does your layout work independently of Streamlit’s native column/container, nested column/container, page config layouts? 2. Do theme changes carry through the entire app?

Tried exploring it. It is fun.

Fig. 1

Fig. 2

Fig. 3

Fig. 4

Breadcrumbs can navigate the pages.

Thanks! It uses native streamlit components in the sidebar (buttons, selectbox, radio) and for the index page i made a component from scratch based on this repo:

This custom made component follows the streamlit theme colors, except if your theme is based on dark theme. If your theme is based on dark, the background color of the card is fixed to rgb(26, 28, 36)

1 Like

Amazing demo! I really like the idea to put breadcrumbs, that is something that could enhance even more the experience and thats something that i would like to implement on this project.

Also for the description, would be nice to have to further customize the cards

SMALL_DESCRIPTION = “…”
LARGE_DESCRIPTION = “…”

1 Like

Hi Wilian!

Thanks so much for your work on this. Lots of potential!

However, I’ve been trying to use grid from streamlit_extras and run into issues. Any idea why? https://arnaudmiribel.github.io/streamlit-extras/extras/grid/ Get the same error in my version of superapp and in your original example/demo app:

File "/Users/***/lib/python3.11/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 534, in _run_script
    exec(code, module.__dict__)
File "/Users/***/app.py", line 128, in <module>
    streamlit_superapp.run()
File "/Users/***/lib/python3.11/site-packages/streamlit_superapp/__init__.py", line 37, in run
    Navigation.initialize()
File "/Users/***/app.py", line 63, in _new_navigation_initialize
    Navigation.render_page(page)
File "/Users/***/lib/python3.11/site-packages/streamlit_superapp/navigation.py", line 150, in render_page
    return page.main(**params)
           ^^^^^^^^^^^^^^^^^^^
File "/Users/***/pages/situ/__init__.py", line 15, in main
    my_grid = grid(2, [2, 4, 1], 1, 4, vertical_align="bottom")```

Can you show me the entire /pages/situ/__init__.py file?

Sure! Just started it, so nothing much in it:

import streamlit as st
# from streamlit_elements import elements, mui, html
from streamlit_extras import grid

NAME = " " # Optional
DESCRIPTION = ""  # Optional
ICON = " " # Optional
TAG = ''



# main function is required
def main():
    st.write("Hello")
    my_grid = grid(2, [2, 4, 1], 1, 4, vertical_align="bottom")
    # my_grid.selectbox("Hello",["a","b","c"]) 

Oh, the problem is how you are importing grid.
grid is a module, you need to import the function grid from the module grid (a bit confusing).

import it like this:

from streamlit_extras.grid import grid

Ah, thanks!

Next update is getting hot!

1 Like

Hello @ferdy, i just released version 1.1.31.
Breadcrumbs are now available.

And now if you run with this settings the sidebar doesn’t open if its not used:

app.run(hide_home_button=True, hide_back_button=True)
3 Likes

Streamlit with you (at this early stage) can already compete with astro framework in creating blogs with ease. Create blog pages in markdown, put it in a specific directory and we are done.

1 Like