Skip to main content
<Link> renders a plain <a> server-side, so it works with JavaScript off, on slow links, and during the brief moment before hydration completes. Once Pylon’s runtime is live, clicks get intercepted and Pylon does a client-side navigation instead of a full page reload.

What it does

The React root persists across navigations, so any layout that’s shared between the old and new route keeps its instance. State, scroll position, video playback — all survive the nav.

API

Any other anchor prop (className, target, rel, onClick, etc.) passes through.

Examples

Basic

A large paginated list with a “next page” link the user might never click:

Open in a new tab

Modifier keys + middle-click also fall through automatically — no special handling needed.

Programmatic navigation

<Link> is the prop-based API. For imperative nav (after a form submit, post-login redirect, etc.), call the global runtime:
The runtime is loaded as part of the shared chunk; window.__pylon is defined as soon as hydration completes. Use the ?. form to be safe on the first render. (Pylon has no RSC boundary, so there’s no "use client" directive — every page component already hydrates on the client.)

How nav actually works

  1. User clicks a <Link>. The runtime’s delegated handler picks it off a[data-pylon-link] clicks.
  2. Runtime fetches the target URL with the standard Accept: text/html header. The server SSRs the new page just like a direct navigation would.
  3. Runtime parses the response and extracts the __PYLON_DATA__ JSON tag (component name, layouts, props).
  4. Runtime looks up the new component in the bundle manifest and dynamically imports its entry chunk.
  5. The entry chunk’s hydrate(component, Page, Layouts) populates the route cache without re-rendering (the cache is keyed on component path).
  6. Runtime calls root.render(buildTree(Page, Layouts, newProps)). React’s reconciler diffs against the existing tree — shared layouts get reused, the page subtree swaps.
  7. history.pushState, scroll to top, done.
If anything fails (fetch errored, response wasn’t HTML, manifest didn’t know the component), the runtime falls back to window.location.href = href so the browser handles it the old-fashioned way.

Differences from Next.js’s <Link>

The hash-link + scroll props are on the roadmap.