Maintainable navigation
A Bubble SPA navigation pattern built around route options and reusable state.
Single page app navigation in Bubble can be set up in several good ways. This lesson shows one pattern we recommend: model routes as aNavigation Path option set, expose the current route from the Global reusable element, and send route changes through a Global custom event.
In a single page app, we always need to know where we are. The current route controls selected sidebar states, conditional visibility, page titles, breadcrumbs, and which view is shown.
We also need to be able to navigate anywhere easily. A sidebar cell, a button inside a workflow, and a redirect after saving a form may all need to send the user to another route.
The maintainable setup gives both jobs a reusable owner. Global exposes the current route so every part of the page can read it. Global also owns the custom event that changes the URL, so workflows do not rebuild route strings in several places.
Use a Navigation Path option set for route options. A path can store the text used in the URL, the normalised path used for matching, theNavigation Page it belongs to, and its parent paths.
- path
- text
- normalisedPath
- text
- Page
- Navigation Page
- Parents
- List of Navigation Paths
- visibleInSidebar
- yes / no
The useful fields are path, normalisedPath,Page, and Parents. Other fields can handle sidebar display, required roles, required feature flags, and whether the route needs a selected project. Those fields let the sidebar and route checks read from the option instead of hardcoding conditions on each button.
We do not want URL expressions everywhere we need to know where we are. Conditional visibility, selected sidebar states, and page-specific groups should not each read Get data from page URL orGet path item #2 directly.
Put that parsing in the Global reusable element. ExposeCurrent Navigation Path, Parent Paths, andPage as reusable element properties. These properties are dynamic, so they update when the URL changes without workflows setting and resetting custom states.
A page group can then ask whether Global's Page is dashboard. A sidebar cell can ask whether Global's Current Navigation Path is Current cell's Navigation Path. Breadcrumbs can read Global's Parent Paths. Each expression reads a named property instead of rebuilding the URL parsing.
Put the main URL routing workflow in a Global custom event. In the example, the event is called Navigate To Tab. It receives a requiredNavigation Path parameter and optional parameters for records that may need to be included in the URL, such as Project,Chat, Agent, Document, orextraParams.
The event sets the URL path from the Navigation Path, sets URL parameters from the optional records, and then sends the user to the Bubble page represented by Global's Page. For example, it can go to the dashboard page only when Global's Page is dashboard, or the admin page only when Global's Page is admin.
Sidebar cells, page buttons, and post-save workflows call this event instead of each building the URL themselves. If the route format changes later, the URL routing logic changes in one custom event.
Shortcut events
Some routes are used often enough to deserve a small shortcut event. For example, a Navigate To Chat event can receive a Chatand trigger Navigate To Tab with the correct navigation path and URL parameters.
The shortcut should still route through Navigate To Tab. It should not duplicate URL path and parameter logic. Its job is to package a common navigation request so callers do not need to remember which path and parameters a chat route requires.
Sidebar items should almost always be a repeating group. The data source can be All Navigation Paths:filtered wherevisibleInSidebaris yes, filtered by the current user's roles, feature flags, and project state.
Hardcoded sidebar buttons are a common sign of technical debt. Adding a route then requires copying a button, updating its selected condition, changing its workflow, and checking whether its access conditions match the rest of the app. A repeating group makes the list of routes explicit.
Each sidebar cell uses the current route from Global for selected and expanded states. For nested routes, it can also check whetherGlobal's Parent Pathscontains the cell'sNavigation Path.
Adding a route
A new route should start in the route registry. Add aNavigation Path option with its path,normalisedPath, Page, parent paths, sidebar visibility, and access fields.
Then add the view condition using Global's exposed properties. If the route needs a common navigation shortcut, create a small custom event that calls Navigate To Tab. The shortcut chooses the path and parameters;Navigate To Tab still owns the URL routing.