The App Router is genuinely great. It's also genuinely confusing if you learned Next.js on the Pages Router. I rebuilt this entire portfolio with it and hit every footgun so you don't have to.
01. Server Components are the default — and that matters
Every component in the App Router is a Server Component by default. That means no useState, no useEffect, no browser APIs — unless you opt in with 'use client'. The mental shift is: render on the server unless you have a reason not to.
// ✅ Server Component — fetches data, no JS sent to client
export default async function BlogPage() {
const posts = await getPosts(); // direct DB call, no API needed
return <PostList posts={posts} />;
}
// ✅ Client Component — only where interactivity is needed
'use client'
export function LikeButton({ postId }: { postId: string }) {
const [liked, setLiked] = useState(false);
return <button onClick={() => setLiked(true)}>...</button>;
}02. loading.tsx is your best friend
Drop a loading.tsx file in any route segment and Next.js automatically wraps your page in a Suspense boundary. Instant streaming skeleton UI with zero configuration. I use this on every data-heavy page.
Route segment files: page.tsx → layout.tsx → loading.tsx → error.tsx → not-found.tsx. Learn all five and the App Router will finally feel intuitive.
03. Parallel routes for modals that work like real URLs
Parallel routes (@folder convention) let you render two pages simultaneously in the same layout. The killer use case: modals with real URLs, back-button support, and shareable links — without any extra state management.
The App Router rewards you for thinking in segments, not pages. Once that mental model clicks, everything else follows naturally.