Creating a multi-layered page system

Due to a business need, I need to develop a streamlit application which esentially has multiple sets of multipages. I am having trouble creating this with the newest st.navigation, as it only can be used once, not multiple times in the same app.

Esentially, first I need to have a “home page” where there are 5 pages representing different applications (but still running in the same streamlit application). Clicking on any one of these pages will redirect us to another set of pages, unique to each of the 5 tools. I also need a “Return” button that will bring us back to the home page.

I know that st.navigation can be used to create a “dictionary” style navigation, but my use case here is that, once clicking on any one of the 5 applications, I only need those pages to be active.

Is there any solution to this?

The page and navigation can do this.

See the navigation below.

    pg = st.navigation([
        st.Page("home.py", title='Home'),
        st.Page(sports, title="Sports"),
    ])

If sports nav is hit you can create a new sidebar nav.

    pg = st.navigation([
        st.Page(sports_page, title='Sports'),
        st.Page(soccer, title="Soccer"),
        st.Page(basketball, title="Basketball"),
    ])

What you need is a session variable that tracks the nav selected.

if ss.sports:
    pg = st.navigation([
        st.Page(sports_page, title='Sports'),
        st.Page(soccer, title="Soccer"),
        st.Page(basketball, title="Basketball"),
    ])
else:
    pg = st.navigation([
        st.Page("home.py", title='Home'),
        st.Page(sports, title="Sports"),
    ])
pg.run()

Define a session variable sports.

import streamlit as st
from streamlit import session_state as ss


if 'sports' not in ss:
    ss.sports = False

Once the sports nav is pressed, set the sports to true.

def sports():
    ss.sports = True
    st.rerun()

And that would bring us to a sports multipage app, with pages such as basketball with the ability to go back to the home.

def basketball():
    st.title("Basketball")
    if st.button('Back to Main Page'):
        ss.sports = False
        st.rerun()

Complete sample code.

app.py

import streamlit as st
from streamlit import session_state as ss


if 'sports' not in ss:
    ss.sports = False


def sports():
    ss.sports = True
    st.rerun()


def basketball():
    st.title("Basketball")
    if st.button('Back to Main Page'):
        ss.sports = False
        st.rerun()


def soccer():
    st.title("Soccer")
    if st.button('Back to Main Page'):
        ss.sports = False
        st.rerun()


def sports_page():
    st.title("Sports")
    if st.button('Back to Main Page'):
        ss.sports = False
        st.rerun()


if ss.sports:
    pg = st.navigation([
        st.Page(sports_page, title='Sports'),
        st.Page(soccer, title="Soccer"),
        st.Page(basketball, title="Basketball"),
    ])
else:
    pg = st.navigation([
        st.Page("home.py", title='Home'),
        st.Page(sports, title="Sports"),
    ])
pg.run()

home.py

import streamlit as st


st.title('Home')

In the beginning you have this.

After pressing Sports.

After pressing basketball.

You can create page related menu in the left sidebar as per standard procedure given in streamlit. That is creating a pages directory and saving seperate file for each menu option. st.Page - Streamlit Docs

In the respective page file which will appear as menu option on the left side bar, you can define Navigation bar by utilizing a module called hydralit_components. This can be downloaded and installed from GitHub - TangleSpace/hydralit_components: A package of custom components for Streamlit and Hydralit. Can be used directly or in combination with the Hydralit package. . You can create Horizontal menu system for each page. hence with a page/menu option given on the left menu, you would have a seperate menu system for that page showing as horizontal bar on the top of page. hence each vertical menu option on the left side bar you can have individual menu system. See a screenshot below