GameCraftGameCraft

NProgress Integration Guide

Learn how to integrate NProgress navigation feedback in ProductReady

NProgress Integration Guide

Overview

NProgress is integrated throughout the ProductReady application to provide visual feedback during page navigations. The implementation is designed to work seamlessly with Next.js 13+ App Router.

Architecture

Components

  1. NProgressProvider (src/components/nprogress/nprogress-provider.tsx)

    • Client component that tracks route changes
    • Uses usePathname() and useSearchParams() hooks
    • Automatically shows/hides progress bar on navigation
    • Configured once on mount
  2. NProgressLink (src/components/nprogress/nprogress-link.tsx)

    • Wrapper around next/link that starts progress on click
    • Respects onClick event handlers
    • Honors preventDefault() calls
  3. useNProgressRouter (src/components/nprogress/nprogress-link.tsx)

    • Hook that wraps Next.js useRouter with progress indication
    • Provides: push, replace, back, forward, refresh
    • Each navigation method starts NProgress automatically
  4. configureNProgress (src/components/nprogress/nprogress-config.ts)

    • Centralized configuration
    • Called once when NProgressProvider mounts

Integration Points

Root Layout (layout.tsx)
  └─ Global CSS (includes nprogress.css)
  
[lang] Layout (for marketing pages)
  └─ LangLayoutClient (client component)
      └─ NProgressProvider
          └─ RootProvider (Fumadocs)
              └─ Children (marketing pages)

(dashboard) Layout (for dashboard pages)
  └─ ThemeProvider
      └─ TRPCProvider
          └─ NProgressProvider
              └─ Children (dashboard pages)

Usage

Automatic (No Code Changes)

Most navigation is handled automatically:

  • All internal <a> link clicks are intercepted globally - no special components needed
  • Existing next/link components work automatically
  • Fumadocs sidebar, breadcrumbs, and navigation links work automatically
  • Browser back/forward buttons trigger progress
  • URL changes from any source show progress

The NProgressProvider uses a global click listener that intercepts all internal link clicks, so you don't need to use special Link components like NProgressLink or WebLink for NProgress to work.

Manual Control (Advanced)

import { NProgressLink } from '~/components/nprogress';

// Replace next/link with NProgressLink
<NProgressLink href="/dashboard" className="...">
  Go to Dashboard
</NProgressLink>

Using useNProgressRouter

import { useNProgressRouter } from '~/components/nprogress';

function MyComponent() {
  const router = useNProgressRouter();
  
  const handleClick = () => {
    // Progress bar starts automatically
    router.push('/settings');
  };
  
  return <button onClick={handleClick}>Settings</button>;
}

Direct NProgress API

import NProgress from 'nprogress';

// Manual start
NProgress.start();

// Manual complete
NProgress.done();

// Set specific percentage (0 to 1)
NProgress.set(0.4);

// Increment
NProgress.inc();

Configuration

Global Settings

Edit src/components/nprogress/nprogress-config.ts:

NProgress.configure({
  showSpinner: true,    // Show spinner in top-right
  speed: 400,           // Animation speed (ms)
  minimum: 0.08,        // Starting percentage
  easing: "ease",       // CSS easing function
  trickle: true,        // Auto-increment
  trickleSpeed: 200,    // Trickle interval (ms)
});

Styling

Edit src/app/global.css under the "NProgress custom styling" section:

/* Progress bar color */
#nprogress .bar {
  background: oklch(0.646 0.222 41.116); /* Light mode */
}

.dark #nprogress .bar {
  background: oklch(0.769 0.188 70.08); /* Dark mode */
}

/* Bar height */
#nprogress .bar {
  height: 3px; /* Adjust as needed */
}

/* Spinner color */
#nprogress .spinner-icon {
  border-top-color: oklch(0.646 0.222 41.116);
  border-left-color: oklch(0.646 0.222 41.116);
}

Best Practices

DO

✅ Use automatic integration (no code changes needed) ✅ Keep progress bar visible but subtle ✅ Test on slow connections (Network Throttling in DevTools) ✅ Ensure contrast in both light and dark modes ✅ Call NProgress.done() when programmatically controlling

DON'T

❌ Start progress without finishing it (causes stuck progress bar) ❌ Use NProgress for non-navigation loading (use Suspense instead) ❌ Call NProgress.start() twice without done() in between ❌ Override styles without maintaining theme consistency

Debugging

Progress Bar Doesn't Appear

  1. Check browser console for errors
  2. Verify NProgressProvider is in the component tree
  3. Ensure CSS is imported (@import "nprogress/nprogress.css")
  4. Check z-index conflicts (NProgress uses z-index: 9999)

Progress Bar Gets Stuck

// Force complete the progress
NProgress.done(true);

// Or in console:
window.NProgress.done(true);

Multiple Progress Bars

This happens when multiple NProgressProviders are mounted. Ensure only one provider exists in the component tree (at layout level).

Performance

  • Bundle Size: ~2KB gzipped (nprogress library)
  • Runtime Overhead: Negligible (passive event listeners)
  • Animation Cost: Uses CSS transforms (GPU accelerated)

Browser Support

NProgress works in all modern browsers:

  • Chrome/Edge (latest)
  • Firefox (latest)
  • Safari (latest)
  • Mobile browsers (iOS Safari, Chrome Mobile)

Accessibility

  • Progress bar is visual only (no ARIA announcements)
  • Does not interfere with screen readers
  • Does not trap keyboard focus
  • Color contrast meets WCAG AA standards in both themes

Migration from Pages Router

If migrating from Next.js Pages Router:

  1. Remove old router event listeners (router.events.on)
  2. Remove manual NProgress.start() / NProgress.done() calls
  3. Add NProgressProvider to your App Router layout
  4. Navigation will work automatically

Further Reading

On this page