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-routerBasic 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>
);
}Navigation with WebFRouter
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);WebFRouterLink Component
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:
- Native Transitions: Screen transitions use platform-native animations (Cupertino for iOS, Material for Android)
- Proper Lifecycle: Each route has its own lifecycle, similar to native apps
- Back Button Integration: Hardware back button works correctly on Android
- Memory Management: Routes that are not visible can be unloaded to save memory
- Deep Linking: Integration with platform deep linking systems
- 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.