Navigate Multipage App with Buttons instead of Sidebar

Hi,

I’m new to Streamlit and am building a Multipage App as described here Multipage apps. Rather than using the sidebar to navigate through the pages, I’d like to create a walk-through experience using a “Next Page” button at the bottom of each page. Unfortunately, I haven’t been able to figure out how to do this, other than with a very hacky JS approach that forces a page reload. What is the proper way to do this using the new Streamlit Multipage App functionality?

A minimal example of what I want to do:

multipage_app.py

import streamlit as st

st.header("Main Page")

st.button("Button I want to click to go to next page")

next_page.py (in pages folder)

import streamlit as st

st.header("Next Page")

Thanks a lot for your help!

1 Like

Hey @cbattle!

We don’t have a built-in way to do this right now from Python. But you can use just a normal link via markdown or HTML. E.g. insert this into multipage_app.py:

st.markdown('<a href="/next_page" target="_self">Next page</a>', unsafe_allow_html=True)

This should add a link that navigates to the page in next_page.py. Note that I put in target="_self" here so that the link opens in the same tab. By default, links in Streamlit apps open in a new tab.

Now, this isn’t a button yet! But you can use some custom CSS to style a link like a button. Have a look through this thread. It talks about download buttons (which is not what you want) but the CSS part should be exactly the same for any kind of link.

I’ll also add your request to our internal feedback tracker for multipage apps, so we can think about a better solution for this in the future!

I have the same doubt.
Wondering if it’s possible use the native streamlit multipages not just the st.markdown:

  • The st.markdown will open a new website em users interface. I do not want that.

Maybe it’s possible use CSS to hide the st.sidebar and use “on_click” button to call a function that change the page clicked?
@andfanilo @randyzwitch

Hey jrieke, thanks for your help! Your solution works as advertised, which I appreciate, but the page reloads which kills the session state I was trying to share between the pages. Is there any way to access the page’s st.sidebar state and then set that directly on a button click?

Ah got it! Good point. Hm then I think there’s currently no way to do this. Or at least no easy hack. Maybe @blackary knows some advanced hacks? :wink:

@cbattle This is a pretty hacky solution, but should work to change the page

def switch_page(page_name: str):
    from streamlit import _RerunData, _RerunException
    from streamlit.source_util import get_pages

    def standardize_name(name: str) -> str:
        return name.lower().replace("_", " ")
    
    page_name = standardize_name(page_name)

    pages = get_pages("streamlit_app.py")  # OR whatever your main page is called

    for page_hash, config in pages.items():
        if standardize_name(config["page_name"]) == page_name:
            raise _RerunException(
                _RerunData(
                    page_script_hash=page_hash,
                    page_name=page_name,
                )
            )

    page_names = [standardize_name(config["page_name"]) for config in pages.values()]

    raise ValueError(f"Could not find page {page_name}. Must be one of {page_names}")```
6 Likes

@cbattle There’s also a Streamlit component called streamlit_book that inherently has Next/Prev buttons for navigating multiple pages.

Here are some links to this:

1 Like