Build your custom Streamlit file-based page routing


A week ago, I was sitting in an airport cafe, ready to wait 3 hours for a plane from Manchester back to Paris, followed by a 4 hour train trip to the South of France.

Those long business trips are my usual gateway to catch up on "things I want to learn but never have time to". I would load up on hour-long entrepreneurship podcasts and rediscover books about Marketing from Seth Godin.

But the morning in this airport cafe, I stumbled upon Next.js's File-based routing system.

Next.js is one of the most popular front-end frameworks, powering websites like Stripe or The Washington Post.

It extends React's capabilities to simplify building fast and scalable web applications, so I regularly read about its features for frontend practices to bring back into the hands of Data Fans using Streamlit.

In the following figure, each folder containing a `page.js` file becomes an accessible URL segment that displays said file. For example, `app/dashboard/settings/page.js` will be accessible on the `dashboard/settings/` URL.

This seemed a little more versatile than how Streamlit initially built an automatic multipage app from the `pages` folder.

Now that Streamlit enables programmatic creation of multipage navigation, it sounds feasible to look for all the `page.py` files in an `app` folder and convert them to accessible URL paths.

The following code is written inside a top-level `streamlit_app.py` file and ran with `streamlit run streamlit_app.py`. It could be any other name, I'm just using the file name Streamlit Cloud runs by default.

Locate all page.py files

I love the built-in `pathlib` module. Anytime I need to browse folders or manipulate file names + paths, pathlib has the method to help me.

For example, `Path("./app").rglob("page.py")` finds all page.py files in any nested folder from `app` into a generator.

Extract URL path

pathlib preserved the file path for each `page.py` file. I want to remove the `app` and `page.py` parts of the path to form the URL segment.

Therefore I use the `parts` attribute for each file Path to retrieve an array of all components for the path, and removed the first & last part.

Extract a title

Static Site Generators like Docusaurus or Material for MkDocs, usually provide page metadata like title or date of publishing at the top of the file with front matter.

I am not planning to add front matter text as top-level comment of my Python files, instead I use `ast` to parse the source code of every page file to look for the first `st.title` call and use that as the page title for the navigation menu.

Half the AST code was generated by Google Gemini 1.5 Pro, it did way better than I expected on the "You are a Python developer. Use the ast module to find the argument of the first st.title Python function call in a Python file".

Don't worry, full code is provided in a gist at the end of the message

From a list of page.py files to a navigation menu

Now that I have methods to extract URL segments and titles for any page.py file, all left is to extract all information for each page.py file in the `app` folder. And there you have it!

What's next

Fun fact, I thought Partial reruns would be my favorite recent Streamlit feature. Then I found myself amazed by Plotly Chart Selections. But right now, I'm finding programmatic multipage apps to be the most fun and valuable new feature

For example, after a Zoom call with a Linkedin DataFan, I got inspired to build a Streamlit toolbox to work on conversations and recordings out of Microsoft Teams meetings.

Half a day later, I had Azure OpenAI and Google Gemini Pro connections stored into st.session_state inside streamlit_app.py, and 4 different pages using the LLMs to transcribe or summarize Teams videos and conversations. Here's a screenshot below, building multipage Streamlit utilities app never felt so compelling 🌸

Hope this inspires you to build more Streamlit multipage toolboxes to help glue your enterprise processes. Have a nice day DataFan!


Apparently I can embed polls in emails now...let's try this ahah!

Wait wait, what about the Source code??

Brighten your Work with Streamlit/Web Apps and Social Media Videos

Upcoming Youtube tutorials, the latest updates and exclusive resources around Streamlit & friends, GIFs and animations. Directly in your inbox every ~2 weeks.

Read more from Brighten your Work with Streamlit/Web Apps and Social Media Videos

Ever needed to uniquely identify users for your Streamlit app through an email/Google single sign-on page? With version 1.42, Streamlit comes with Native Authentication support through the OpenID Connect protocol. I created a fake Streamlit store app with a sign up button for you to play with Streamlit native authentication through Auth0, an authentication as a service platform that makes it easier to manage multiple social logins like Google, X/Twitter or Linkedin. The app is still live on...

I have suffered 3 weeks on this Google auth in Streamlit thing, my mind is not ready to make a video about it so here's a link to tinker with the source code instead. Bring me to the source code! See below for a longer text recap! Integrating Google OAuth2 Authentication to Streamlit has been an issue for some time, with multiple solutions being developed like streamlit-oauth, st_oauth's prototype by the Streamlit team or streamlit-google-auth. But for the past months, I have been building...

I just heard the Solara team unveiled a new platform to deploy Dash, Solara and Streamlit apps! py.cafe, to share Python apps while on a coffee chat WASM Platforms py.cafe is a new WebAssembly powered solution to host and share Python apps through the power of Pyodide. This is a fancy way to say you can implement a Streamlit meme app in your browser, then copy the URL and send it to a friend, colleague or the CEO of your dream company. Just like this link (hopefully this long weird URL is not...