# Next.js Server Components — Part 1: The Model

## 1. What a Server Component Is

In the App Router, **every component is a Server Component by default** — it runs only on the server (or at build time for static routes), never ships its code to the browser, and can do things client code normally can't: read files, query a database directly, use server-only secrets, `await` inside the component body.

```tsx
// app/page.tsx — a Server Component, no directive needed, this is the default
import { db } from "@/lib/db";

export default async function Page() {
  const posts = await db.post.findMany(); // direct DB access, never sent to the browser
  return (
    <ul>
      {posts.map((p) => (
        <li key={p.id}>{p.title}</li>
      ))}
    </ul>
  );
}
```

There is no `useEffect` + loading state here — the component itself is `async`, and Next.js waits for it (or streams around it, per the Routing topic's `loading.tsx`) before sending HTML.

## 2. Why This Is a Big Deal

| | Client-fetched data (old SPA pattern) | Server Component data |
|---|---|---|
| Where the fetch runs | browser, after JS loads and hydrates | server, before any HTML is sent |
| Waterfall | client requests API, API queries DB — 2 network hops from the user's perspective | server directly queries DB — 0 extra client-visible hops |
| Bundle size | fetching library + data-shape code ships to the browser | zero — the component and its imports never leave the server |
| Secrets | API keys must go through a backend proxy, never in client code | can use DB credentials, private API keys directly |

Server Components collapse the client→API→database chain into a single server-side step, and the code that does it is never part of the JavaScript bundle sent to the browser.

## 3. Server Components Can Render Client Components

```tsx
// app/page.tsx (Server Component)
import LikeButton from "./LikeButton"; // a Client Component

export default async function Page() {
  const post = await getPost();
  return (
    <article>
      <h1>{post.title}</h1>
      <LikeButton postId={post.id} initialLikes={post.likes} />
    </article>
  );
}
```

```tsx
// app/LikeButton.tsx
"use client";
import { useState } from "react";

export default function LikeButton({ postId, initialLikes }: { postId: string; initialLikes: number }) {
  const [likes, setLikes] = useState(initialLikes);
  return <button onClick={() => setLikes((n) => n + 1)}>{likes} likes</button>;
}
```

This is the core composition pattern: static/data-heavy parts of the tree stay Server Components (zero client JS), and only the genuinely interactive leaf (`LikeButton`) is a Client Component, marked with `"use client"` — covered fully in its own topic. Server Components can pass **serializable** props (strings, numbers, plain objects, JSX) down into Client Components, but not functions or class instances, since those props have to cross the server/client boundary.

## 4. What Server Components Cannot Do

```tsx
export default function Page() {
  // ❌ no useState, useEffect, useContext, event handlers — no client runtime exists here
  // const [count, setCount] = useState(0);
  // ❌ no browser APIs (window, document, localStorage)
  return <div>...</div>;
}
```

Server Components have no lifecycle, no state, no effects, no event handlers — they run once, produce output, and that's the entire extent of their behavior. Anything interactive has to live in a Client Component.

## 5. Composition Rule: Client Components Cannot Import Server Components

```tsx
"use client";
// ❌ This is NOT allowed — importing a Server Component directly into a Client Component
// file forces it to also become part of the client bundle, defeating the purpose.
// import ServerOnlyThing from "./ServerOnlyThing";
```

```tsx
// ✅ Instead, pass the Server Component as `children` from a parent Server Component:
// app/page.tsx (Server Component)
import ClientWrapper from "./ClientWrapper";
import ServerOnlyThing from "./ServerOnlyThing";

export default function Page() {
  return (
    <ClientWrapper>
      <ServerOnlyThing />
    </ClientWrapper>
  );
}
```

```tsx
// app/ClientWrapper.tsx
"use client";
export default function ClientWrapper({ children }: { children: React.ReactNode }) {
  return <div className="wrapper">{children}</div>;
}
```

`ClientWrapper` never imports `ServerOnlyThing` — it just receives already-rendered content as `children`, so the Server Component's code still never enters the client bundle, even though it visually ends up "inside" a Client Component.

Continue to `fe_nextjs_server_components_theory_2.md` for the RSC "flight" serialization format, why `"use client"` is a compiler directive, and streaming.
