Rendering

Next.js supports multiple rendering strategies, each suited to different types of documentation content. This page covers the options and when to use each.

Server rendering

By default, all pages in the App Router are Server Components. Documentation content is rendered on the server and sent as HTML to the browser, resulting in fast initial page loads and excellent SEO.

app/docs/page.tsx
// This is a Server Component by default
export default function DocsPage() {
  return (
    <article className="docs-prose">
      <h1>Server-rendered documentation</h1>
      <p>This HTML is generated on the server.</p>
    </article>
  )
}

Static rendering

For documentation that rarely changes, use static rendering to pre-generate pages at build time. Next.js 16 introduces the "use cache" directive for explicit caching:

app/docs/guide/page.tsx
"use cache"

export default async function GuidePage() {
  const content = await fetchGuideContent()
  return <article>{content}</article>
}

Recommended for documentation

Static rendering is ideal for most documentation pages. It provides the fastest possible load times and reduces server load.

Streaming

For pages with slow data sources, streaming allows the shell to render immediately while content loads progressively:

app/docs/api-ref/page.tsx
import { Suspense } from "react"

export default function ApiRefPage() {
  return (
    <article className="docs-prose">
      <h1>API Reference</h1>
      <Suspense fallback={<div>Loading API docs...</div>}>
        <ApiContent />
      </Suspense>
    </article>
  )
}

async function ApiContent() {
  const data = await fetchApiDocs() // slow operation
  return <div>{/* render API docs */}</div>
}

Client Components

Interactive documentation features — such as live code editors, search, and theme toggles — require Client Components. Mark them with the "use client" directive:

components/live-editor.tsx
"use client"

import { useState } from "react"

export function LiveEditor({ initialCode }: { initialCode: string }) {
  const [code, setCode] = useState(initialCode)

  return (
    <div>
      <textarea value={code} onChange={(e) => setCode(e.target.value)} />
      <div className="preview">{/* Render preview */}</div>
    </div>
  )
}

Keep Client Components minimal

Only use "use client" for components that need interactivity. This keeps your documentation bundle small and pages fast.