Render on the Server, Send Zero JS
Server Components — the Default
Every component in `app/` is a Server Component unless marked otherwise. They run on the server, can read databases directly, and ship only HTML to the browser.
What you'll learn
- Recognize Server Components as the default in `app/`
- See zero-JS rendering for static content
- Read data directly without `useEffect`
Server Components are the App Router’s headline feature. They run on the server, can await
data, and send only the rendered HTML — no React, no component code — down the wire.
The Default Behavior
Any file inside app/ is a Server Component unless you add 'use client'. That means you
can await data right inside the component body — no useEffect, no loading flags.
// app/posts/[id]/page.tsx
import { db } from '@/lib/db'
export default async function PostPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params
const post = await db.posts.findById(id)
return (
<article>
<h1>{post.title}</h1>
<p>{post.body}</p>
</article>
)
} The browser receives HTML. The component code never ships.
Zero JavaScript For Static Content
A page made entirely of Server Components ships zero React component code to the client. The framework runtime is still there, but your component logic stays on the server.
export default function About() {
return <h1>About us</h1>
} That renders as plain HTML. Bundle size for the page: effectively nothing of your own code.
Things Server Components Cannot Do
No useState, no useEffect, no event handlers like onClick. Those need the client.
When you need interactivity, reach for a Client Component.