Skip to Content
DocsDeveloper GuideHybrid Routing

Hybrid Routing

Hybrid Routing in WebF is fundamentally different from traditional Single-Page Applications (SPAs). To achieve a truly native navigation experience with proper screen transitions, WebF does not use the standard History API or hash-based routing.

Instead, WebF uses a hybrid routing mechanism, where each “page” of your WebF application is rendered on a separate, native Flutter screen. This is called Hybrid Routing because it synchronizes navigation between your WebF app code and the Flutter Navigator.

To manage this, you will use a framework-specific routing package designed for WebF.

For Flutter developers: See the Hybrid Routing guide to learn how to set up the Flutter side with WebFSubView and integrate with go_router.

For React Developers

The official approach is to use the @openwebf/react-router package. This library provides a familiar component-based API with comprehensive routing capabilities.

Installation

npm install @openwebf/react-router

Basic Route Setup

You can include a title prop on each <Route> to set the text that appears in the center of the native navigation bar for that screen.

// Basic route configuration import { Route, Routes } from '@openwebf/react-router'; import { HomePage } from './pages/home'; import { ProfilePage } from './pages/profile'; function App() { return ( <Routes> <Route path="/" element={<HomePage />} title="Home" /> <Route path="/profile" element={<ProfilePage />} title="My Profile" /> </Routes> ); }

The WebFRouter object provides imperative navigation methods for programmatic route changes:

import { WebFRouter, useLocation } from '@openwebf/react-router'; function NavigationExample() { const location = useLocation(); // Push a new route with state const navigateToProfile = () => { WebFRouter.pushState({ userId: 123, source: 'dashboard' }, '/profile/edit'); }; // Replace current route const replaceRoute = () => { WebFRouter.replaceState({ updated: true }, '/settings'); }; // Navigate back const goBack = () => { WebFRouter.back(); }; // Access location state console.log('Current state:', location.state); console.log('Current path:', location.pathname); return ( <div> <button onClick={navigateToProfile}>Go to Profile</button> <button onClick={replaceRoute}>Replace with Settings</button> <button onClick={goBack}>Go Back</button> </div> ); }

Advanced Navigation Methods

WebFRouter provides Flutter-style navigation methods for more complex scenarios:

import { WebFRouter } from '@openwebf/react-router'; // Push a named route (equivalent to Navigator.pushNamed in Flutter) await WebFRouter.push('/details', { itemId: 42 }); // Replace current route (equivalent to Navigator.pushReplacementNamed) await WebFRouter.replace('/login', { sessionExpired: true }); // Pop and push (equivalent to Navigator.popAndPushNamed) await WebFRouter.popAndPushNamed('/success', { orderId: 'ORD-123' }); // Check if can pop and conditionally pop if (WebFRouter.canPop()) { const didPop = WebFRouter.maybePop({ cancelled: false }); console.log('Did pop:', didPop); } // Restorable navigation with state restoration const restorationId = await WebFRouter.restorablePopAndPushNamed('/checkout', { cartItems: items, timestamp: Date.now() }); console.log('Restoration ID:', restorationId);

For declarative navigation, use the WebFRouterLink component:

import { WebFRouterLink } from '@openwebf/react-router'; function NavigationMenu() { return ( <nav> <WebFRouterLink path="/" title="Home"> <span>Home</span> </WebFRouterLink> <WebFRouterLink path="/profile" title="My Profile" onScreen={() => console.log('Link is visible')} > <span>Profile</span> </WebFRouterLink> </nav> ); }

Cross-Platform Router Shim

For applications that need to work in both WebF and browser environments, you can create a router shim:

import * as WebFLib from '@openwebf/react-router'; import { BrowserRouter, Link as RRDLink, Route as RRDRoute, Routes as RRDRoutes, useLocation as RRDUseLocation, useParams as RRDUseParams, } from 'react-router-dom'; const isWebF = typeof window !== 'undefined' && !!(window as any).webf; // Export the appropriate router based on environment export const useParams = isWebF ? WebFLib.useParams : RRDUseParams; export const useLocation = isWebF ? WebFLib.useLocation : RRDUseLocation; export const Routes = isWebF ? WebFLib.Routes : RRDRoutes; export const Route = isWebF ? WebFLib.Route : RRDRoute; export const RouterProvider = ({ children }) => { if (isWebF) { return <>{children}</>; } return <BrowserRouter>{children}</BrowserRouter>; };

This approach is key to making your app feel truly native, with correct screen transitions and lifecycle management.

For Other Frameworks

Note for other frameworks: This example uses the official package for React. If a similar routing package does not yet exist for your framework, please feel free to open an issue to discuss it with the WebF team.

Why Hybrid Routing?

WebF’s hybrid routing approach provides several key advantages over traditional web routing:

  1. Native Transitions: Screen transitions use platform-native animations (Cupertino for iOS, Material for Android)
  2. Proper Lifecycle: Each route has its own lifecycle, similar to native apps
  3. Back Button Integration: Hardware back button works correctly on Android
  4. Memory Management: Routes that are not visible can be unloaded to save memory
  5. Deep Linking: Integration with platform deep linking systems
  6. Synchronized Navigation: Flutter Navigator and WebF routing stay in sync automatically

This makes your WebF app feel truly native, not like a web page running in an app.

Next Steps: To set up the complete routing system, see the Hybrid Routing guide for Flutter integration details.