Skip to content

Multipage

Gabriel Tem Pass edited this page May 5, 2024 · 1 revision

Currently there are two main ways to use the component in a multipage app (MPA). Both of them are explained below, with their pros and cons.

Streamlit's structure

The more obvious approach, is to follow Streamlit's MPA structure and use st.switch_page to programmatically switch pages. Here, the st_navbar() function must be called in the main Python file, also known as the entrypoint, and in every Python file inside the pages directory. For example, if the app structure looks like this:

your_repository/
├── pages/
│   ├── page_1.py
│   └── page_2.py
└── home.py

The home.py file serves as the entrypoint, to execute the app with streamlit run home.py, and also as the home page. An important note about the pages is that they need to set the selected parameter to their respective name. Below is the code for each file of this example and the resulting app.

home.py:

import streamlit as st
from streamlit_navigation_bar import st_navbar

st.set_page_config(initial_sidebar_state="collapsed")

page = st_navbar(["Home", "Page 1", "Page 2"])

if page == "Page 1":
    st.switch_page("pages/page_1.py")
if page == "Page 2":
    st.switch_page("pages/page_2.py")

# Home content goes here, for example:
st.write("Foo")

page_1.py:

import streamlit as st
from streamlit_navigation_bar import st_navbar

st.set_page_config(initial_sidebar_state="collapsed")

page = st_navbar(["Home", "Page 1", "Page 2"], selected="Page 1")

if page == "Home":
    st.switch_page("home.py")
if page == "Page 2":
    st.switch_page("pages/page_2.py")

# Page 1 content goes here, for example:
st.write("Bar")

page_2.py:

import streamlit as st
from streamlit_navigation_bar import st_navbar

st.set_page_config(initial_sidebar_state="collapsed")

page = st_navbar(["Home", "Page 1", "Page 2"], selected="Page 2")

if page == "Home":
    st.switch_page("home.py")
if page == "Page 1":
    st.switch_page("pages/page_1.py")

# Page 2 content goes here, for example:
st.write("Baz")

MPA Streamlit [App] [Source]

This approach is the more intuitive one, since it uses Streamlit's official solution for MPA and has all of its benefits. However, when a user clicks to switch to another page, the navbar will briefly glitch. Causing a bad visual experience. The limitation is planned to be fixed in the future, but there is no estimated date for it to happen yet.

Recommended structure

The recommended structure for the app works in a different way, but it is still pretty intuitive. It uses conditions with functions to display the page contents programmatically. Where each function contains the content of a single page, and comes from a Python file in the pages folder. To treat the pages directory as a package that can be imported, there is a __init__.py file inside it, with import statements to automatically load the functions from the modules. This is demonstraded by converting the Streamlit example to the recommended file structure:

your_repository/
├── pages/
│   ├── __init__.py
│   ├── home.py
│   ├── page_1.py
│   └── page_2.py
└── app.py

Notice how the home.py file is just a page now, and app.py is the entrypoint file to execute the app with streamlit run app.py. This is optional, but it is a good practice, because it separates the content from the app setup and configs. Under this structure, st.set_page_config and st_navbar must be called only in the main file, and the functions can be imported using import pages as pg. Below is the code for each file and the resulting app again.

app.py:

import streamlit as st
from streamlit_navigation_bar import st_navbar
import pages as pg

st.set_page_config(initial_sidebar_state="collapsed")

page = st_navbar(["Home", "Page 1", "Page 2"])

if page == "Home":
    pg.home()
elif page == "Page 1":
    pg.page_1()
elif page == "Page 2":
    pg.page_2()

__init__.py:

from .home import home
from .page_1 import page_1
from .page_2 import page_2

home.py:

import streamlit as st

def home():
    # Home content goes here, for example:
    st.write("Foo")

page_1.py:

import streamlit as st

def page_1():
    # Page 1 content goes here, for example:
    st.write("Bar")

page_2.py:

import streamlit as st

def page_2():
    # Page 2 content goes here, for example:
    st.write("Baz")

MPA Recommended [App] [Source]

The main advantage of this approach is having a seamless visual experience when switching pages. It also has less code and is more compartmentalized, which is easier to maintain. But it does not enjoy the features of Streamlit MPA structure, like unique URLs for every page, or the ability to use st.page_link to switch to another page within the app. So, analyze whether this solution meets your needs.

Clone this wiki locally