Skip to content

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?