Documentation
Docs
Introduction
Getting Started
Tutorial: build an app
Core Concepts
Routing
Server-Side Rendering
Mimir, state management
Pages & Layouts
API Routes
Styling & Theming
Building & Deploying
API Reference
Guides
Recipes
FAQ (use cases)
The router
After hydration, navigation is the client router's job. ekko:rune/router exposes hooks to read the current
location and functions to change it, all without a server round-trip.
useRouter()
Returns a live object describing the current location and the navigation controls:
The hook subscribes to route changes, so a component using useRouter() re-renders when the URL changes
(including on back/forward).
useParams() and useSearchParams()
Focused hooks if you only need part of the location:
useParams() reads the params extracted when the current route was matched against __routes.
useSearchParams() parses location.search into an object.
navigate(href, opts?)
Imperatively navigate on the client:
navigate matches href against the client route table, imports the target page's chunk (cached after the
first time), renders it inside the layout, and updates history. No full page load. On the server (during
SSR) navigate is a no-op, the server does not navigate.
How matching works on the client
The hydration payload includes __routes: an array of { pattern, pageFile, guard } sorted static →
dynamic → catch-all (the same priority order as the server). On a navigation the router:
- Splits
hrefinto pathname + query. - Walks
__routesin priority order, testing each pattern (:parammatches one segment,*restmatches
the remainder).
- On the first match, records the extracted
params, dynamically importspageFile, and renders.
Because the route table is baked into the page, matching is instant and offline-capable, no request needed to decide where a link goes.
Reacting to navigation
Any component using useRouter()/useParams()/useSearchParams() re-renders on navigation. For
side-effects (analytics, scroll restoration), use an effect keyed on router.path:
Server vs client
| Server (SSR) | Client (after hydrate) | |
|---|---|---|
useRouter().path | the request path | the live pathname |
navigate(...) | no-op | client navigation |
params/query | from the request | from the matched route / location.search |
This means you can call useRouter() in a component that renders on both, it returns sensible values in
each environment, and your component does not need to branch on "am I on the server".
Next: links and the navigation rules, Navigation.