The App Router isn't just a new file structure — it's a fundamentally different model for building web apps. Server Components, streaming, and the new data fetching patterns change how you think about where logic lives. After migrating three large production apps, here are the patterns that actually work.
Server Components: The Right Mental Model
The key insight is that Server Components are not fetched components — they run on the server at request time and their output is serialized HTML. They never re-render, never have state, and their code never ships to the client. This is a fundamentally different primitive from useEffect + fetch.
Move the Client/Server boundary as far down the tree as possible. A component only needs 'use client' if it uses browser APIs, event handlers, or React hooks. Everything else can stay on the server.
Parallel Routes for Complex Layouts
Parallel routes let you render multiple pages in the same layout simultaneously — each with its own loading and error states. This is the App Router's answer to dashboard layouts where the sidebar, main content, and modals load independently.
Streaming with Suspense Boundaries
Wrap slow data fetches in Suspense to stream the fast parts of your page immediately, then progressively fill in slower sections. Users see content within 100ms instead of waiting 2 seconds for the slowest query to finish.