{"id":14959590,"url":"https://github.com/tanglespace/hydralit","last_synced_at":"2025-04-05T07:04:52.058Z","repository":{"id":37670911,"uuid":"387057335","full_name":"TangleSpace/hydralit","owner":"TangleSpace","description":"A library to create multi-page Streamlit applications with ease.","archived":false,"fork":false,"pushed_at":"2023-04-14T21:22:49.000Z","size":105,"stargazers_count":207,"open_issues_count":11,"forks_count":20,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-05T07:04:47.991Z","etag":null,"topics":["python","secure","streamlit","web-application"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TangleSpace.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-17T23:58:51.000Z","updated_at":"2025-03-22T13:33:57.000Z","dependencies_parsed_at":"2024-09-24T13:34:03.497Z","dependency_job_id":"fd39a49f-3a55-4aa3-b483-6050fdf86f84","html_url":"https://github.com/TangleSpace/hydralit","commit_stats":{"total_commits":26,"total_committers":5,"mean_commits":5.2,"dds":0.3076923076923077,"last_synced_commit":"964e468f963d87ed83d1f3555efd5ce49f158c25"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TangleSpace%2Fhydralit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TangleSpace%2Fhydralit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TangleSpace%2Fhydralit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TangleSpace%2Fhydralit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TangleSpace","download_url":"https://codeload.github.com/TangleSpace/hydralit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247299831,"owners_count":20916190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["python","secure","streamlit","web-application"],"created_at":"2024-09-24T13:20:10.327Z","updated_at":"2025-04-05T07:04:52.033Z","avatar_url":"https://github.com/TangleSpace.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":" \r\n # **Hydralit** \u003cimg src=\"https://github.com/TangleSpace/hydralit/raw/main/docs/images/hydra.png\" alt=\"hydra\" width=\"50\"/\u003e\r\nThe Hydralit package is a wrapping and template project to combine multiple independant (or somewhat dependant) Streamlit applications into a multi-page application.\r\n\r\nCurrently the project implements a host application HydraApp and each child application simply needs to be either a class deriving from the HydraHeadApp class and implementing a single, simple method, run() for maximum profit, or you can use a Flask style decorator on your functions to add them directly as seperate Streamlit pages.\r\n\r\nWhen converting existing applications, you can effectively put all the existing code inside the run() method and create a wrapper class deriving from HydraHeadApp or put a decorator over the function. Then you create the parent app as an instance of HydraApp, add your child apps to it (see example [secure_app.py](\"https://github.com/TangleSpace/hydralit-example/blob/main/secure_app.py\")) and with only a few lines of code everything will magically come together.\r\n\r\n\u003cbr\u003e\r\n\r\n## **Version 1.0.14 fixes session state refactor performed by Streamlit, maybe after changing it 10 times they'll settle on a way forward, or they're just trying to constantly break the Hydralit package, wtf knows.**\r\n - Now compatible with Streamlit \u003e=1.12, thanks to the tireless efforts of [saikumarmk](https://github.com/saikumarmk)\r\n\r\n \u003cbr\u003e\r\n\r\n## **Version 1.0.13 fixes the long standing stupidty of Streamlit constantly changing the method name of the session context manager, now works with Streamlit 1.9.x and above.**\r\n - Added the ability to disable to use of the app loader within the constructor.\r\n\u003cbr\u003e\r\n\r\n## **Version 1.0.12 fixes an edge case when installing with Streamlit for the first time.**\r\n\u003cbr\u003e\r\n\r\n## **Hydralit now fully supports all versions of Streamlit, including 1.4.0, despite the odd changes made in version 1.4.0 that completely broke Hydralit.**\r\n\u003cbr\u003e\r\n\r\n## **Hydralit \u003e=1.0.3 now requires a minimum version of Streamlit \u003e=0.86.x to fully support the recently migrated beta containers, if using Streamlit \u003c=0.85.x please continue to use Hydralit \u003c=1.0.2**\r\n\r\n\r\n\u003cbr\u003e\r\n\u003cp align=\"center\"\u003e\r\n\t\u003ca href=\"https://pepy.tech/project/hydralit/\" alt=\"PyPI downloads\"\u003e\r\n\t\u003cimg src=\"https://pepy.tech/badge/hydralit\" /\u003e\r\n\t\u003c/a\u003e\r\n    \u003ca href=\"https://www.python.org/\" alt=\"Python version\"\u003e\r\n        \u003cimg src=\"https://img.shields.io/pypi/pyversions/hydralit\" /\u003e\u003c/a\u003e\r\n    \u003ca href=\"https://pypi.org/project/hydralit/\" alt=\"PyPI version\"\u003e\r\n        \u003cimg src=\"https://img.shields.io/pypi/v/hydralit\" /\u003e\u003c/a\u003e\r\n    \u003ca href=\"https://hydralit.aur-license.org/\" alt=\"License\"\u003e\r\n        \u003cimg src=\"http://img.shields.io/:license-Apache-blue.svg?style=flat-square\"\u003e\u003c/a\u003e\r\n    \u003ca href=\"https://streamlit.io/\" alt=\"Streamlit\"\u003e\r\n        \u003cimg src=\"http://img.shields.io/:streamlit-\u003e=0.86.0-blue.svg?style=flat-square\"\u003e\u003c/a\u003e\r\n\u003c/p\u003e\r\n\r\n## Installation\r\nHydralit can be installed from PyPI:\r\n\r\n```bash\r\npip install -U hydralit\r\n```\r\n\r\n\u003ch1\u003e\u003ca href=\"https://hydralit-secure-sample.herokuapp.com/\"\u003eYou can see what's possible using Hydralit here!\u003c/a\u003e\u003c/h1\u003e\r\n\r\n# Lightning Example\r\n ```python\r\n#when we import hydralit, we automatically get all of Streamlit\r\nimport hydralit as hy\r\n\r\napp = hy.HydraApp(title='Simple Multi-Page App')\r\n\r\n@app.addapp()\r\ndef my_home():\r\n  hy.info('Hello from app1')\r\n\r\n@app.addapp()\r\ndef app2():\r\n  hy.info('Hello from app 2')\r\n\r\n\r\n#Run the whole lot, we get navbar, state management and app isolation, all with this tiny amount of work.\r\napp.run()\r\n ```\r\n \r\n This tiny amount of code creates a menu and pages that render when the target function is called by selecting it from the menu.\r\n \u003cp align=\"center\"\u003e\r\n\u003cimg src=\"https://github.com/TangleSpace/hydralit_components/blob/main/resources/baby_demo.gif?raw=true\" title=\"Quick Example\" alt=\"Quick Example\", width=\"100%\" height=\"100%\"\u003e\r\n\u003c/p\u003e\r\n\r\n\r\n## Latest features (version 1.0.11)\r\n - Fully supports all versions of Streamlit, including 1.4.0 (big thanks to [oggers](https://github.com/oggers) for some amazing support!).\r\n - Fixed the missing error handling bug, now all exceptions are raised to be handled however the user chooses instead of capturing and displaying an image. (big thanks to [rambam613](https://github.com/rambam613) for finding and fixing this bug, very nice!).\r\n - Can completely customise the Home and Logout menu entries, title and icon data from the add_app entry will be used for these items now as well as the existing.\r\n\u003cp align=\"center\"\u003e\r\n\u003cimg src=\"https://github.com/TangleSpace/hydralit_components/blob/main/resources/customised_navbar.PNG?raw=true\" title=\"Navbar\" alt=\"Navbar\", width=\"100%\" height=\"100%\"\u003e\r\n\u003c/p\u003e\r\n\r\n - Cleaned up the formatting when running in sticky and hiding Streamlit headers and footers, yes, they will come back now when using the navbar.\r\n - Removed the background effort for all loader animations (everyone hated this).\r\n - Smaller, sleeker navbar, including a much nicer non-animated mode.\r\n  \u003cp align=\"center\"\u003e\r\n\u003cimg src=\"https://github.com/TangleSpace/hydralit_components/blob/main/resources/non-animated_navbar.PNG?raw=true\" title=\"Navbar\" alt=\"Navbar\", width=\"100%\" height=\"100%\"\u003e\r\n\u003c/p\u003e\r\n\r\n - Full offline support for Font Awesome and Bootstrap icons for navbar entries, as well as all emojis.\r\n - Improved performance with some refactoring of the session and transition code, apps load faster now.\r\n\r\n\u003cbr\u003e\u003cbr\r\n\r\n## Version 1.0.10 features\r\n - Added Flask like decorators to convert any function into a child app (see example below)\r\n - Can set auto login with guest account when using a secure app\r\n - Support for a non-secure app in a secure app (like a signup app)\r\n - Full integration with the Hydralit Navbar that now supports complex nav!\r\n - some bug fixes where app to app redirect was inconsistant\r\n - Banners\r\n - Compression behind download button\r\n - Hydralit Navbar\r\n - Can turn off the navbar animation now! (must be using Hydralit_components \u003e=1.0.4)\r\n\r\n## NOTE\r\nDue to the Streamlit execution model, the ability to use internal nav links from a child app is one-shot when using the navbar. This means that the internal link will redirect to the child, however if a script rerun request is made within the child app (changing the value of a widget for example), the nav will bounce back to the calling app. You can disable the navbar and the Streamlit core components nav menu will appear and the internal links will work as expected.\r\n\r\n\r\n## Complex and sticky nav with no Streamlit markers is as easy as a couple of parameters in the Hydralit constructor.\r\n ```python\r\napp = HydraApp(title='Secure Hydralit Data Explorer',favicon=\"🐙\",hide_streamlit_markers=True,use_navbar=True, navbar_sticky=True)\r\n ```\r\n\r\n## Now powered by [Hydralit Components](https://github.com/TangleSpace/hydralit_components).\r\nThe Hydralit Navbar is fully integrated, theme aware and animated (you can turn it off if you like), just add your child apps and go, the navbar will appear automatically.\r\n# Navbar - Responsive, theme aware and animated.\r\n\u003cp align=\"center\"\u003e\r\n\u003cimg src=\"https://raw.githubusercontent.com/tanglespace/hydralit_components/master/resources/hydralit_navbar.gif\" title=\"Quick Example\" alt=\"Quick Example\", width=\"60%\" height=\"100%\"\u003e\r\n\u003c/p\u003e\r\n\r\n# Spinners and Loaders\r\nOut of the box you get a nice loader/spinner when navigating between apps/pages. You can also create your own loader app and completely customise every part of how it looks and when it loads, even creating different effects depending on the target application. See the [Hydralit secure example code](https://github.com/TangleSpace/hydralit-example/blob/main/apps/myloading_app.py) to see what is possible.\r\n\r\n\u003cp align=\"center\"\u003e\r\n\u003cimg src=\"https://github.com/TangleSpace/hydralit_components/blob/main/resources/standard_loaders.gif?raw=true\" title=\"HyLoaders\" alt=\"HyLoaders\", width=\"45%\" height=\"45%\"\u003e\r\n\u003cimg src=\"https://github.com/TangleSpace/hydralit_components/blob/main/resources/pretty_loaders.gif?raw=true\" title=\"HyLoaderspretty\" alt=\"HyLoaders\", width=\"45%\" height=\"45%\"\u003e\r\n\u003cimg src=\"https://github.com/TangleSpace/hydralit_components/blob/main/resources/pulse_bars.gif?raw=true\" title=\"HyLoaderspretty\" alt=\"HyLoaders\", width=\"100%\" height=\"60%\"\u003e\r\n\r\n\r\n## Quick Start\r\nIf you have some functions and want them to run like seperate pages, you can quickly get going with a Flask style decorator over your functions.\r\n ```python\r\n#when we import hydralit, we automatically get all of Streamlit\r\nimport hydralit as hy\r\n\r\napp = hy.HydraApp(title='Simple Multi-Page App')\r\n\r\n@app.addapp(is_home=True)\r\ndef my_home():\r\n  hy.info('Hello from Home!')\r\n\r\n@app.addapp()\r\ndef app2():\r\n  hy.info('Hello from app 2')\r\n\r\n@app.addapp(title='The Best', icon=\"🥰\")\r\ndef app3():\r\n  hy.info('Hello from app 3, A.K.A, The Best 🥰')\r\n\r\n#Run the whole lot, we get navbar, state management and app isolation, all with this tiny amount of work.\r\napp.run()\r\n ```\r\nThis tiny amount of code creates a nice custom multi-page app as below.\r\n \u003cp align=\"center\"\u003e\r\n\u003cimg src=\"https://github.com/TangleSpace/hydralit_components/blob/main/resources/quick_demo.gif?raw=true\" title=\"Quick Example\" alt=\"Quick Example\", width=\"100%\" height=\"100%\"\u003e\r\n\u003c/p\u003e\r\n\r\n\r\n### Examples\r\nYou can try it out by running the two sample applications with their children that are located in the [hydralit-example repository](https://github.com/TangleSpace/hydralit-example).\r\n```bash\r\nhydralit_example\u003e pip install -r requirements.txt\r\n\r\nhydralit_example\u003e streamlit run secure.app\r\n```\r\n\r\n\u003ch1\u003e\u003ca href=\"https://hydralit-secure-sample.herokuapp.com/\"\u003eYou can see this example running here\u003c/a\u003e\u003c/h1\u003e\r\n\r\n\r\n# Converting existing applications\r\nThis code sample comes directly from the [Streamlit example data explorer](https://docs.streamlit.io/en/stable/tutorial/create_a_data_explorer_app.html#let-s-put-it-all-together)\r\n```python\r\nimport streamlit as st\r\nimport pandas as pd\r\nimport numpy as np\r\n\r\nst.title('Uber pickups in NYC')\r\n\r\nDATE_COLUMN = 'date/time'\r\nDATA_URL = ('https://s3-us-west-2.amazonaws.com/'\r\n            'streamlit-demo-data/uber-raw-data-sep14.csv.gz')\r\n\r\n@st.cache\r\ndef load_data(nrows):\r\n    data = pd.read_csv(DATA_URL, nrows=nrows)\r\n    lowercase = lambda x: str(x).lower()\r\n    data.rename(lowercase, axis='columns', inplace=True)\r\n    data[DATE_COLUMN] = pd.to_datetime(data[DATE_COLUMN])\r\n    return data\r\n\r\ndata_load_state = st.text('Loading data...')\r\ndata = load_data(10000)\r\ndata_load_state.text(\"Done! (using st.cache)\")\r\n\r\nif st.checkbox('Show raw data'):\r\n    st.subheader('Raw data')\r\n    st.write(data)\r\n\r\nst.subheader('Number of pickups by hour')\r\nhist_values = np.histogram(data[DATE_COLUMN].dt.hour, bins=24, range=(0,24))[0]\r\nst.bar_chart(hist_values)\r\n\r\n# Some number in the range 0-23\r\nhour_to_filter = st.slider('hour', 0, 23, 17)\r\nfiltered_data = data[data[DATE_COLUMN].dt.hour == hour_to_filter]\r\n\r\nst.subheader('Map of all pickups at %s:00' % hour_to_filter)\r\nst.map(filtered_data)\r\n```\r\n\r\nLet's also use a simple application to combine with the demo above.\r\n```python\r\nimport streamlit as st\r\nimport numpy as np\r\nimport pandas as pd\r\nfrom data.create_data import create_table\r\n\r\ndef app():\r\n    st.title('Small Application with a table and chart.')\r\n\r\n    st.write(\"See `apps/simple.py` to know how to use it.\")\r\n\r\n    st.markdown(\"### Plot\")\r\n    df = create_table()\r\n\r\n    st.line_chart(df)\r\n```\r\n\r\n\r\nYou can easily convert these apps to be used within Hydralit by simply wrapping each in a class derived from HydraHeadApp within Hydralit and putting all the code in the run() method.\r\n\r\nFor the above Streamlit demo application, this means all that is needed is a slight modification, we create a file sample_app.py and add;\r\n```python\r\nimport streamlit as st\r\nimport pandas as pd\r\nimport numpy as np\r\n\r\n#add an import to Hydralit\r\nfrom hydralit import HydraHeadApp\r\n\r\n#create a wrapper class\r\nclass MySampleApp(HydraHeadApp):\r\n\r\n#wrap all your code in this method and you should be done\r\n    def run(self):\r\n        #-------------------existing untouched code------------------------------------------\r\n        st.title('Uber pickups in NYC')\r\n\r\n        DATE_COLUMN = 'date/time'\r\n        DATA_URL = ('https://s3-us-west-2.amazonaws.com/'\r\n                    'streamlit-demo-data/uber-raw-data-sep14.csv.gz')\r\n\r\n        @st.cache\r\n        def load_data(nrows):\r\n            data = pd.read_csv(DATA_URL, nrows=nrows)\r\n            lowercase = lambda x: str(x).lower()\r\n            data.rename(lowercase, axis='columns', inplace=True)\r\n            data[DATE_COLUMN] = pd.to_datetime(data[DATE_COLUMN])\r\n            return data\r\n\r\n        data_load_state = st.text('Loading data...')\r\n        data = load_data(10000)\r\n        data_load_state.text(\"Done! (using st.cache)\")\r\n\r\n        if st.checkbox('Show raw data'):\r\n            st.subheader('Raw data')\r\n            st.write(data)\r\n\r\n        st.subheader('Number of pickups by hour')\r\n        hist_values = np.histogram(data[DATE_COLUMN].dt.hour, bins=24, range=(0,24))[0]\r\n        st.bar_chart(hist_values)\r\n\r\n        # Some number in the range 0-23\r\n        hour_to_filter = st.slider('hour', 0, 23, 17)\r\n        filtered_data = data[data[DATE_COLUMN].dt.hour == hour_to_filter]\r\n\r\n        st.subheader('Map of all pickups at %s:00' % hour_to_filter)\r\n        st.map(filtered_data)\r\n        #-------------------existing untouched code------------------------------------------\r\n```\r\nFor the other small application, again we can convert this very easily by wrapping in a class derived from HydraHeadApp from Hydralit and putting all the code in the run() method, we create a file small_app.py and add;\r\n```python\r\nimport streamlit as st\r\nimport numpy as np\r\nimport pandas as pd\r\nfrom data.create_data import create_table\r\n\r\n#add an import to Hydralit\r\nfrom hydralit import HydraHeadApp\r\n\r\n#create a wrapper class\r\nclass MySmallApp(HydraHeadApp):\r\n\r\n#wrap all your code in this method and you should be done\r\n    def run(self):\r\n        #-------------------existing untouched code------------------------------------------\r\n        st.title('Small Application with a table and chart.')\r\n\r\n        st.markdown(\"### Plot\")\r\n        df = create_table()\r\n\r\n        st.line_chart(df)\r\n```\r\n\r\nThese are is now ready to be used within a Hydralit application. We just need to create a simple host application that derives from the HydraApp class in Hydralit, add the children and we are done! we create a file host_app.py and add;\r\n```python\r\nfrom hydralit import HydraApp\r\nimport streamlit as st\r\nfrom sample_app import MySampleApp\r\nfrom small_app import MySmallApp\r\n\r\n\r\nif __name__ == '__main__':\r\n\r\n    #this is the host application, we add children to it and that's it!\r\n    app = HydraApp(title='Sample Hydralit App',favicon=\"🐙\")\r\n  \r\n    #add all your application classes here\r\n    app.add_app(\"Small App\", icon=\"🏠\", app=MySmallApp())\r\n    app.add_app(\"Sample App\",icon=\"🔊\", app=MySampleApp())\r\n\r\n    #run the whole lot\r\n    app.run()\r\n```\r\n\r\n### Or you could use the decorator method shown in the Lightning example and simply wrap your functions, both ways work, you can get access to more controls with the class method as the template class allows access to the Hydralit internal state for access and navigation information.\r\n\r\nThis super simple example is made of 3 files.\r\n```\r\nhydralit sample project\r\n│   host_app.py\r\n│   small_app.py\r\n│   sample_app.py\r\n```\r\n### Run this sample\r\n```bash\r\nhydralit sample project\u003e pip install hydralit\r\n\r\nhydralit sample project\u003e streamlit run host.app\r\n```\r\n\r\n### Examples\r\nThe code for a host application that is secured with a login app is shown below, the entire example is located in the [hydralit-example repository](https://github.com/TangleSpace/hydralit-example).\r\n\r\n```python\r\nfrom hydralit import HydraApp\r\nimport streamlit as st\r\nimport apps\r\n\r\n\r\nif __name__ == '__main__':\r\n    over_theme = {'txc_inactive': '#FFFFFF'}\r\n    #this is the host application, we add children to it and that's it!\r\n    app = HydraApp(\r\n        title='Secure Hydralit Data Explorer',\r\n        favicon=\"🐙\",\r\n        hide_streamlit_markers=False,\r\n        #add a nice banner, this banner has been defined as 5 sections with spacing defined by the banner_spacing array below.\r\n        use_banner_images=[\"./resources/hydra.png\",None,{'header':\"\u003ch1 style='text-align:center;padding: 0px 0px;color:black;font-size:200%;'\u003eSecure Hydralit Explorer\u003c/h1\u003e\u003cbr\u003e\"},None,\"./resources/lock.png\"], \r\n        banner_spacing=[5,30,60,30,5],\r\n        use_navbar=True, \r\n        navbar_sticky=False,\r\n        navbar_theme=over_theme\r\n    )\r\n\r\n    #Home button will be in the middle of the nav list now\r\n    app.add_app(\"Home\", icon=\"🏠\", app=apps.HomeApp(title='Home'),is_home=True)\r\n\r\n    #add all your application classes here\r\n    app.add_app(\"Cheat Sheet\", icon=\"📚\", app=apps.CheatApp(title=\"Cheat Sheet\"))\r\n    app.add_app(\"Sequency Denoising\",icon=\"🔊\", app=apps.WalshApp(title=\"Sequency Denoising\"))\r\n    app.add_app(\"Sequency (Secure)\",icon=\"🔊🔒\", app=apps.WalshAppSecure(title=\"Sequency (Secure)\"))\r\n    app.add_app(\"Solar Mach\", icon=\"🛰️\", app=apps.SolarMach(title=\"Solar Mach\"))\r\n    app.add_app(\"Spacy NLP\", icon=\"⌨️\", app=apps.SpacyNLP(title=\"Spacy NLP\"))\r\n    app.add_app(\"Uber Pickups\", icon=\"🚖\", app=apps.UberNYC(title=\"Uber Pickups\"))\r\n    app.add_app(\"Solar Mach\", icon=\"🛰️\", app=apps.SolarMach(title=\"Solar Mach\"))\r\n\r\n    #we have added a sign-up app to demonstrate the ability to run an unsecure app\r\n    #only 1 unsecure app is allowed\r\n    app.add_app(\"Signup\", icon=\"🛰️\", app=apps.SignUpApp(title='Signup'), is_unsecure=True)\r\n\r\n    #we want to have secure access for this HydraApp, so we provide a login application\r\n    #optional logout label, can be blank for something nicer!\r\n    app.add_app(\"Login\", apps.LoginApp(title='Login'),is_login=True) \r\n\r\n    #specify a custom loading app for a custom transition between apps, this includes a nice custom spinner\r\n    app.add_loader_app(apps.MyLoadingApp(delay=5))\r\n    #app.add_loader_app(apps.QuickLoaderApp())\r\n\r\n    #we can inject a method to be called everytime a user logs out\r\n    @app.logout_callback\r\n    def mylogout_cb():\r\n        print('I was called from Hydralit at logout!')\r\n\r\n    #we can inject a method to be called everytime a user logs in\r\n    @app.login_callback\r\n    def mylogin_cb():\r\n        print('I was called from Hydralit at login!')\r\n\r\n    #if we want to auto login a guest but still have a secure app, we can assign a guest account and go straight in\r\n    app.enable_guest_access()\r\n\r\n    #--------------------------------------------------------------------------------------------------------------------\r\n    #if the menu is looking shit, use some sections\r\n    #check user access level to determine what should be shown on the menu\r\n    user_access_level, username = app.check_access()\r\n\r\n    # If the menu is cluttered, just rearrange it into sections!\r\n    # completely optional, but if you have too many entries, you can make it nicer by using accordian menus\r\n    if user_access_level \u003e 1:\r\n        complex_nav = {\r\n            'Home': ['Home'],\r\n            'Intro 🏆': ['Cheat Sheet',\"Solar Mach\"],\r\n            'Hotstepper 🔥': [\"Sequency Denoising\",\"Sequency (Secure)\"],\r\n            'Clustering': [\"Uber Pickups\"],\r\n            'NLP': [\"Spacy NLP\"],\r\n        }\r\n    elif user_access_level == 1:\r\n        complex_nav = {\r\n            'Home': ['Home'],\r\n            'Intro 🏆': ['Cheat Sheet',\"Solar Mach\"],\r\n            'Hotstepper 🔥': [\"Sequency Denoising\"],\r\n            'Clustering': [\"Uber Pickups\"],\r\n            'NLP': [\"Spacy NLP\"],\r\n        }\r\n    else:\r\n        complex_nav = {\r\n            'Home': ['Home'],\r\n        }\r\n\r\n  \r\n    #and finally just the entire app and all the children.\r\n    app.run(complex_nav)\r\n\r\n    #(DEBUG) print user movements and current login details used by Hydralit\r\n    #---------------------------------------------------------------------\r\n    user_access_level, username = app.check_access()\r\n    prev_app, curr_app = app.get_nav_transition()\r\n    print(prev_app,'- \u003e', curr_app)\r\n    print(int(user_access_level),'- \u003e', username)\r\n    #---------------------------------------------------------------------\r\n```\r\n\r\nYou can try it out by running the two sample applications with their children that are located in the [hydralit-example repository](https://github.com/TangleSpace/hydralit-example).\r\n```bash\r\nhydralit_example\u003e pip install -r requirements.txt\r\n\r\nhydralit_example\u003e streamlit run secure.app\r\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftanglespace%2Fhydralit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftanglespace%2Fhydralit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftanglespace%2Fhydralit/lists"}