git clone https://github.com/Intense-Visions/harness-engineering
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/codex/next-server-components" ~/.claude/skills/intense-visions-harness-engineering-next-server-components-9ec3bc && rm -rf "$T"
agents/skills/codex/next-server-components/SKILL.mdNext.js Server Components
Keep data fetching and heavy logic on the server; push interactivity to the client only where needed
When to Use
- Fetching data that does not require browser APIs or user interaction
- Accessing backend resources (databases, file system, internal APIs) directly in components
- Reducing client-side JavaScript bundle size
- Passing sensitive credentials (API keys, tokens) through server-only code paths
- Deciding where to draw the
boundary in a component tree'use client'
Instructions
- Every component in
is a Server Component by default — no directive needed. Addapp/
only when the component uses hooks, browser APIs, or event handlers.'use client' - Server Components can be
—async
data directly inside the component body instead of usingawait
.useEffect - Never import server-only modules (database clients,
, secret env vars) into Client Components. Use thefs
package to enforce this at build time.server-only - Pass server-fetched data to Client Components as props — do not share state across the boundary directly.
- Place
as close to the leaf as possible — this minimizes the client bundle.'use client' - Client Components can import and render Server Components as children via the
prop (composition), but cannot import a Server Component module directly.children - Use
to deduplicate fetch calls across a request when multiple Server Components fetch the same data.React.cache() - Mark utility modules with
to prevent accidental client-side imports.import 'server-only'
// app/dashboard/page.tsx — Server Component (async, no directive) import { db } from '@/lib/db'; // server-only module — safe here import { MetricCard } from './metric-card'; // Client Component receives data as props export default async function DashboardPage() { const metrics = await db.query.metrics.findMany(); return ( <div> {metrics.map(m => <MetricCard key={m.id} metric={m} />)} </div> ); } // app/dashboard/metric-card.tsx — Client Component 'use client'; import { useState } from 'react'; export function MetricCard({ metric }: { metric: Metric }) { const [expanded, setExpanded] = useState(false); return <div onClick={() => setExpanded(e => !e)}>{metric.label}</div>; }
Details
React Server Components (RSC) render on the server and send HTML + a serialized component tree to the client. They never ship their module code to the browser, so they can safely import server-only dependencies.
The boundary model:
'use client' marks a module as the root of a client subtree. All modules imported by that module are also bundled for the client — the directive propagates downward through the import graph. This is why pushing the boundary toward leaves reduces bundle size.
Serialization constraints: Props crossing the server→client boundary must be serializable (strings, numbers, plain objects, arrays). Functions, class instances, and Promises cannot be passed directly as props to Client Components (Promises can be passed to Suspense-aware Client Components via
use()).
Common mistakes:
- Adding
to a file that imports a database client — the database client ends up in the bundle'use client' - Fetching data in a Client Component with
when a Server Component parent could fetch it directlyuseEffect - Importing a Client Component into a Server Component and then re-exporting it — this works fine; the Client Component is still bundled only once
Performance note: Server Components reduce Time to First Byte (TTFB) for data-heavy pages because HTML arrives pre-rendered. Interactivity is hydrated progressively.
Source
https://nextjs.org/docs/app/building-your-application/rendering/server-components
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.