nextjs
Next.js 16 App Router patterns and best practices for this project
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Menu
Next.js 16 App Router patterns and best practices for this project
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Baseado na classificação ocupacional SOC
| name | nextjs |
| description | Next.js 16 App Router patterns and best practices for this project |
This project uses Next.js 16.1.4 with the App Router, TypeScript, and Tailwind CSS. Next.js 16 brings significant performance improvements with Turbopack as the default bundler and built-in React Compiler support.
Detected Version: Next.js 16.1.4 Router: App Router (default) Language: TypeScript 5.x Styling: Tailwind CSS 4.x Node.js: 20.9+ required
Key Files:
next.config.ts - Next.js configuration (TypeScript)src/app/layout.tsx - Root layout with metadatasrc/app/page.tsx - Home pagesrc/app/globals.css - Global stylestsconfig.json - TypeScript configuration with Next.js pluginsrc/app/
├── layout.tsx # Root layout (required)
├── page.tsx # Home route (/)
├── globals.css # Global styles
├── favicon.ico # Site favicon
└── tasks/ # Example nested route
└── page.tsx # /tasks route
| File | Purpose | Required |
|---|---|---|
layout.tsx | Shared UI for route segment | Yes (root) |
page.tsx | Route UI, makes route publicly accessible | Yes |
loading.tsx | Loading UI with Suspense | No |
error.tsx | Error UI boundary | No |
not-found.tsx | 404 UI | No |
By default, all components in the App Router are Server Components:
// src/app/page.tsx (Server Component by default)
export default function Home() {
// Runs on server only
// Can directly access backend resources
// Cannot use hooks or event handlers
return <div>Server-rendered content</div>;
}
Benefits:
Use 'use client' directive when you need:
useState, useEffect, etc.)onClick, onChange, etc.)'use client'; // Must be at the top of the file
import { useState } from 'react';
export default function TaskInput() {
const [value, setValue] = useState('');
return (
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
}
// src/app/page.tsx (Server Component)
import TaskList from '@/components/TaskList'; // Client component
export default function Home() {
// Server logic here
return (
<main>
<h1>Task Manager</h1>
<TaskList /> {/* Client interactivity isolated here */}
</main>
);
}
Rule: Keep Server Components as far up the tree as possible, only use Client Components where interactivity is needed.
// src/app/layout.tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Task Manager',
description: 'A simple task management app',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
Dynamic Metadata:
// src/app/tasks/[id]/page.tsx
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const task = await getTask(params.id);
return { title: task.description };
}
src/
├── app/ # App Router pages
│ ├── layout.tsx
│ ├── page.tsx
│ └── globals.css
├── components/ # React components
│ ├── ui/ # Generic UI components
│ ├── layout/ # Layout components
│ └── features/ # Feature-specific components
└── lib/ # Utilities and types
├── types.ts
└── utils.ts
Best Practice: Use @/ import alias (configured in tsconfig.json):
import { Task } from '@/lib/types';
import TaskInput from '@/components/TaskInput';
Next.js 16 includes automatic font optimization with next/font:
// src/app/layout.tsx
import { Geist, Geist_Mono } from 'next/font/google';
const geistSans = Geist({
variable: '--font-geist-sans',
subsets: ['latin'],
});
const geistMono = Geist_Mono({
variable: '--font-geist-mono',
subsets: ['latin'],
});
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable}`}>
{children}
</body>
</html>
);
}
import Image from 'next/image';
<Image
src="/task-icon.png"
alt="Task icon"
width={24}
height={24}
priority // For above-the-fold images
/>
// Global styles in src/app/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
// Component-level Tailwind classes
<div className="flex min-h-screen items-center justify-center bg-zinc-50">
<main className="max-w-3xl w-full px-4">
{/* Content */}
</main>
</div>
Turbopack is now the default bundler in Next.js 16:
Enable filesystem caching for even faster rebuilds:
// next.config.ts
export default {
experimental: {
turbopackFileSystemCacheForDev: true,
},
};
React Compiler is stable in Next.js 16:
useMemo, useCallback// No need for useMemo anymore - React Compiler handles it
const filteredTasks = tasks.filter(task => {
if (filter === 'active') return !task.completed;
if (filter === 'completed') return task.completed;
return true;
});
// Async components (Server Components)
export default async function TasksPage() {
const tasks = await fetchTasks(); // Direct async/await
return <TaskList tasks={tasks} />;
}
Before deploying:
npm run build to check for build errorsstrict: true in tsconfig.json)npm run build# Development server (Turbopack)
npm run dev
# Production build
npm run build
# Start production server
npm run start
# Linting
npm run lint
'use client';
export default function BadComponent() {
const data = await fetch('/api/tasks'); // ❌ async/await in Client Component
return <div>{data}</div>;
}
// Server Component
async function TasksPage() {
const tasks = await fetchTasks(); // ✅ Server-side data fetching
return <TaskList tasks={tasks} />; // Pass to Client Component
}
// Client Component
'use client';
function TaskList({ tasks }: { tasks: Task[] }) {
const [filter, setFilter] = useState('all'); // ✅ Client-side state
// ...
}
'use client'; // ❌ Unnecessary if no interactivity
export default function StaticContent() {
return <div>Just static content</div>;
}
// No 'use client' needed - Server Component by default
export default function StaticContent() {
return <div>Static content</div>; // ✅ Zero JS sent to client
}
// Server Component
import ClientComponent from './ClientComponent'; // Client Component
export default function Page() {
// ❌ Passing non-serializable data to Client Component
return <ClientComponent callback={() => console.log('test')} />;
}
// Server Component
export default function Page() {
// ✅ Pass serializable data only
return <ClientComponent data={{ id: 1, name: 'Task' }} />;
}