npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@flightdev/router

v0.5.0

Published

Agnostic client-side routing primitives for Flight Framework

Readme

@flightdev/router

Universal client-side routing primitives for Flight Framework. Zero external dependencies. Works with any UI framework.

Table of Contents


Features

  • Multiple prefetch strategies (none, intent, render, viewport, idle)
  • Network-aware smart prefetching (respects Save-Data and connection speed)
  • Intercepting routes with modal support
  • Prefetch queue with concurrency control
  • SSR-safe implementation
  • Framework-agnostic with React adapters
  • TypeScript-first design
  • IntersectionObserver for viewport prefetching
  • Zero external dependencies

Installation

npm install @flightdev/router

Quick Start

With React

import { RouterProvider, Link, useRouter } from '@flightdev/router';

function App() {
    return (
        <RouterProvider initialPath={url}>
            <Navigation />
            <Content />
        </RouterProvider>
    );
}

function Navigation() {
    return (
        <nav>
            <Link href="/">Home</Link>
            <Link href="/docs" prefetch="intent">Docs</Link>
            <Link href="/about">About</Link>
        </nav>
    );
}

function Content() {
    const { path, navigate } = useRouter();

    return (
        <main>
            <p>Current path: {path}</p>
            <button onClick={() => navigate('/dashboard')}>
                Go to Dashboard
            </button>
        </main>
    );
}

Prefetch Strategies

Flight Router supports multiple prefetch strategies to optimize navigation performance:

| Strategy | Behavior | Best For | |----------|----------|----------| | 'none' | No prefetching (default) | Low-priority links | | 'intent' | Prefetch on hover/focus | Most navigation links | | 'render' | Prefetch immediately | Critical paths (checkout) | | 'viewport' | Prefetch when visible | Mobile, infinite scroll | | 'idle' | Prefetch when browser is idle | Background preloading |

Usage Examples

// No prefetching (default)
<Link href="/docs">Docs</Link>
<Link href="/docs" prefetch="none">Docs</Link>

// Prefetch on hover/focus (recommended for most cases)
<Link href="/docs" prefetch="intent">Docs</Link>
<Link href="/docs" prefetch>Docs</Link>  // boolean true = "intent"

// Prefetch immediately when link renders
<Link href="/checkout" prefetch="render">Checkout</Link>

// Prefetch when link enters viewport (good for mobile)
<Link href="/products" prefetch="viewport">Products</Link>

// Prefetch when browser is idle
<Link href="/settings" prefetch="idle">Settings</Link>

Smart Prefetching

Network-aware prefetching that respects user preferences and connection quality.

Features

  • Respects Save-Data header (users on limited data plans)
  • Detects connection type (2G, 3G, 4G)
  • Configurable minimum network requirements
  • Automatic throttling on slow connections

API

import {
    smartPrefetch,
    shouldSkipPrefetch,
    canPrefetchOnNetwork,
} from '@flightdev/router';

// Respects network conditions automatically
smartPrefetch('/dashboard');

// Check if prefetching should be skipped
if (shouldSkipPrefetch()) {
    console.log('Skipping due to network conditions');
}

// Custom network requirements
const canPrefetch = canPrefetchOnNetwork({
    respectSaveData: true,      // Skip if Save-Data enabled
    respectSlowNetwork: true,   // Skip on 2G/slow-2G
    minEffectiveType: '3g',     // Minimum 3G required
});

Configuration

smartPrefetch('/page', {
    respectSaveData: true,      // Default: true
    respectSlowNetwork: true,   // Default: true
    minEffectiveType: '3g',     // Default: '3g'
    priority: 'high',           // Optional priority override
});

Intercepting Routes

Render routes in modals while preserving URL state. Perfect for photo galleries, user profiles, and detail views.

React Integration

import {
    InterceptedRouteProvider,
    useInterceptedRoute,
} from '@flightdev/router';

// Wrap your layout
function RootLayout({ children }) {
    return (
        <InterceptedRouteProvider>
            {children}
            <ModalRenderer />
        </InterceptedRouteProvider>
    );
}

// Render intercepted content in a modal
function ModalRenderer() {
    const intercepted = useInterceptedRoute();

    if (!intercepted) return null;

    return (
        <Dialog open onClose={intercepted.dismiss}>
            <intercepted.Component />
            <button onClick={intercepted.navigateToPage}>
                View Full Page
            </button>
        </Dialog>
    );
}

Intercepted Route State

| Property | Type | Description | |----------|------|-------------| | Component | () => unknown | The component to render | | pathname | string | The intercepted URL path | | params | Record<string, string> | Route parameters | | dismiss() | () => void | Go back (close modal) | | navigateToPage() | () => void | Navigate to actual page |

Additional Hooks

import {
    useInterceptedRoute,
    useSetInterceptedRoute,
    useIsIntercepting,
} from '@flightdev/router';

// Check if currently intercepting
const isIntercepting = useIsIntercepting();

// Programmatically set intercepted state (for router integration)
const setIntercepted = useSetInterceptedRoute();

Programmatic Prefetching

import {
    prefetch,
    prefetchAll,
    prefetchWhenIdle,
    isPrefetched,
    clearPrefetchCache,
} from '@flightdev/router';

// Basic prefetch
prefetch('/docs');

// High priority prefetch
prefetch('/checkout', { priority: 'high' });

// Prefetch with data loaders
prefetch('/products', { includeData: true });

// Prefetch multiple pages
prefetchAll(['/page1', '/page2', '/page3']);

// Prefetch when browser is idle
prefetchWhenIdle('/dashboard');

// Check if already prefetched
if (!isPrefetched('/docs')) {
    prefetch('/docs');
}

// Clear prefetch cache (useful for testing)
clearPrefetchCache();

Prefetch Queue

Control concurrent prefetch requests to avoid overwhelming the network:

import { PrefetchQueue } from '@flightdev/router';

// Create queue with max 3 concurrent prefetches
const queue = new PrefetchQueue(3);

// Add URLs to queue
queue.add('/page1');
queue.add('/page2', { priority: 'high' });
queue.addAll(['/page3', '/page4', '/page5']);

// Control queue
queue.pause();   // Stop processing
queue.resume();  // Continue processing
queue.clear();   // Remove pending items

// Check state
console.log(queue.pending);     // Items waiting
console.log(queue.activeCount); // Currently prefetching

React Hooks

import {
    useRouter,
    useParams,
    useSearchParams,
    usePathname,
} from '@flightdev/router';

// Get current path and navigation functions
const { path, searchParams, navigate, back, forward } = useRouter();

// Get route parameters (from dynamic routes like [slug])
const { slug } = useParams<{ slug: string }>();

// Get and set search params
const [searchParams, setSearchParams] = useSearchParams();

// Get current pathname
const pathname = usePathname();

Programmatic Navigation

import { navigate, prefetch } from '@flightdev/router';

// Navigate to a path
navigate('/docs');

// Replace history instead of push
navigate('/login', { replace: true });

// Navigate without scrolling to top
navigate('/next-page', { scroll: false });

// Pass state data
navigate('/dashboard', { state: { from: '/login' } });

Route Matching

import { matchRoute, parseParams, generatePath } from '@flightdev/router';

// Check if a path matches a pattern
const { matched, params } = matchRoute('/docs/routing', '/docs/:slug');
// matched: true, params: { slug: 'routing' }

// Parse params from a path
const params = parseParams('/blog/2024/my-post', '/blog/:year/:slug');
// { year: '2024', slug: 'my-post' }

// Generate a path from pattern and params
const path = generatePath('/docs/:slug', { slug: 'api-routes' });
// '/docs/api-routes'

Link Component

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | href | string | required | Target URL path | | prefetch | boolean \| PrefetchStrategy | 'none' | Prefetch strategy | | replace | boolean | false | Replace history entry | | scroll | boolean | true | Scroll to top on navigate | | target | string | - | Link target (_blank, etc) | | className | string | - | CSS class | | aria-label | string | - | Accessibility label |

PrefetchPageLinks Component

For proactive prefetching based on user behavior:

import { PrefetchPageLinks } from '@flightdev/router';

function SearchResults({ results }) {
    return (
        <>
            {results.map(result => (
                <div key={result.id}>
                    <PrefetchPageLinks page={result.url} />
                    <Link href={result.url}>{result.title}</Link>
                </div>
            ))}
        </>
    );
}

Framework Integration

Vue

<script setup>
import { useLinkProps } from '@flightdev/router';

const docsLink = useLinkProps('/docs', { prefetch: 'intent' });
</script>

<template>
    <a v-bind="docsLink">Documentation</a>
</template>

Vanilla JavaScript

import { createLink, prefetch } from '@flightdev/router';

const link = createLink({
    href: '/docs',
    children: 'Documentation',
    prefetch: 'intent',
});

document.body.appendChild(link);

SSR Support

The router is SSR-safe. Pass the initial path from your server:

// entry-server.tsx
export function render(url: string) {
    return renderToString(
        <RouterProvider initialPath={url}>
            <App />
        </RouterProvider>
    );
}

Browser Support

| Feature | Chrome | Firefox | Safari | Edge | |---------|--------|---------|--------|------| | Prefetch | All | All | All | All | | Viewport (IntersectionObserver) | 51+ | 55+ | 12.1+ | 15+ | | Network Information API | 61+ | No | No | 79+ | | requestIdleCallback | 47+ | 55+ | No | 79+ | | fetchPriority | 101+ | No | No | 101+ |

Features gracefully degrade when APIs are unavailable.


TypeScript

Full TypeScript support with exported types:

import type {
    PrefetchStrategy,
    PrefetchOptions,
    SmartPrefetchOptions,
    InterceptedRouteState,
    InterceptedRouteContextValue,
} from '@flightdev/router';

License

MIT