Next.js App Router
Gilt für Next.js 14+ mit dem app/-Verzeichnis und TypeScript.
Dateikonventionen
app/layout.tsx— erforderliches Root-Layout. Muss<html>und<body>enthalten.app/page.tsx— Routeneinstieg. Standardmäßig eine React Server Component (RSC).app/loading.tsx— Streaming-Fallback für das Segment.app/error.tsx— muss eine Client Component sein ('use client'), empfängt{ error, reset }.app/not-found.tsx— 404-UI.app/route.ts— Route Handler (API). ExportiereGET,POSTusw.- Dynamisch:
app/blog/[slug]/page.tsxerhält{ params: { slug: string } }. - Gruppen:
app/(marketing)/about/page.tsx— URL bleibt unbeeinflusst. - Parallel:
app/@modal/page.tsx+layout({ modal }). Abfangend:app/(.)photo/[id]/page.tsx.
Regeln
- Server Components standardmäßig. Füge
'use client'nur hinzu, wenn du Hooks, Ereignisse oder Browser-APIs benötigst. Halte Client-Grenzen klein – verschiebe sie an die Blätter. paramsundsearchParamssind in Next 15 asynchron:await params.- Importiere niemals eine Server Component direkt in eine Client Component, wenn sie serverseitige Funktionen verwendet – übergib sie stattdessen als
children/props. - Verwende
next/linkfür Navigation,next/navigation(useRouter,usePathname) nur in Client Components. Verwenderedirect()/notFound()ausnext/navigationin Server Components. - Ko-lokalisiere:
page.tsx,loading.tsx,error.tsxpro Segment. Gemeinsame UI kommt incomponents/, nicht inapp/, es sei denn, sie ist geroutet.
Muster
// app/blog/[slug]/page.tsx — Next 15 asynchrone params
type Props = { params: Promise<{ slug: string }> };
export default async function BlogPost({ params }: Props) {
const { slug } = await params;
const post = await getPost(slug);
if (!post) notFound();
return <article>{post.title}</article>;
}
export async function generateStaticParams() {
const slugs = await getAllSlugs();
return slugs.map((slug) => ({ slug }));
}
// app/error.tsx — muss eine Client Component sein
'use client';
export default function Error({ error, reset }: { error: Error; reset: () => void }) {
return (
<div>
<h2>Etwas ist schiefgelaufen</h2>
<button onClick={() => reset()}>Erneut versuchen</button>
</div>
);
}
// app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="de">
<body>{children}</body>
</html>
);
}
Checkliste
- Korrekter Dateiname und Segmentplatzierung?
- Client-Direktive nur wo nötig?
-
loading.tsx/error.tsxfür asynchrone Segmente? -
generateStaticParams+generateMetadatawo SEO wichtig ist? - Kein
useRouterausnext/router(Pages-Router-Import)?