install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/next-static-generation" ~/.claude/skills/intense-visions-harness-engineering-next-static-generation && rm -rf "$T"
manifest:
agents/skills/claude-code/next-static-generation/SKILL.mdsource content
Next.js Static Generation
Pre-render pages at build time or on a schedule using SSG, generateStaticParams, and ISR
When to Use
- Pages whose content does not change per-request (marketing pages, blog posts, documentation)
- Routes with a finite, known set of dynamic segments (e.g.,
)/posts/[slug] - High-traffic pages where serving from CDN cache is preferable to per-request rendering
- Implementing Incremental Static Regeneration (ISR) to refresh content on a schedule
- Reducing server compute costs by pre-rendering at build time
Instructions
- Make a page statically rendered by not using dynamic functions (
,cookies()
,headers()
) and not settingsearchParams
.dynamic = 'force-dynamic' - Export
from a dynamic route'sgenerateStaticParams()
to pre-render all known slugs at build time.page.tsx - Set
(seconds) at the page or layout level to enable ISR — the page re-generates in the background after the interval.export const revalidate = 60 - Use
orrevalidatePath()
from a Server Action or route handler for on-demand ISR triggered by a CMS webhook.revalidateTag() - Pass
to{ next: { tags: ['posts'] } }
to attach cache tags for granular invalidation.fetch() - Set
to return 404 for slugs not returned byexport const dynamicParams = false
.generateStaticParams() - Use
insidenotFound()
return values — simply omit slugs you want to 404.generateStaticParams()
// 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>; }
Details
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.
Source
https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic-rendering
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.