# Next.js App Router File Templates This document provides basic templates for the common file types used in a Next.js application with the App Router. These templates follow the current best practices for Next.js 15. ## Page Templates ### Basic Page (`page.tsx`) ```tsx import { Metadata } from 'next' export const metadata: Metadata = { title: 'Page Title', description: 'Page description', } export default function Page() { return (

Page Content

{/* Page content goes here */}
) } ``` ### Dynamic Route Page (`[slug]/page.tsx`) ```tsx export async function generateMetadata({ params }) { return { title: `Page for ${params.slug}`, description: `Description for ${params.slug}`, } } export default function DynamicPage({ params }) { const { slug } = params return (

Dynamic Page: {slug}

{/* Dynamic page content goes here */}
) } ``` ## Layout Templates ### Root Layout (`layout.tsx`) ```tsx import { Metadata } from 'next' import './globals.css' export const metadata: Metadata = { title: { template: '%s | Site Name', default: 'Site Name', }, description: 'Site description', } export default function RootLayout({ children }) { return (
{/* Header content */}
{children}
) } ``` ### Nested Layout (`(dashboard)/layout.tsx`) ```tsx export default function DashboardLayout({ children }) { return (
{children}
) } ``` ### Auth Layout with Session Check (`(authenticated)/layout.tsx`) ```tsx import { redirect } from 'next/navigation' // This is a Server Component export default async function AuthLayout({ children }) { const session = await getSession() // Replace with your auth solution if (!session) { redirect('/login') } return <>{children} } ``` ## Error Handling Templates ### Not Found (`not-found.tsx`) ```tsx import Link from 'next/link' export const metadata = { title: 'Not Found', description: 'Page not found', } export default function NotFound() { return (

404 - Page Not Found

The page you are looking for does not exist.

Return to Home
) } ``` ### Error Page (`error.tsx`) ```tsx 'use client' // Error components must be Client Components import { useEffect } from 'react' export default function Error({ error, reset }) { useEffect(() => { // Log the error to an error reporting service console.error(error) }, [error]) return (

Something went wrong!

) } ``` ### Global Error (`global-error.tsx`) ```tsx 'use client' export default function GlobalError({ error, reset }) { return (

Something went wrong!

) } ``` ## Loading States ### Loading Component (`loading.tsx`) ```tsx export default function Loading() { return (

Loading...

) } ``` ## Route Handlers ### API Route (`api/route.ts`) ```ts import { NextResponse } from 'next/server' export async function GET(request) { // Handle GET request return NextResponse.json({ message: 'Hello World' }) } export async function POST(request) { // Handle POST request const body = await request.json() return NextResponse.json({ received: body }) } ``` ### Dynamic API Route (`api/[slug]/route.ts`) ```ts import { NextResponse } from 'next/server' export async function GET(request, { params }) { const { slug } = params return NextResponse.json({ slug }) } ``` ## Middleware ### Middleware (`middleware.ts`) Place this file in the root of your project: ```ts import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' // This function runs before requests are completed export function middleware(request: NextRequest) { const currentUrl = request.nextUrl.clone() // Example: check if user is authenticated const isAuthenticated = checkAuth(request) if (!isAuthenticated && currentUrl.pathname.startsWith('/protected')) { return NextResponse.redirect(new URL('/login', request.url)) } return NextResponse.next() } // Configure matcher for paths that should trigger middleware export const config = { matcher: ['/protected/:path*', '/api/:path*'], } // Example auth check function function checkAuth(request) { // Implement your auth check logic here return !!request.cookies.get('auth-token') } ``` ## Utilities - Server Actions ### Form Actions (`actions.ts`) ```ts 'use server' export async function submitForm(formData: FormData) { // Validate data const name = formData.get('name') const email = formData.get('email') // Process data try { // Save to database or send to API await saveToDatabase({ name, email }) return { success: true } } catch (error) { return { success: false, error: error.message } } } async function saveToDatabase(data) { // Implementation for database interaction } ``` ## Server Component with Data Fetching ### Data Fetching in Server Component (`dashboard/page.tsx`) ```tsx // This is a Server Component export default async function DashboardPage() { // This data fetching happens on the server const data = await fetchDashboardData() return (

Dashboard

{data.map(item => (

{item.title}

{item.value}

))}
) } async function fetchDashboardData() { // API or database call const res = await fetch('https://api.example.com/dashboard-data', { cache: 'no-store' // Don't cache this data }) if (!res.ok) { throw new Error('Failed to fetch dashboard data') } return res.json() } ``` ## Client Component with Hooks ### Interactive Client Component (`components/Counter.tsx`) ```tsx 'use client' // Mark as Client Component import { useState } from 'react' export default function Counter() { const [count, setCount] = useState(0) return (

Count: {count}

) } ``` ## Parallel Routes ### Parallel Route Layout (`@dashboard/page.tsx` and `@profile/page.tsx`) In your directory structure: ``` app/ layout.tsx [user]/ layout.tsx page.tsx @dashboard/ page.tsx @profile/ page.tsx ``` In `[user]/layout.tsx`: ```tsx export default function UserLayout({ children, dashboard, profile }) { return (
{/* Sidebar navigation */}
{children}
{dashboard}
{profile}
) } ``` ## Route Interception ### Photo Modal Example (`./(.)photos/[id]/page.tsx`) The directory structure might look like: ``` app/ photos/ page.tsx [id]/ page.tsx (.)photos/ [id]/ page.tsx // This intercepts /photos/[id] ``` In `./(.)photos/[id]/page.tsx`: ```tsx export default function PhotoModal({ params }) { const { id } = params // Fetch photo data based on id return (

Photo {id}

{`Photo
) } ``` ## References - [Official Next.js Documentation](https://nextjs.org/docs/app) - [Pages and Layouts](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts) - [Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) - [Error Handling](https://nextjs.org/docs/app/building-your-application/routing/error-handling) - [Loading UI and Streaming](https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming) - [Metadata API](https://nextjs.org/docs/app/building-your-application/optimizing/metadata) - [Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions) - [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware)