Client navigation
Use primate/client to navigate from browser code without a full page reload.
It is useful for interactions that happen outside a link, such as a desktop
notification click.
import client from "primate/client";
await client.navigate("/projects/42");client.navigate() is available only in browser code. Call it from a hydrated
frontend component, event handler, or other client-side module; do not call it
while rendering on the server.
Destinations
Pass either a relative or absolute URL:
await client.navigate("projects/42");
await client.navigate("/projects/42?tab=activity");
await client.navigate("https://app.example.com/projects/42");Relative URLs resolve from the current page. Same-origin destinations use Primate's SPA navigation: Primate fetches and updates the current frontend without a full document reload, updates browser history, and scrolls to a hash target when one is present.
External destinations use normal browser navigation instead:
await client.navigate("https://example.com");This lets application code use the same method without checking whether a URL belongs to the current app.
Notification example
For example, navigate when a notification is clicked:
import client from "primate/client";
notification.addEventListener("click", () => {
void client.navigate(`/projects/${project.id}`);
});Use void when the caller does not need to wait for the navigation to finish.
Refreshing the current route
Use refresh to fetch fresh server data for the current pathname and query
without changing the URL, adding a history entry, scrolling, or reloading the
document:
import client from "primate/client";
const refreshed = await client.refresh();The promise resolves to true after Primate applies the fresh route data and
dispatches the updated event. It resolves to false if the request fails, is
superseded by another navigation, redirects to another URL, or does not return
a successful Primate route response. In those cases, the current view, URL, and
history remain unchanged.
refresh is distinct from navigating to the current URL. A same-URL
client.navigate() call keeps its existing no-op behavior.
Links and events
Primate automatically intercepts ordinary same-origin links after hydration, so
you usually do not need to call client.navigate() from an anchor's click
handler. For custom link handling, pass the click event as the optional second
argument:
link.addEventListener("click", event => {
void client.navigate(link.href, event);
});For same-origin URLs, the event is prevented and the SPA navigation runs. For external URLs, the event is left untouched so the browser performs its normal link navigation.
Query strings and hashes
Query strings and hashes are preserved:
await client.navigate("/search?q=primate#results");Navigating to a different query string on the current route performs an SPA navigation. Navigating to a hash on the current route updates history and scrolls to the matching element.
Shallow navigation
Use shallow to update the query string without fetching, remounting the
current view, or scrolling:
await client.navigate("/search?q=primate", { shallow: true });The public request store updates immediately. Back and Forward update it again
without fetching while traversal remains within the same rendered view. Use
replace when the new URL should replace the current history entry:
await client.navigate("/search?q=framework", {
replace: true,
shallow: true,
});Shallow navigation applies only when the destination has the current pathname. A different pathname performs normal SPA navigation.
See Frontends for frontend setup and the available hydrated frontend integrations.