Next.js is a powerful React framework that provides a robust set of features for building modern web applications. It offers server-side rendering, static site generation, API routes, and many other capabilities out of the box.
You can create a new Next.js project using any of these commands:
# Using create-next-app (recommended)
npx create-next-app@latest my-next-app
# With TypeScript
npx create-next-app@latest my-next-app --typescript
# Using pnpm
pnpm create next-app my-next-app
# Using Yarn
yarn create next-app my-next-app
A typical Next.js project structure looks like this:
my-next-app/
├── app/ # App Router (Next.js 13+)
│ ├── layout.tsx
│ ├── page.tsx
│ └── [...routes]
├── public/ # Static files
├── components/ # React components
├── lib/ # Utility functions
├── styles/ # CSS files
├── next.config.js # Next.js configuration
└── package.json # Project dependencies
Next.js 13+ introduces the App Router, a new paradigm in file-system based routing:
// app/page.tsx - Home page
export default function Home() {
return <h1>Welcome to Next.js!</h1>
}
// app/blog/[slug]/page.tsx - Dynamic route
export default function BlogPost({ params }: { params: { slug: string } }) {
return <h1>Blog Post: {params.slug}</h1>
}
Next.js provides multiple ways to fetch data:
// Server Components (Next.js 13+)
async function BlogPosts() {
const posts = await fetch('https://api.example.com/posts')
const data = await posts.json()
return (
<ul>
{data.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
// Client Components
'use client'
import { useEffect, useState } from 'react'
function ClientComponent() {
const [data, setData] = useState(null)
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(setData)
}, [])
return // ...
}
Create API endpoints easily in the app/api directory:
// app/api/hello/route.ts
import { NextResponse } from 'next/server'
export async function GET() {
return NextResponse.json({ message: 'Hello, Next.js!' })
}
Next.js supports various styling approaches:
// CSS Modules
import styles from './Button.module.css'
export default function Button() {
return <button className={styles.button}>Click me</button>
}
// Tailwind CSS
export default function Card() {
return (
<div className="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md">
<h2 className="text-xl font-medium">Card Title</h2>
</div>
)
}
Use Server Components by Default
Optimize Images
import Image from 'next/image'
export default function Profile() {
return (
<Image
src="/profile.jpg"
alt="Profile"
width={500}
height={300}
priority
/>
)
}
Implement Loading States
// app/loading.tsx
export default function Loading() {
return <div>Loading...</div>
}
Error Handling
// app/error.tsx
'use client'
export default function Error({
error,
reset,
}: {
error: Error
reset: () => void
}) {
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</div>
)
}
Create a .env.local file for environment variables:
DATABASE_URL="your-database-url"
API_KEY="your-api-key"
Access them in your code:
const apiKey = process.env.API_KEY
Implement Metadata
// app/layout.tsx
export const metadata = {
title: 'My Next.js App',
description: 'Built with Next.js',
}
Use Dynamic Imports
import dynamic from 'next/dynamic'
const DynamicComponent = dynamic(() => import('../components/Heavy'))
Next.js applications can be deployed to various platforms:
Vercel (Recommended)
vercel
Custom Server
npm run build
npm run start
Next.js provides a powerful and flexible framework for building modern web applications. Its extensive features, excellent developer experience, and strong community support make it an excellent choice for both small and large-scale projects. Start with the basics and gradually explore its advanced features as your application grows.