Best practices and guidelines for working with Next.js 16 App Router
This project uses Next.js 16.1.1 with the App Router. Key conventions:
app/ directory for all routes and layoutsapp/ directorylayout.tsx files for shared UI across routespage.tsx files to create route segments'use client''use client') only when needed for:
// Server Component (default)
export default function ServerComponent() {
return <div>Server Component</div>;
}
// Client Component
'use client';
import { useState } from 'react';
export default function ClientComponent() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
[param] folders for dynamic segments (e.g., app/users/[id]/page.tsx)(folderName) for organization without affecting the URLlayout.tsx in subdirectoriesloading.tsx for route-level loading UIerror.tsx for route-level error handlingnot-found.tsx for custom 404 pagesapp/api/ directory using route.ts filesfetch options (cache, revalidate, etc.)// Server Component data fetching
export default async function Page() {
const data = await fetch('https://api.example.com/data', {
next: { revalidate: 3600 } // Revalidate every hour
});
const json = await data.json();
return <div>{json.title}</div>;
}
next/image: Import from next/image for optimized imageswidth, height, and alt propspriority prop for above-the-fold imagesfill with a container for responsive imagesimport Image from 'next/image';
<Image
src="/image.jpg"
alt="Description"
width={500}
height={300}
priority // for above-the-fold images
/>
metadata export in layout.tsx or page.tsxgenerateMetadata function for dynamic metadataMetadata type from nextimport type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Page Title',
description: 'Page description',
};
app/globals.cssdark: variantparams prop typessearchParams prop types// Typed route params
export default function UserPage({
params,
}: {
params: { id: string };
}) {
return <div>User {params.id}</div>;
}
Performance:
Code Organization:
Error Handling:
error.tsx for error boundariesloading.tsxAPI Routes:
route.ts files in app/api/ directory// app/api/users/route.ts
export async function GET() {
return Response.json({ users: [] });
}
export async function POST(request: Request) {
const body = await request.json();
return Response.json({ created: body });
}
.env.local for local developmentNEXT_PUBLIC_template.tsx for UI that needs to remount on navigation@folder syntax for parallel routes(.)folder syntax for intercepting routesnpm run dev - Start development servernpm run build - Build for productionnpm run start - Start production servernpm run lint - Run ESLint