Incremental Static Regeneration (ISR)
Overview#
Incremental Static Regeneration (ISR) lets you build static pages at deploy time and update them without a full rebuild. When combined with the Uniform Page Router SDK, ISR gives you the performance benefits of static pages with the content freshness of server-side rendering.
ISR is configured through the standard Next.js getStaticProps and getStaticPaths functions, which the Uniform SDK wraps with withUniformGetStaticProps and withUniformGetStaticPaths.
How ISR works with the Page Router#
At build time,
getStaticPathsfetches all paths from the Uniform Project Map.getStaticPropsresolves each composition via the Route API and pre-renders the page.At runtime, cached pages are served instantly from the CDN. Pages not pre-rendered at build time (or new pages added after the build) are rendered on their first request and cached (because
fallback: true).When content changes, pages are revalidated either on a time interval (
revalidateoption) or on-demand via a webhook from Uniform.
Basic ISR setup#
Step 1: Use withUniformGetStaticProps and withUniformGetStaticPaths#
By default, withUniformGetStaticPaths returns { fallback: true }, which means:
- Pages listed in the paths array are pre-rendered at build time.
- Pages not in the list are rendered on their first request and then cached.
- This is the recommended default -- it ensures new pages work immediately without requiring a rebuild.
Step 2: Add time-based revalidation (optional)#
To periodically refresh static pages, use handleComposition to add a revalidate value:
With revalidate: 30, Next.js serves the cached page to visitors but regenerates it in the background if the cached version is older than 30 seconds. This is the "stale-while-revalidate" pattern.
Understanding the trade-offs#
Option A: SSG with fallback (recommended starting point)#
Build time: Proportional to number of pages. First visit (known pages): Instant. First visit (new pages): On-demand render, then cached. Best for: Most sites with moderate page counts.
Option B: SSG with no pre-rendering#
Build time: Fastest (seconds). First visit: On-demand render, then cached. Best for: Sites with many pages where build time is a concern.
To return an empty paths array:
Option C: SSG with revalidation#
Combines pre-rendering with periodic background regeneration:
Build time: Proportional to pages. Content freshness: Within the revalidation window. Best for: Content that changes regularly but does not need instant updates.
note
For most Uniform projects, Option A (SSG with fallback) combined with on-demand revalidation via webhooks provides the best balance of performance and content freshness. Time-based revalidation (revalidate) is useful as a safety net but should not be your primary cache invalidation strategy.
Customizing static paths#
Filtering paths#
Use the callback option to filter which paths are pre-rendered:
Scoping to a subtree#
Use rootPath to only fetch paths under a specific project map node:
Custom project map client#
Override the default client if you need custom API host or authentication:
On-demand revalidation via webhooks#
When content is published in Uniform, you want cached static pages to update without a full rebuild. Next.js Page Router supports on-demand revalidation through the res.revalidate() API.
How it works#
Step 1: Create the revalidation API route#
Create a dedicated API route to handle revalidation webhooks:
Step 2: Configure the webhook in Uniform#
- Go to your Uniform project in the dashboard.
- Navigate to Settings -> Webhooks.
- Click Add webhook.
- Configure the webhook:
- URL:
https://your-site.com/api/revalidate?secret=your-secret-value-here - Events: Select
composition.published,composition.deleted,projectMapNode.update, and any other events you want to trigger revalidation.
- URL:
- Save the webhook.
warning
Make sure not to select *.changed webhook events (like composition.changed) as those fire during content authoring and will cause unnecessary revalidation requests. Only select *.published and *.deleted events.
Step 3: Handle composition-specific paths#
For more granular revalidation, parse the webhook payload to identify which composition changed and resolve its project map paths:
ISR with personalization#
When using ISR with personalization, keep in mind:
Client-side personalization (default) works seamlessly with ISR. All visitors receive the same static page, and personalization variants are resolved in the browser. This may cause a brief visual flicker as the page swaps variants after hydration.
Edge-side personalization (via
@uniformdev/context-edge-vercel) eliminates the flicker by resolving variants at the edge before the page is served. This is the recommended approach for ISR sites that need personalization without flicker. See Edge-side personalization in the main guide.
note
With client-side personalization, there is no need to generate multiple static pages per route (one for each variant combination). The single static page contains all variants, and the context engine selects the correct one on the client. This keeps build times fast.
CDN provider compatibility#
On-demand revalidation requires your hosting provider to support the Next.js res.revalidate() API:
| Provider | Support |
|---|---|
| Vercel | Full support |
| Self-hosted | Supported with persistent .next cache directory |
| Netlify | Supported via Netlify's Next.js runtime |
| Cloudflare | Supported via Open Next adapter |
Consult your provider's documentation to ensure on-demand ISR is compatible with your deployment setup.