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>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.
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.