Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/cloudflare/vinext/llms.txt

Use this file to discover all available pages before exploring further.

The Link component enables client-side navigation without full page reloads. vinext’s implementation provides viewport-based prefetching, locale support, and scroll management.

Import

import Link from 'next/link'

Basic Usage

import Link from 'next/link'

export default function Navigation() {
  return (
    <nav>
      <Link href="/about">About</Link>
      <Link href="/blog">Blog</Link>
    </nav>
  )
}

API Reference

Props

href
string | UrlObject
required
The path or URL to navigate to.Can be a string:
<Link href="/dashboard">Dashboard</Link>
Or an object with pathname and query:
<Link href={{ pathname: '/user/[id]', query: { id: '123' } }}>
  User Profile
</Link>
as
string
URL displayed in the browser (for dynamic routes).Legacy pattern — use the href string directly instead:
{/* Old */}
<Link href="/user/[id]" as="/user/123">User</Link>

{/* New */}
<Link href="/user/123">User</Link>
replace
boolean
default:"false"
Replace the current history entry instead of pushing a new one.
<Link href="/login" replace>
  Login
</Link>
prefetch
boolean
default:"true"
Enable automatic prefetching when the link enters the viewport.Uses IntersectionObserver with a 250px margin. Set to false to disable:
<Link href="/heavy-page" prefetch={false}>
  Heavy Page
</Link>
scroll
boolean
default:"true"
Scroll to top after navigation (unless navigating to a hash).
<Link href="/page" scroll={false}>
  Stay at Current Scroll Position
</Link>
locale
string | false
Locale for i18n routing.
  • locale="fr" — prepend /fr prefix
  • locale={false} — use default locale (no prefix)
  • locale={undefined} — use current locale
<Link href="/" locale="fr">
  Français
</Link>
onNavigate
(event: NavigateEvent) => void
Called before navigation (Next.js 16+ View Transitions API).Call event.preventDefault() to handle navigation manually:
<Link 
  href="/about"
  onNavigate={(e) => {
    if (document.startViewTransition) {
      e.preventDefault()
      document.startViewTransition(() => {
        // Custom transition logic
      })
    }
  }}
>
  About with Transition
</Link>

Standard Anchor Props

All standard <a> attributes are supported:
<Link 
  href="/profile"
  className="nav-link"
  id="profile-link"
  onClick={(e) => console.log('clicked')}
  target="_blank"  // External links
  rel="noopener"
>
  Profile
</Link>

Prefetching

How It Works

  1. Viewport detection: When a <Link> enters the viewport (+ 250px margin), prefetching begins
  2. App Router: Fetches the .rsc payload and stores in memory cache
  3. Pages Router: Injects a <link rel="prefetch"> tag
  4. Deduplication: Each URL is prefetched only once

Cache TTL

Prefetched entries are valid for 30 seconds. After expiry, the link re-prefetches on next viewport entry.

Disabling Prefetch

{/* Never prefetch */}
<Link href="/admin" prefetch={false}>
  Admin Panel
</Link>

{/* Prefetch on hover instead */}
<Link 
  href="/search"
  prefetch={false}
  onMouseEnter={() => router.prefetch('/search')}
>
  Search
</Link>
Hash-only navigation updates the URL without triggering a full navigation:
<Link href="#section-2">Jump to Section 2</Link>
<Link href="?filter=active#results">Filter and Jump</Link>
Scrolls to the target element using element.scrollIntoView(). External URLs are passed through to the browser:
<Link href="https://example.com" target="_blank" rel="noopener">
  External Site
</Link>
No prefetching or client-side handling occurs.

useLinkStatus Hook

Track the pending state of a parent <Link>:
import Link, { useLinkStatus } from 'next/link'

function LinkContent() {
  const { pending } = useLinkStatus()
  
  return (
    <span>
      {pending && <Spinner />}
      Click Me
    </span>
  )
}

export default function Nav() {
  return (
    <Link href="/slow-page">
      <LinkContent />
    </Link>
  )
}

Router Integration

App Router

Calls window.__VINEXT_RSC_NAVIGATE__() to fetch and render the new RSC stream.

Pages Router

Dynamically imports the target page module and re-renders the React root.

basePath Support

If basePath is configured in next.config.js, it’s automatically prepended:
// next.config.js
module.exports = {
  basePath: '/docs'
}
{/* Renders as /docs/api */}
<Link href="/api">API</Link>

Limitations

Shallow routing: The shallow option is not supported in App Router (Next.js removed it).
Middleware rewrites: Links to rewritten paths work correctly, but the browser URL shows the rewrite destination (no masking).

Source

View source code → Implementation: /home/daytona/workspace/source/packages/vinext/src/shims/link.tsx

Build docs developers (and LLMs) love