Multi-page app doesn't have independent user sessions

Hi,

I have a multi page app that is much larger than the given code snippet, I have reduced it to its simplest building blocks as a copy paste workable piece of code that shows my issue.

import panel as pn
import param
from panel.theme import DefaultTheme


class NavigationBar(param.Parameterized):

    def __init__(self, app_routes_titles, **params):
        super().__init__(**params)
        self.app_routes_titles = app_routes_titles
        self.base_urls = list(self.app_routes_titles.keys())
        self.url_parameters = {}

        # Create the buttons
        self.buttons = self._create_buttons()

        # The panel row object to show the navigation buttons
        self.nav_row = pn.Row(*self.buttons, width_policy="max")

    def _create_buttons(self):
        buttons = []
        button_type = "primary"  # first button
        for url, title in self.app_routes_titles.items():
            button = pn.widgets.Button(
                name=title,
                button_type=button_type,
                height=50,
                width=150,
                margin=(0, 0, 0, 0),
            )
            button_type = "light"  # all other buttons
            button.js_on_click(code=f"window.location.href = '{url}';")
            # Attach the route as a tag for identifying later
            button.tags = [url]
            buttons.append(button)
        return buttons

    def colour_btn(self, active_page_route):
        for btn in self.buttons:
            tag = next(iter(btn.tags), None)
            btn.button_type = "primary" if tag == active_page_route else "light"


class Sidebar(param.Parameterized):

    def __init__(self, page_route, **params):
        super().__init__(**params)
        self.page = page_route
        self.selector = pn.widgets.Select(options=["1", "2", "3"])

    def get_sidebar_col(self):
        """Return the panel column of sidebar objects."""
        # Append sidebar objects
        sidebar_col = pn.Column(
            self.selector,
            self.page
        )
        return sidebar_col


class BasePage(param.Parameterized):

    def __init__(self, template, sidebar, navigation_bar, **params):
        super().__init__(**params)
        self.navigation_bar = navigation_bar
        self.template = template
        self.template.sidebar.append(sidebar.get_sidebar_col())
        # Other common set up for both pages
        self.template.main.append(navigation_bar.nav_row)


class Page1(BasePage):

    def __init__(self, template, sidebar, navigation_bar):
        self.template = template
        self.main_area = pn.Column("This is the main content of page 1")
        self.template.main.append(self.main_area)
        super().__init__(self.template, sidebar, navigation_bar)


class Page2(BasePage):

    def __init__(self, template, sidebar, navigation_bar):
        self.template = template
        self.main_area = pn.Column("This is the main content of page 2")
        self.template.main.append(self.main_area)
        super().__init__(self.template, sidebar, navigation_bar)


def create_route(page_route, page_class, app_titles):
    print("CREATING ROUTE")

    def route_function():
        print("EXECUTING ROUTE FUNCTION")
        print(f"curdoc session id: {pn.state.curdoc.session_context.id}")
        print(f"Session info: {pn.state.session_info}")
        nav_bar_cls = NavigationBar(app_titles)
        nav_bar_cls.colour_btn(page_route)
        template = pn.template.MaterialTemplate(
            title="Multi Page App", theme=DefaultTheme, busy_indicator=None
        )
        sidebar = Sidebar(page_route)
        page = page_class(template, sidebar, nav_bar_cls)
        return page.template

    return route_function


def main():
    app_routes_titles = {
        "/": (Page1, "Page 1"),
        "/2": (Page2, "Page 2")
    }
    app_titles = {
        page_route: page_tuple[1]
        for (page_route, page_tuple) in app_routes_titles.items()
    }
    app_routes = {
        page_route: create_route(page_route, page_tuple[0], app_titles)
        for (page_route, page_tuple) in app_routes_titles.items()
    }

    pn.serve(
        app_routes,
        title="Multi Page App",
        port=8000,
        admin=True,
        location=True,
        show=True
    )


if __name__ == "__main__":
    main()

The app is going to be hosted on an azure web app service. The issue I have is that the each time you navigate to a different page, it is a new session. This means that the sidebar, nav bar and template are recreated on load of every single page. What I would like is that the user keeps the same sidebar instance across every page. I thought this would be possible because I mistakenly thought that the user would be in the same session (rather than a new one on load of every page).

Is there any way to adapt this code so that a user will recieve the same sidebar across every page? I am thinking I may have to link all the values that I need in the sidebar into the URL and then pass them to the new page. If I make the sidebar creation outside of route_function, then it is shared by all sessions and so one user selecting a value in the selector will cause another user to see those changes (not what I want).

@Marc I know you did the multi page app documentation - and I tried to follow this by making the pn.serve use routes of urls and functions (not instances) that look like:
{"": route_function, “\2”: route_function}

One option is to load your urls in an iframe, this way the sidebar never changes.