Guides
Link and Navigation
Use Link for app navigation that should participate in Mreact's client navigation runtime. It gives you route-aware prefetching, scroll behavior, and controlled document reloads without turning a server-rendered route into a hydrated client route.
Use Link for app navigation
Use Link from @reckona/mreact-router/link for internal app links. Raw anchors are still valid for plain HTML and external destinations, but Link is the right default when you want route navigation behavior.
import { Link } from "@reckona/mreact-router/link";
export default function Page() {
return <Link href="/docs">Docs</Link>;
}Typed route hrefs
Concrete Link hrefs can be typed directly. Build output includes .mreact/routes.d.ts, which declares discovered app route patterns and augments @reckona/mreact-router/link. Include that declaration in your TypeScript program, and Link will type-check internal href strings without importing any generated runtime module.
The generated file contains declare module "@reckona/mreact-router/link" so the public Link type learns your app's route union at type-check time.
{
"include": ["src", ".mreact/routes.d.ts"]
}The same generated declaration exports AppRouteParams<Path> and AppRouteParamMap for route-aware helper code that needs the params shape without duplicating folder names by hand. A route such as src/app/users/$id/files/$...path/page.tsx maps to AppRouteParams<"/users/:id/files/:...path"> with { readonly id: string; readonly path: readonly string[] }, so renaming a route folder updates the generated params type on the next build.
For dynamic routes, pass a concrete URL to Link. The generated declaration checks that the URL matches a discovered route shape, so dynamic params are required at compile time as path segments, unknown route shapes are rejected, and external URLs stay outside the internal route type.
import { Link } from "@reckona/mreact-router/link";
export function UserLink(props: { user: { id: string; name: string } }) {
return (
<Link href={`/users/${encodeURIComponent(props.user.id)}?tab=activity#profile`}>
{props.user.name}
</Link>
);
}For catch-all routes, encode each decoded segment and join them into the concrete URL:
import { Link } from "@reckona/mreact-router/link";
export function FileLink(props: { path: readonly string[] }) {
const encodedPath = props.path.map(encodeURIComponent).join("/");
return (
<Link href={`/files/${encodedPath}`}>
Open file
</Link>
);
}Use href() only for runtime construction
Use href() from @reckona/mreact-router when code needs runtime URL construction from Mreact route patterns, especially when you want one helper to encode params, search values, and hashes. It remains public and safe to use, but it is no longer required just to get typed Link hrefs.
import { href } from "@reckona/mreact-router";
import { Link } from "@reckona/mreact-router/link";
export function UserLink(props: { user: { id: string; name: string } }) {
return (
<Link
href={href("/users/:id", {
hash: "profile",
params: { id: props.user.id },
search: { tab: "activity" },
})}
>
{props.user.name}
</Link>
);
}Importing href() into a client route includes the URL-building helper in that route's client bundle. For ordinary links with already-constructed strings, prefer Link href directly.
Prefetch, not preload
The API is named prefetch, not preload. It controls navigation preparation, not server runtime module preloading or HTML asset preload links.
import { Link } from "@reckona/mreact-router/link";
export function Navigation() {
return (
<nav>
<Link href="/dashboard" prefetch="intent">Dashboard</Link>
<Link href="/docs" prefetch="viewport">Docs</Link>
<Link href="/settings" prefetch="none">Settings</Link>
</nav>
);
}prefetch="intent" is the default behavior for likely user intent. prefetch="viewport" prepares links when they enter the viewport. prefetch="none" disables route prefetch for links where eager work would be wasteful or surprising.
Scroll and document reloads
Use scroll="preserve" when the current scroll position should survive navigation, such as editor panes or long virtualized views. Use reload when a link should force a full document navigation instead of app navigation.
import { Link } from "@reckona/mreact-router/link";
export function ToolbarLinks() {
return (
<nav>
<Link href="/editor" scroll="preserve">Editor</Link>
<Link href="/legacy" reload>Legacy page</Link>
</nav>
);
}Navigation runtime
Server-only routes can get the lightweight navigation runtime without becoming hydrated client routes. When Mreact can see a rendered Link in the server-rendered route tree, it injects the navigation runtime automatically.
Use navigationRuntime only to override automatic detection:
export const navigationRuntime = false;Set it to false when a route must stay JavaScript-free even though it renders Link. Set it to true when navigation links are hidden behind a pattern the analyzer cannot see, such as a render prop, higher-order component, or runtime props value.
Same-origin navigation
Mreact intercepts same-origin app navigation and updates the changed route payload without a full document reload. During client navigation, it keeps route data, metadata, scroll restoration, and client route scripts synchronized.
External URLs use normal document navigation. Use reload for an internal URL when the browser should also perform a normal document navigation.