When building large-scale websites with thousands or millions of pages using Incremental Static Regeneration (ISR), updating navigation data can cause revalidating every page that includes the navigation component. Since each page regeneration consumes server resources, this widespread revalidation will result in large resource usage in terms of function duration, bandwidth, and hits on the backend.
With Vercel, you can render navigation using build-time data for fast loads, then update it using a shared endpoint to keep all pages current without individual revalidation.
In this guide, you'll learn:
- How to apply smart revalidation to update navigation without triggering full ISR revalidation for every page, thereby reducing function duration, bandwidth, and backend load.
- How to fetch navigation data on the client once per session and reuse it across pages for a consistent, fresh experience.
- How lightweight server-side caching ensures fast responses without overwhelming infrastructure.
Your navigation data stays fresh whilst maintaining good UX using the following process:
- The initial render at build time uses server data for instant paint and no layout shift.
- The application fetches a shared navigation endpoint once and reuses the data across pages in the same session
- Server-side caching refreshes the endpoint periodically to keep responses current without forcing ISR revalidation of every page
- Manual triggers such as a CMS webhook or an client-side button, can revalidate the navigation instantly
- SWR handles recovery, automatically fetching fresh navigation data when a user reconnects to the internet
This ensures users always see up-to-date navigation while browsing the site, whether through client-side transitions or full page reloads.
Let's review how to implement this by exploring an existing demo repository.
Start by cloning and running the MegaNav Demo repository to see the implementation in action:
git clone https://github.com/vercel-solutions/meganav-demo.gitcd meganav-demopnpm installpnpm run dev
- Open http://localhost:3000 to see the demo running.
- Click on Products in the top navigation
- Notice how the navigation shows timestamps that update in real-time without affecting page performance
SWR provides automatic polling to keep navigation data fresh on the client side. The following component is imported in the app/layout.tsx
file and used in all pages:
const { data: nav } = useSWR<NavigationData>('/api/navigation', fetcher, { fallbackData, revalidateOnFocus: false, revalidateOnMount: true, revalidateOnReconnect: true, refreshInterval: 10000, // 10 seconds for demonstration purposes only});// Ensure we always have data to renderconst navigationData = nav || fallbackData;
refreshInterval
to 10 seconds is for demonstration purposes only. In a production environment, you will not need refreshInterval
as revalidateOnMount
and revalidateOnReconnect
are sufficient.Test SWR behavior:
- Open the browser's Network tab
- Watch for requests to
/api/navigation
every 10 seconds - Notice how the navigation timestamps updates automatically
The navigation API uses server-side caching with a 5-minute revalidation period. This ensures fresh data without overwhelming your server.
import { getNavigationData } from '@/lib/mock-nav';import { NextResponse } from 'next/server';
export const revalidate = 360; // every 5 minutes for demonstration purposes
export async function GET() { // needs to be wrapped in the async function in order bundler not to pack it as static const data = await getNavigationData(); return NextResponse.json(data);}
You can trigger immediate navigation updates using ISR on-demand revalidation.
import { revalidatePath } from 'next/cache';import { NextResponse } from 'next/server';
export async function GET() { try { revalidatePath('/api/navigation'); return NextResponse.json({ revalidated: true, now: Date.now() }); } catch (err) { console.log(err); return NextResponse.json( { message: 'Error revalidating' }, { status: 500 }, ); }}
Test manual revalidation:
- Open http://localhost:3000
- Click on Products in the top navigation and notice the timestamp for each item
- Click the Simulate Headless CMS Change button
- Watch the navigation timestamps update immediately
- Note that the page content timestamp does not change
You can implement this system directly with a headless CMS. Instead of using a button, you will trigger revalidation with specific CMS events such as content publishing. You can do this with many CMSs using a webhook.
- Navigation API: Use on-demand ISR with 1 day time-based revalidation. If you use time-based revalidation only, set it to 5-15 minutes for fresh data.
- ISR Pages: 1-24 hours revalidation for stable content
- MegaNav Demo Repository - Clone and experiment with the complete implementation
- Next.js App Router Documentation - Learn more about Next.js routing and API routes
- SWR Documentation - Explore advanced data fetching patterns