Getting started
Install the package, register the services, declare two routes - a working router in five minutes, in any Blazor render mode.
1 · Install
Bit.Brouter targets net8.0, net9.0 and net10.0, and brings its JavaScript
along as a static web asset - there is no script tag to add. The optional
Bit.Brouter.Generators package is an analyzer-only companion that generates
the typed BrouterRoutes URL builders.
# The router itself: dotnet add package Bit.Brouter # Optional - typed, compile-time-safe URL builders: dotnet add package Bit.Brouter.Generators <!-- ...or declare them in your .csproj. PrivateAssets="all" on the generator keeps the analyzer out of your own package's dependencies: --> <PackageReference Include="Bit.Brouter" Version="10.6.0-pre-03" /> <PackageReference Include="Bit.Brouter.Generators" Version="10.6.0-pre-03" PrivateAssets="all" />
2 · Register the services
Add AddBitBrouterServices in Program.cs (in a Blazor Web App,
register it on both the server and the client project), and add
@using Bit.Brouter to your _Imports.razor. Every option has a
sensible default - the callback is where routing behavior is configured app-wide.
// Program.cs builder.Services.AddBitBrouterServices(o => { o.CaseSensitive = false; // default o.IgnoreTrailingSlash = true; // default o.ViewTransitions = true; // animated page changes o.ScrollBehavior = BrouterScrollMode.ToTop; o.ScrollToFragment = true; // /docs#install scrolls #install into view o.FocusOnNavigateSelector = "h1"; // move focus after navigation (accessibility) // constraints, loader caching, keep-alive and more live here too });
3 · Hand Brouter the URL space
In a Blazor Web App, a single catch-all host page routes every URL to Brouter
(this is exactly how this site is wired). In a standalone WebAssembly app, render
<Brouter> directly from App.razor instead - no host page
needed.
@* Host.razor - the built-in router maps every URL here; Brouter takes over. *@ @page "/" @page "/{*path}" <AppRouter /> @code { [Parameter] public string? Path { get; set; } }
4 · Declare routes
Routes are components, so a route tree is just markup. Templates are a superset-compatible
match of the built-in router's - so your existing @page components keep
working: point AppAssembly at your app and they are discovered and matched
alongside the hand-declared tree.
@* AppRouter.razor *@ <Brouter NotFoundUrl="404" AppAssembly="@GetType().Assembly"> <Routes> <Broute Path="/" Component="@typeof(HomePage)" /> <Broute Name="user" Path="/users/{id:int}"> <Content><UserPage /></Content> </Broute> <Broute Path="404"> <Content><h1>404</h1><p>Nothing here.</p></Content> </Broute> </Routes> </Brouter>
5 · Link and navigate
<BrouterLink> renders a real anchor with active-class and
aria-current handling; the injected IBrouter service is the
programmatic side.
<BrouterLink Href="/users/42">Saleh</BrouterLink> // anywhere, via DI: @inject IBrouter brouter brouter.Navigate("/users/42");
Where next?
- How a navigation works - the best next read: one page that explains the order everything else happens in.
- Route templates - the full grammar your paths can use.
- Nested routes & outlets - persistent layouts around swapping children.
- Guards and data loading - deciding whether to navigate, and fetching before you render.
- Recipes - ready-made answers to the things apps usually need next.
- Migration guide - moving an existing app off the built-in Router.