Server Components render on the server with no JavaScript sent to the client, ideal for data fetching and static content. Client Components (marked with 'use client') render on both server and client, enabling interactivity like state and event handlers.
Server Components (Default in App Router):
await data directlyuseState, useEffect, event handlers, browser APIsClient Components:
'use client' directive at top of fileComposition Pattern:
Best Practice:
'use client' as far down the tree as possible// app/posts/page.tsx - Server Component
// No 'use client' = Server Component by default
import { db } from '@/lib/db'; // Can access DB directly!
export default async function PostsPage() {
// ✅ Can await data directly
const posts = await db.posts.findMany();
// ✅ Can access server-only resources
const apiKey = process.env.SECRET_API_KEY;
// ❌ Cannot use hooks
// const [count, setCount] = useState(0); // Error!
// ❌ Cannot use event handlers directly
// <button onClick={() => {}}>Click</button> // Error!
return (
<div>
<h1>Posts</h1>
{posts.map((post) => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.content}</p>
</article>
))}
</div>
);
}