Hash-Based Routing Documentation¶
Overview¶
The Not Alone app uses anvil_extras.routing for client-side navigation through hash-based routing. This enables single-page application (SPA) behavior with clean URLs and browser history support.
Routing Architecture¶
Template System¶
The app uses two main templates for routing:
Routertemplate - Main application layout with sidebar navigationStatictemplate - Used for authentication pages (sign in/up)
The Router template is decorated with a condition to ensure the tenant is set:
@routing.template(path='app', priority=5, condition=lambda: Global.get_s('tenant') is not None)
class Router(RouterTemplate):
    # ...
URL Structure¶
URLs in the application follow these patterns:
- Authentication: 
#sign,#signin,#signup - Main app: 
#app/[section] - Detail views: 
#app/[section]/[id] 
Route Definitions¶
Authentication Routes¶
@routing.route('', template='Static')
@routing.route('sign', template='Static', url_keys=[routing.ANY])
class Sign(SignTemplate):
    # ...
@routing.route('signin', template='Static', url_keys=[routing.ANY])
class Signin(SigninTemplate):
    # ...
@routing.route('signup', template='Static', url_keys=[routing.ANY])
class Signup(SignupTemplate):
    # ...
Main Application Routes¶
@routing.route('/home', template='Router')
class Home(HomeTemplate):
    # ...
@routing.route('/members', template='Router', url_keys=[routing.ANY])
class Members(MembersTemplate):
    # ...
@routing.route('/volunteers', template='Router')
class Roles(RolesTemplate):
    # ...
Detail View Routes¶
@routing.route("/memberdetail", template="Router", url_keys=['user_email'])
@routing.route('/profile', template='Router')
class MemberDetail(MemberDetailTemplate):
    # ...
@routing.route('/roledetail', template='Router', url_keys=['role'])
class RoleDetail(RoleDetailTemplate):
    # ...
Navigation Implementation¶
URL Hash Management¶
The Router component manages URL hashes for navigation links:
def __init__(self, **properties):
    self.init_components(**properties)
    self.link_home.tag.url_hash = 'app/home'
    self.link_apply.tag.url_hash = 'app/apply'
    self.link_profile.tag.url_hash = 'app/profile'
    self.link_members.tag.url_hash = 'app/members'
    self.link_fin.tag.url_hash = 'app/financials'
    self.link_volunteers.tag.url_hash = 'app/volunteers'
    self.link_admin.tag.url_hash = 'app/admin'
    self.link_reports.tag.url_hash = 'app/reports'
    self.link_settings.tag.url_hash = 'app/settings'
Navigation Events¶
The Router handles navigation events and updates UI state:
def nav_click(self, sender, **event_args):
    if sender.tag.url_hash == '':
        if Global.user:
            self.set_account_state(Global.user)
            routing.set_url_hash('app')
        else:
            routing.set_url_hash('')
    else:
        routing.set_url_hash(sender.tag.url_hash)
def on_navigation(self, url_hash, url_pattern, url_dict, unload_form):
    # Update selected state of navigation links
    for link in self.cp_sidebar.get_components():
        if type(link) == Link:
            link.role = 'selected' if link.tag.url_hash == url_hash else None
    if url_hash in ['homeanon', 'homedetail', 'app']:
        self.link_home.role = 'selected'
Route Parameters¶
Some routes accept parameters through url_keys:
- Member Detail View:
 - Accepts user email as parameter
 - 
URL format:
#app/memberdetail?user_email=example@email.com - 
Role Detail View:
 - Accepts role identifier as parameter
 - URL format: 
#app/roledetail?role=role_id 
Authentication and Routing¶
The routing system integrates with authentication:
def link_logout_click(self, **event_args):
    with anvil.server.no_loading_indicator:
        anvil.users.logout()
        self.set_account_state(None)
        routing.clear_cache()
        Global.clear_global_attributes()
        routing.set_url_hash('sign', load_from_cache=False)
Key features: - Clears routing cache on logout - Redirects to sign-in page - Prevents cached data from persisting across sessions
Best Practices¶
- Template Selection
 - Use 
Routertemplate for authenticated pages - 
Use
Statictemplate for authentication flows - 
URL Parameters
 - Use 
url_keysfor required parameters - 
Use
routing.ANYfor optional parameters - 
Navigation State
 - Update selected states in 
on_navigation - Clear cache when logging out
 - 
Use
routing.set_url_hash()for programmatic navigation - 
Conditional Routes
 - Use template conditions for access control
 - 
Check permissions before allowing navigation
 - 
Cache Management
 - Clear routing cache when user state changes
 - Use 
load_from_cache=Falsewhen fresh data is required