Next.js (App Router)
Before continuing, ensure your workstation has been set up with the Core Components, as well as components specific to the language ecosystem you're working in: [JavaScript] [Java] [.Net] [Python] [Rust]
This document serves to outline best practices involved in using Next.js with the App Router.
Project Structure
The App Router follows a file-based routing structure, so it is essential to have a clear, concise folder structure. An example of a project structure is listed below.
app/
├── layout.tsx # Shared layout (header, footer, etc.)
├── page.tsx # Root route
├── dashboard/
│ ├── layout.tsx
│ └── page.tsx
├── settings/
│ └── page.tsx
Layouts and Pages
Page
A page is UI that is rendered to a specific route. For example,
export default function Page() {
return <h1>Hello Next.js!</h1>
}
Layout
A layout is UI that is shared between multiple pages. On navigation, layouts preserve state, remain interactive, and do not rerender.
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
{/* Layout UI */}
{/* Place children where you want to render a page or nested layout */}
<main>{children}</main>
</body>
</html>
)
}
Nested Routes
Nested routes are composed of multiple urls such as /blog/[slug]
. To create nested routes, you can nest folders inside each other.
Dynamic Routes
Useful when you don't know the exact segment names ahead of time and want to create routes from dynamic data, you can use Dynamic Segments that are filled in at request time or prerendered at build time.
A Dynamic Segment can be created by wrapping a folder's name in square brackets: [folderName]. For example, [id] or [slug]. For example,
// app/blog/[slug]/page.tsx
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
return <div>My Post: {slug}</div>
}
Images
Next.js has many built-in capabilites for optimizing images. These include:
- Size optimization: Automatically serving correctly sized images for each device, using modern image formats like WebP.
- Visual stability: Preventing layout shift automatically when images are loading.
- Faster page loads: Only loading images when they enter the viewport using native browser lazy loading, with optional blur-up placeholders.
- Asset flexibility: Resizing images on-demand, even images stored on remote servers.
Using these image optimizations is as simple as,
import Image from 'next/image'
export default function Page() {
return <Image src="" alt="" />
}
If you are including images from remote urls, you must define a list of supported URL patterns in next.config.ts
. For example,
import { NextConfig } from 'next'
const config: NextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 's3.amazonaws.com',
port: '',
pathname: '/my-bucket/**',
search: '',
},
],
},
}
export default config
Server and Client Components
- Server Components (default): Great for data-fetching and performance
- Client Components ('use client'): Use when needed for interactivity (e.g., state, effects)
To use a client component (server component is default) use the "use client"
directive at the top of the file, above imports.
Fetching Data
Server Components
In Server Components, you have the following options to fetch data:
- The
fetch
API - An ORM or Database
Client Components
In Client Components, there are two ways to fetch data in Client Components, using:
- React's use hook
- A community library like SWR or React Query
SEO (Search Engine Optimization)
Metadata
The easiest way to define metadata for a page in Next.js is using the static metadata object. For example,
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'My Blog',
description: '...',
}
export default function Page() {}
Additionally, the following special files are available for metadata:
- favicon.ico, apple-icon.jpg, and icon.jpg
- opengraph-image.jpg and twitter-image.jpg
- robots.txt
- sitemap.xml You can use these for static metadata, or you can programmatically generate these files with code.
See the official documentation for more ways to generate metadata, specifically for dynamic data.