Multi Page Streamlit Application - Code-A2Z/jarvis GitHub Wiki
📑 Multi Page Streamlit Application!
Jarvis - An AI-Powered application with streamlit interface is built using multi-page functionality to handle a wide range of tasks.
The different pages in streamlit interface are categorized on the basis of their functionality like,
-
There are 5 categories right now!
- Account
- Automations
- Models
- Programs
- Admin Control
-
These categories consist some range of pages based on their functionality like,
- API based programs
- Image generator programs
- Recommendation models
- Health care models
- Messenger automations
- Coding automations, etc.
camelToReadable.py
— Helper Module
Converts the name of the modules from camel case letters to readable format.
def camelToReadable(camelCaseName):
readableName = ''.join([' ' + char if char.isupper() else char for char in camelCaseName]).strip()
return readableName.title()
getFolder.py
— Helper Module
Scans a parent directory and lists folders as pages.
import os
import streamlit as st
from src.helpers.camelToReadable import camelToReadable
def getFolders(MODULE_FOLDER_PATH):
try:
files = [f for f in os.listdir(MODULE_FOLDER_PATH) if os.path.isdir(os.path.join(MODULE_FOLDER_PATH, f)) and not f.startswith('__')]
except FileNotFoundError:
st.error("The specified directory does not exist.")
return {}
folders = {}
for folder in files:
readable_name = camelToReadable(folder)
folders[readable_name] = folder
return folders
getModules.py
— Helper Module
Reads all
.py
files in a folder and maps them to user-readable module names.
import os
import streamlit as st
from src.helpers.camelToReadable import camelToReadable
def getModules(COMMON_MODULE_PATH):
try:
files = [f for f in os.listdir(COMMON_MODULE_PATH) if f.endswith('.py') and not f.startswith('__')]
except FileNotFoundError:
st.error("The specified directory does not exist.")
return {}
modules = {}
for file in files:
module_name = file[:-3]
readable_name = camelToReadable(module_name)
modules[readable_name] = module_name
return modules
structPages.py
— Build Pages Dynamically
Creates a
Page
object for each module under a category folder.
import streamlit as st
import importlib
import random
import re
from src.helpers.getModules import getModules
from src.helpers.getFolders import getFolders
icons = [
.
.
":material/smart_toy:",
":material/email:",
":material/web:",
":material/camera_alt:",
":material/assignment:",
.
.
]
def formatTitle(name):
return re.sub(r'(?<!^)(?=[A-Z])', ' ', name)
def createPageModule(BASE_DIR, MAIN_DIR, MODULES):
st.title(formatTitle(MAIN_DIR))
choice = st.selectbox(f'Select a {BASE_DIR[:-1].lower()} to execute', [None] + list(MODULES.keys()), key=MAIN_DIR)
st.divider()
if choice in MODULES:
module_name = MODULES[choice]
try:
module = importlib.import_module(f"src.apps.pages.{BASE_DIR}.{MAIN_DIR}.{module_name}")
func = getattr(module, module_name)
func()
except ModuleNotFoundError as e:
st.toast(f"Module '{module_name}.py' could not be found.", icon="🚫")
st.error(f"An error occurred: {e}", icon="🚫")
except AttributeError as e:
st.toast(f"Function '{module_name}' could not be found in '{module_name}.py'.", icon="🚫")
st.error(f"An error occurred: {e}", icon="🚫")
except Exception as e:
st.error(f"An error occurred: {e}", icon="🚫")
else:
st.info("Star this project on [GitHub](https://github.com/Code-A2Z/jarvis), if you like it!", icon='⭐')
def structPages(path):
folders = getFolders(path)
pages = []
for name, folder in folders.items():
COMMON_MODULE_PATH = f"{path}/{folder}"
MODULES = getModules(COMMON_MODULE_PATH)
if MODULES:
pages.append(
st.Page(
lambda path=path.split('/')[-1], folder=folder, MODULES=MODULES: createPageModule(path, folder, MODULES),
title=name,
icon=random.choice(icons),
url_path=folder
)
)
return pages
Jarvis.py
— Main Application Entrypoint
This script structures the app, adds categories/pages, and applies user authentication logic.
import streamlit as st
from src.helpers.structPages import structPages
from src.helpers.getFolders import getFolders
def application():
pages = {
"": [
st.Page("src/apps/public/home.py", title="Home", icon=":material/home:"),
st.Page("src/apps/public/youtubePlaylist.py", title="Jarvis Videos", icon=":material/ondemand_video:"),
],
"Account": [
st.Page("src/apps/auth/auth.py", title="Authentication", icon=":material/lock_open:"),
],
}
if st.user and st.user.is_logged_in:
MAIN_DIR = "src/apps/pages"
folders = getFolders(MAIN_DIR)
if folders:
for folder_name, folder_dir in folders.items():
pages[folder_name.title()] = structPages(f"{MAIN_DIR}/{folder_dir}")
if st.user.email == st.secrets["general"]["ADMIN_EMAIL"] and st.user.given_name == st.secrets["general"]["ADMIN_NAME"]:
pages.update({
"Admin": [
st.Page("src/apps/auth/env.py", title="Environment Variables", icon=":material/security:"),
]
})
return st.navigation(pages)
application().run()
This modular setup allows for:
- Easy extensibility by adding/removing modules
- Role-based dynamic page access
- Category-driven navigation structure
- Clean user interface powered by st.Page and custom helper functions