App Router
Recommended instead of pages approach in v13
In /app:
Folders are used to define routes
[]
page.jsfile in that folder makes route segments accessibleCan colocate components, stylesheets, and images
layouts in
layout.tsshow UI that is shared across multiple routes. If multiple layouts apply, they do nested wrappingapp/blog/[slug]/page.tsxfor dynamic slugapp/blog/[...slug]/page.tsxfor catch all slug ie/blog/a/band slug is list
A route group(folder that doesn't affect path) can be created by wrapping a folder's name in parenthesis:
(folderName)
app/page.tsx
export default function Page() {
return <h1>Hello, Home page!</h1>
}app/blog/[slug]/page.tsx
export default function Page({ params }: { params: { slug: string } }) {
return <div>My Post: {params.slug}</div>
}
//optional, prerender the dynamic routes
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
return posts.map((post) => ({
slug: post.slug,
}))
}Linking
Link component recommended and provides prefetching
import Link from 'next/link'
export default function Page() {
return <Link href="/dashboard">Dashboard</Link>
}Programmatically
'use client'
import { useRouter } from 'next/navigation'
export default function Page() {
const router = useRouter()
return (
<button type="button" onClick={() => router.push('/dashboard')}>
Dashboard
</button>
)
}Server components programmatically
import { redirect } from 'next/navigation'
async function fetchTeam(id: string) {
const res = await fetch('https://...')
if (!res.ok) return undefined
return res.json()
}
export default async function Profile({ params }: { params: { id: string } }) {
const team = await fetchTeam(params.id)
if (!team) {
redirect('/login')
}
// ...
}Last updated