The core shift is this: by default, components run on the server at request time (or build time). They can directly access databases, file systems, secrets, and server APIs. They never send their implementation code to the browser. The output is serialised UI — essentially a description of what to render — which the client receives and hydrates only where interactivity is needed.
Client components (marked with 'use client') are still React components in the traditional sense — they run in the browser, can use hooks, handle events, and manage local state. The key insight is that most of a typical application's component tree does not need any of this. Navigation, data display, layout, typography — none of it requires a browser.
The composition pattern that makes this work: server components can import and render client components, but client components cannot import server components. This creates a clear boundary — the server component tree fetches data and composes the page, and client components are inserted as interactive islands within it.