Routing guide
Progressive-enhancement routing in TypeScript
Build client-side navigation on top of real links and directly requestable URLs. White Label Router uses the History API as an enhancement instead of replacing browser navigation.
Start with real links
A public route should begin as an ordinary anchor with a meaningful href. The browser, keyboard users, crawlers, context menus, and no-JavaScript clients can all use that link before any client-side routing is initialized.
data-pushstate opts an eligible same-origin link into History API navigation after Router initializes.
<a href="/products/42" data-pushstate>View product 42</a>Scope routing when only one region is enhanced
An existing server-rendered page does not need to hand every link to one client router. Set navigationRoot to the Document or Element that owns the enhancement so only click events reaching that region are considered.
This is separate from router.scope, which remains application data passed to route callbacks. Multiple independently owned regions can coexist when their navigation roots do not overlap.
const router = new Router();
router.navigationRoot = document.querySelector('[data-account-area]');
router.initialize();Use one route contract in browser and server code
Browser initialization dispatches the current URL and attaches navigation listeners. Server code passes an explicit request URL through the same route matching, guard, query, and lifecycle contracts without requiring window or document.
Every public browser route should still be directly requestable from the server so progressive enhancement never becomes a crawler or accessibility dependency.
const router = new Router();
router.routes = {
'/products': (_scope, location) => console.log(location.data.url),
defaultRoute: () => true
};
router.initialize('/products/42?color=blue');Preserve native browser behavior
Modified clicks, non-left clicks, downloads, alternate targets, and cross-origin URLs remain native. Back and forward navigation reads the actual browser location rather than treating application history state as the source of truth.
Rejected programmatic navigation is atomic from Router’s perspective: failed guards, cross-origin browser URLs, and routes without runnable view behavior do not destroy the current route, push history, or replace the last successful Router location state.
That keeps routing an enhancement around web-platform navigation rather than a replacement for it.
Keep page context crawlable and accessible
Directly requested pages should return meaningful HTML with an appropriate title, description, canonical URL, and robots metadata. Browser route transitions can then update title and focus for interactive navigation.
Client route guards are an interface concern, not server authorization. Secure resources still need authorization at the server boundary.