The first page in dynamic navigation is loaded every time the app is run

I am building an app. It is not deployed.
I am following instructions on this page Create a dynamic navigation menu - Streamlit Docs.

Every time I attempt to log in, the logout page (according to the instructions it is the first in the navigation menu) is loaded and I get logged out immediately after.

account_pages = [logout_page, settings]

if len(page_dict) > 0:
pg = st.navigation({“Account”: account_pages} | page_dict)

If I move the page to the bottom of the list, everything works fine.
account_pages = [settings, logout_page]

Is this a bug or an app design issue?

Hi @Michael13, welcome to the forum!

There’s a subtle piece of that tutorial which is that if you have signed in with a role, then the default page in the list is set to something different. For example:

respond_1 = st.Page(
    "respond/respond_1.py",
    title="Respond 1",
    icon=":material/healing:",
    default=(role == "Responder"),
)

See the default=(role=="Responder"), which means that if your role is Responder, that will be your default page.

If you log in with any role, then the default page will be set appropriately. If you don’t have a role, then the default page will be the first page in the dictionary, which is log out, so that will run automatically.

So, if you want to avoid automatic logout, you can set a different page to be the default one, or (as you’ve noticed), put the logout page to not be the first page in the list.

Here’s a simplified version of that app, and you can see that because I made “settings” to be the default page, you don’t get logged out by default:

import streamlit as st

if "login_status" not in st.session_state:
    st.session_state.login_status = False


def login():
    if st.button("Login"):
        st.session_state.login_status = True
        st.rerun()


def logout():
    st.session_state.login_status = False
    st.rerun()


logout_page = st.Page(logout, title="Log out", icon=":material/logout:")
settings = st.Page(
    "settings.py", title="Settings", icon=":material/settings:", default=True
)

account_pages = [logout_page, settings]


if st.session_state.login_status:
    pg = st.navigation({"Account": account_pages})
else:
    pg = st.navigation([st.Page(login)])

pg.run()
1 Like

@blackary thanks a lot.
I looked into it, but could not figure it out (that condition in parenthesis evaluating to True). This is what the documentations says:


Now it is clear.
Thanks a lot for your help again!

Sorry, I don’t really understand the question – that documentation is correct and explains what is happening. The default page that is navigated to first is either:

  1. The first st.Page that you pass to st.navigation
  2. OR, whichever st.Page has default=True

If you don’t set default=True on something BESIDES the logout page, and you have that one first, then the first thing that will run is the logout page, so you get logged out immediately. You can avoid this by either setting default=True on a different page, or moving logout to not be the first page.

In the example on the docs that you referenced, they switch default depending on which role you use.

I overlooked this default=True. More specifically I could not figure out that the condition in parenthesis evaluated to boolean. I got confused.

Thanks again for your help.

1 Like

Ah, gotcha. Yeah, I think I’ll suggest to the docs team to make that a bit more explicit – it’s fairly easy to miss what’s happening there.

Thanks. That would help. It is explained. But it would be nice to stress it a bit.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.