Architecting Multi-View Navigation in Framework7 SPAs
Learn how to implement independent navigation stacks in Framework7 using multiple View instances to create complex, non-linear SPA architectures.
05 Sept 2025, 08:56 UTC

The Navigation State Problem
In complex Single Page Applications (SPAs), a single linear navigation stack often fails to meet user expectations for multitasking or dashboard-style interfaces. When a user switches between a primary content area and a side-panel or a separate tabbed interface, resetting the entire application state to a single URL path disrupts the user experience. The core challenge is maintaining independent navigation histories—where moving 'back' in one area does not affect the position of another.
The Smallest Suitable Design: Independent View Instances
Framework7 solves this through the View component. Rather than treating the entire app as one route, you define multiple View instances. Each View maintains its own internal navigation stack and DOM container. For a standard split-screen or tabbed architecture, the minimal design requires one Main View for primary content and one Secondary View for contextual details or settings.
To implement this, define your views in the app initialization. This separates the routing logic into distinct silos:
const app = new Framework7({
el: '#app',
view: {
mainView: {
selector: '.view-main',
routes: [
{ path: '/', component: HomePage },
{ path: '/settings/', component: SettingsPage },
],
},
sideView: {
selector: '.view-side',
routes: [
{ path: '/details/:id/', component: DetailPage },
],
},
},
});Trust and Data Boundaries
Because Framework7 views operate independently, data does not automatically flow between them. The Router handles the URL and the DOM transition, but it is not a state management system. When navigating from mainView to a specific ID in sideView, the trust boundary lies at the route parameter.
The sideView should treat the :id parameter as untrusted input. The DetailPage component must validate this ID against a data store or API before rendering content to prevent crashes or unauthorized data access if a user manually manipulates the URL.
Operational Checks and Implementation
To trigger navigation in a specific view programmatically, you must reference that view's router instance. Running this command from a component within the main view allows you to update the side panel without refreshing the main content:
// Run within a Framework7 component or app context
// Required permissions: Access to the app instance
app.views.sideView.router.navigate(`/details/${userId}/`);
// Expected check: The .view-side DOM element updates
// while .view-main remains static.Failure Modes and Constraints
| Failure Mode | Cause | Mitigation |
|---|---|---|
| 404 on Refresh | Web server attempts to find physical file at /details/123 | Configure server (Nginx/Apache) to redirect all requests to index.html |
Memory Consumption: Framework7 caches page instances to ensure fast transitions. In a multi-view setup, the number of cached DOM elements doubles. If your application has dozens of complex pages across multiple views, you may encounter memory pressure on low-end mobile devices. Monitor the DOM size using browser developer tools to ensure you aren't leaking page instances.
Conditions for Design Evolution
The independent View architecture is sufficient for most dashboard and split-screen layouts. However, you should move toward a global state management library (like Pinia or Redux) if the following conditions occur:
- The
sideViewneeds to react in real-time to changes occurring inside themainViewwithout a manual navigation trigger. - Data fetched in one view must be persisted and modified across multiple other views without re-fetching from the API.
- Complex deep-linking requirements demand that a single URL represents the state of three or more simultaneous views.
To verify the current implementation, initialize a project with two views and use the browser's back button. If the back button only pops the mainView stack while the sideView remains unchanged, the independent navigation histories are correctly isolated.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.