New package st-pages: change page names and icons in sidebar without changing filenames

I love multipage apps, but donā€™t really prefer having to move/rename files in order to change their name, order or icon in the sidebar. I especially donā€™t like adding emojis to filenames.

Iā€™ve been doing a number of experiments about different ways multipage apps could work differently, and have combined some of those into a new package st-pages.

Example usage:

from st_pages import Page, show_pages, add_page_title

# Optional -- adds the title and icon to the current page
add_page_title()

# Specify what pages should be shown in the sidebar, and what their titles 
# and icons should be
show_pages(
    [
        Page("streamlit_app.py", "Home", "šŸ "),
        Page("other_pages/page2.py", "Page 2", ":books:"),
    ]
)

PyPI: st-pages Ā· PyPI
GitHub: GitHub - blackary/st_pages: An experimental version of Streamlit Multi-Page Apps
Example app (basic): https://st-pages.streamlit.app/
Example app (with sections): https://st-pages-sections.streamlit.app/

If you want to give this a try, please do! Feedback is welcome on this post, or on GitHub.

28 Likes

Thanks for adding it to the Tracker :heart:

Also looks awesome, need to try this cough video idea cough !

5 Likes

Great addition also gives a tree view look & feelā€¦

1 Like

Hi @blackary, lovely component!

Just 2 points:

  1. I get a flicker each time a menu option is chosen. I guess itā€™s due to the streamlit rerun - donā€™t know if that can be done away with.
  2. Can a separate component be made just for the left pane (menu) with a folding option (i.e. If Cool apps is clicked, the display of menu options ā€˜Example Fourā€™ and ā€˜Example Twoā€™ are toggled)? (Hopefully, writing custom Streamlit components will get easier in time).

Cheers

2 Likes

@Shawn_Pereira

  1. Yeah, the flicker is unfortunate but unavoidable for now, as Iā€™m just using css to add the indentation, and thereā€™s a slight delay before it actually gets applied to each new page. Iā€™d love to figure out a way to make it permanent.

  2. Yes, that would be nice. For now, this is a fairly thin wrapper around the existing MPA, so that we get the nice url changes, etc. for free. I agree that something like that would be great, but would be tough to get the same url behavior.

3 Likes

This is a great addition, I was able to delete a lot of code by using it. One thing that Iā€™ve noticed is that sometimes when I start my app, the first page isnā€™t selected and there is no display in the main area of my app. I have to click on the first (or any) icon in the sidebar to see some content.

3 Likes

This should be Streamlitā€™s default design, itā€™s so much better, thanks for this package.

3 Likes

@rickspada Yeah, I have seen that issue sometimes as well, and havenā€™t figured out a workaround yet. The good news is that it should work for all future users of the app once itā€™s loaded the page list once.

2 Likes

Thank you, is it possible to make the section also clickable.
Thanks.

1 Like

Thanks @blackary, this is very cool!

A quick question: how hard would it be to make this per-user with your current codebase? One problem with the official implementation of multi-page apps is that one cannot limit the page visibility depending on the user, which was possible with the old st.radio / st.selectbox multi-page hack, and for a second there I was really excited that this package would solve that.

1 Like

@Sai_SaiGraph It is definitely possible, but right now the section is just a placeholder, not an actual page. Would you like to be able to specify an actual page of content, or have it be auto-generated somehow?

1 Like

Hi @ennui, I would love to be able to extend this to be able to dynamically specify the pages that are visible to each user, but havenā€™t found a clean way to do that yet. Iā€™ll probably keep looking for a way to do that, and am very open to contributions if anyone has any ideas.

2 Likes

I m having trouble making sections. Is there any trick? I have tried the code and toml versions, without success. Sections are show, but there is no indentation. The simplest code that replicate this :

from st_pages import Page, Section, add_page_title, show_pages

add_page_title()

show_pages([
    Section(name="Section1", icon=":books:"),
    Page("page1.py", "Page 1", ":notebook:"),
    Page("page2.py", "Page 2", ":blue_book:"),
    Section(name="Section2", icon=":bar_chart:"),
    Page("page3.py", "Page 3", ":bar_chart:"),
])
3 Likes

@Rafael_Del_Rey Do you see any error messages while itā€™s running? What version of st-pages do you have installed? I tried a fresh install of st-pages in a new environment with your code, and it worked for me.

1 Like

VocĆŖ sabe se Ć© possĆ­vel adicionar icons de outras fontes?

1 Like

Hi @blackary , is it possible to put two emojis side by side for the page icons?

1 Like

@mmazzarino Right now only unicode icons are supported (though if someone has a clever idea for supporting other sources of icons, I would love it), either by pasting them in directly, or with the :icon-name: syntax.

1 Like

Hi @DebayanPaul93, it is possible, though with the default styling it doesnā€™t work very well. If you just paste in two icons, like :house::carrot:, add add the following line to all your pages, it seem to work fine:

st.markdown(
    """
<style>
    [data-testid="stSidebar"] span:first-child { {
        width: initial !important;
    }
</style>
    """,
    unsafe_allow_html=True,
)

If others are interested in this behavior, I could also bake this into the library, but I donā€™t know if itā€™s a very common use-case.

1 Like

Hi @blackary , Thanks for the hack! I will test it out. My use case in the multi-page apps is that it puts a checkmark emoji next to the existing emoji when the user provides all required inputs in that page to indicate that page has been filled. My app is basically collection a lot of user inputs in multiple pages and doing a heavy calculation at the final page of the app. I wanted to inform the user before they proceed to calculation step, all required inputs are provided else they can check the page where inputs are missing.

1 Like

Hi @DebayanPaul93, ah, that is a very interesting idea. Unfortunately, this library is not currently well-suited for dynamically updating the page list or icons on a per-user basis. Because it simply piggy-backs on the existing Streamlit behavior, which is to maintain a global cache of pages in the app, if one user changes the list of pages, or their appearance, it will change for all users. I am very interested in solving the general problem of dynamically altering the page list on a per-user basis, but I donā€™t have a great way to do it yet.

1 Like