From harness-claude
Pre-renders Next.js App Router pages at build time or on schedule using SSG, generateStaticParams, and ISR. For static content, dynamic slugs, high-traffic pages, and CMS-triggered updates.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Pre-render pages at build time or on a schedule using SSG, generateStaticParams, and ISR
Implements static site generation for instant TTFB, SEO, and infrequent updates using ISR, on-demand revalidation, hybrid rendering in Next.js, Astro, Gatsby.
Guides Next.js data fetching with SSG, SSR, ISR, fetch caching strategies like force-cache and no-store, revalidation, dynamic rendering, and generateStaticParams for data-driven apps.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Share bugs, ideas, or general feedback.
Pre-render pages at build time or on a schedule using SSG, generateStaticParams, and ISR
/posts/[slug])cookies(), headers(), searchParams) and not setting dynamic = 'force-dynamic'.generateStaticParams() from a dynamic route's page.tsx to pre-render all known slugs at build time.export const revalidate = 60 (seconds) at the page or layout level to enable ISR — the page re-generates in the background after the interval.revalidatePath() or revalidateTag() from a Server Action or route handler for on-demand ISR triggered by a CMS webhook.{ next: { tags: ['posts'] } } to fetch() to attach cache tags for granular invalidation.export const dynamicParams = false to return 404 for slugs not returned by generateStaticParams().notFound() inside generateStaticParams() return values — simply omit slugs you want to 404.// app/posts/[slug]/page.tsx
import { notFound } from 'next/navigation';
export const revalidate = 3600; // Re-generate every hour
export async function generateStaticParams() {
const posts = await fetch('https://api.example.com/posts', {
next: { tags: ['posts'] },
}).then(r => r.json());
return posts.map((p: { slug: string }) => ({ slug: p.slug }));
}
export default async function PostPage({ params }: { params: { slug: string } }) {
const post = await fetch(`https://api.example.com/posts/${params.slug}`, {
next: { tags: [`post-${params.slug}`] },
}).then(r => r.json());
if (!post) notFound();
return <article>{post.content}</article>;
}
Next.js App Router has four rendering modes: static (default), dynamic, streaming, and ISR. Static generation produces HTML at build time and serves it from a CDN — zero server compute per request.
ISR mechanics: When revalidate is set, Next.js uses a stale-while-revalidate strategy. The first request after the interval triggers a background regeneration; the stale page is served during regeneration. This means the interval is a minimum, not a guarantee — high-traffic pages regenerate quickly, low-traffic pages may take longer.
On-demand ISR: Call revalidatePath('/posts/my-slug') or revalidateTag('posts') from a route handler secured with a secret token. Wire this to your CMS webhook to regenerate pages immediately on content updates.
generateStaticParams at build time: Next.js calls generateStaticParams during next build and pre-renders every returned slug. If dynamicParams is true (default), slugs not pre-rendered are rendered on-demand and then cached. If false, they return 404.
fetch() caching: In the App Router, fetch() is extended to accept { next: { revalidate, tags } } options. This opts individual fetch calls into the Data Cache, separate from the HTTP cache. Server Components without any dynamic functions are cached by the Full Route Cache.
https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic-rendering