- #nextjs
- #app-router
- #server-components
Three Next.js App Router pitfalls that bit me
Migrating to Next.js App Router unlocks Server Components but introduces traps the docs don't always emphasize. Three patterns burned me on my first project:
1. params is now a Promise
In Next.js 15+, route params are async. Forgetting await returns a Promise where you expect an object:
// ❌ Wrong — params is a Promise
export default function Page({ params }) {
return <div>{params.slug}</div>; // [object Promise]
}
// ✅ Right
export default async function Page({ params }) {
const { slug } = await params;
return <div>{slug}</div>;
}2. Hardcoded locale strings break i18n routing
When you build a bilingual site, every internal <Link> needs the locale prefix. href="/products" silently navigates to the default locale; href={\/$/products`}` is correct.
3. The Server/Client boundary is sticky
Mark a component "use client" and ALL its imports become client bundle. Want a server-data prop in a client component? Pass it through children, not as a direct import.
Once you embrace these three patterns, App Router clicks. Until then, prepare for confusing hydration mismatches.