nextjs-rendering

Provides expert guidance on Next.js rendering behavior, including static vs dynamic rendering, streaming, Suspense boundaries, cache components, and the prospective render system. Use when working with Next.js SSG, ISR, streaming, server components, or debugging rendering modes.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "nextjs-rendering" with this command: npx skills add goncy/skills/goncy-skills-nextjs-rendering

Next.js Rendering

Expert guidance on Next.js rendering modes, streaming behavior, and static vs dynamic page generation.

Static vs Dynamic Rendering

Next.js has two fundamental rendering types: static and dynamic.

Static rendering:

  • Pages are built at build time and uploaded to a CDN
  • No compute occurs at request time
  • Assets are replicated to edge locations globally
  • Faster response times (no compute, cached near user)
  • Remains available even if origin region goes down

Dynamic rendering:

  • Pages are executed on-demand in a configured region
  • Involves compute at request time
  • Goes down if the region becomes unavailable
  • Required when content cannot be determined at build time

SSG (Static Site Generation) and ISR (Incremental Static Regeneration) are the same underlying mechanism — the only difference is whether all paths are generated upfront or incrementally on-demand.

Determining Render Mode: Async Dynamic APIs

Next.js determines whether a page is static or dynamic using async dynamic APIs. The framework performs a prospective render to detect what resolves synchronously vs asynchronously.

The microtask test:

  1. Next.js runs an initial "warmup render" to search for cached instances and fill caches
  2. A second render runs for just one tick, then aborts
  3. Anything that resolves within that microtask is considered "instant" and can be static
  4. Anything that cannot resolve in one tick is treated as dynamic

Special case for params: Routes using params can be static because each route is called once per item in generateStaticParams. Since the params are known at build time, they resolve instantly.

// Static: params from generateStaticParams resolve instantly
export async function generateStaticParams() {
  return [{ id: '1' }, { id: '2' }];
}

export default async function Page({ params }: { params: { id: string } }) {
  // params.id is instant - this page can be static
}

Streaming and Suspense Boundaries

Streaming is only enabled for dynamic rendering. Static content does not stream because no compute is involved — the complete HTML is served from the CDN.

Document-level Suspense requirement: To enable streaming with a loading skeleton, wrap the HTML document with an empty Suspense boundary. Without a document wrapper outside the boundary, there is nothing to stream — the framework needs the outer shell to send while inner content loads.

// Enable streaming with document shell
<Suspense fallback={null}>
  <html>
    <body>
      <Suspense fallback={<Skeleton />}>
        <SlowComponent />
      </Suspense>
    </body>
  </html>
</Suspense>

ISR and Suspense fallbacks: Suspense boundary fallbacks do not display when generating ISR paths. Since ISR generation happens at build time or on first request (static generation), there is no streaming — the complete page is generated before being served.

Cache Components (use cache)

Cache components can combine static and dynamic rendering within the same page, but the page itself still has a render mode.

Applying use cache to a page component: When use cache is added to a page or the main component of a page, the page produces static output that:

  • Will be cached (static)
  • Won't be streamed
  • Won't have "holes" (Suspense boundaries) in it

Cache components with dynamic pages: Even with use cache on individual components, the page overall is still either static or dynamic. Cache components allow granular control — static cached sections within dynamic pages, or dynamic sections within static pages.

// Page-level cache: produces static output
'use cache';
export default async function Page() {
  // Entire page is static, no streaming
}

// Component-level cache: can mix static/dynamic
export default async function Page() {
  return (
    <>
      <StaticCachedSection />  {/* has 'use cache' */}
      <DynamicSection />        {/* no cache directive */}
    </>
  );
}

Rendering Workflow

When working with Next.js rendering:

  1. Determine if the page can be static (all data available at build time)
  2. If static, decide between full SSG (all paths) or ISR (incremental)
  3. If dynamic is required, plan Suspense boundaries for streaming
  4. Add document-level Suspense wrapper if streaming with skeletons
  5. Use use cache granularly to cache expensive components within dynamic pages
  6. Remember: streaming only works for dynamic rendering, not static/ISR

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

whatsapp-web-js

No summary provided by upstream source.

Repository SourceNeeds Review
General

nextjs-caching

No summary provided by upstream source.

Repository SourceNeeds Review
General

nano-banana-2

Nano Banana 2 - Gemini 3.1 Flash Image Preview

Repository Source