From harness-claude
Pre-renders Next.js pages at build time or on a schedule using SSG, generateStaticParams, and ISR for reduced server costs and faster CDN delivery.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:next-static-generationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Pre-render pages at build time or on a schedule using SSG, generateStaticParams, and ISR
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
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeAdvises optimal Next.js rendering strategies (SSG, SSR, ISR, CSR) based on content type, update frequency, SEO, and performance for pages and data fetching.
Provides patterns for static site generation including build-time rendering, incremental static regeneration, on-demand revalidation, and hybrid rendering for Next.js, Astro, and 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.