Next.js
The React framework for production
⚡ What is Next.js?
Next.js is a powerful React framework that provides server-side rendering, static site generation, and API routes out of the box. It simplifies building production-ready React applications with built-in optimization and routing.
// Simple Next.js page
export default function Home() {
return <h1>Welcome to Next.js!</h1>;
}
Key Next.js Features
File-based Routing
Pages automatically become routes
// pages/about.js → /about
export default function About() {}
SSR & SSG
Server-side and static rendering
export async function getServerSideProps() {
return { props: {} };
}
API Routes
Build backend APIs in Next.js
// pages/api/hello.js
export default function handler(req, res) {
res.json({ message: 'Hello' });
}
Image Optimization
Automatic image optimization
import Image from 'next/image';
<Image src="/pic.jpg" width={500} height={300} />
🔹 Creating a Next.js App
Create a new Next.js application using the official create-next-app tool. This sets up everything you need with best practices and optimal configuration.
# Create new Next.js app
npx create-next-app@latest my-app
# Navigate to project
cd my-app
# Start development server
npm run dev
Your app will be running at http://localhost:3000
🔹 File-based Routing
Next.js uses the file system for routing. Create files in the pages directory and they automatically become routes without any configuration needed.
// pages/index.js → /
export default function Home() {
return <h1>Home Page</h1>;
}
// pages/about.js → /about
export default function About() {
return <h1>About Page</h1>;
}
// pages/blog/[slug].js → /blog/:slug
export default function BlogPost({ slug }) {
return <h1>Post: {slug}</h1>;
}
Folder Structure:
- pages/index.js → /
- pages/about.js → /about
- pages/blog/index.js → /blog
- pages/blog/[id].js → /blog/123
🔹 Navigation with Link
Use the Link component for client-side navigation between pages. It prefetches pages in the background for instant navigation without full page reloads.
import Link from 'next/link';
export default function Navigation() {
return (
<nav>
<Link href="/">Home</Link>
<Link href="/about">About</Link>
<Link href="/blog/my-post">Blog Post</Link>
</nav>
);
}
// Programmatic navigation
import { useRouter } from 'next/router';
function MyComponent() {
const router = useRouter();
const handleClick = () => {
router.push('/dashboard');
};
return <button onClick={handleClick}>Go to Dashboard</button>;
}
🔹 Dynamic Routes
Create dynamic routes using square brackets in file names. Access route parameters using the useRouter hook to build flexible, data-driven pages.
// pages/posts/[id].js
import { useRouter } from 'next/router';
export default function Post() {
const router = useRouter();
const { id } = router.query;
return <h1>Post ID: {id}</h1>;
}
// pages/blog/[...slug].js - Catch all routes
// Matches /blog/a, /blog/a/b, /blog/a/b/c
export default function Blog() {
const router = useRouter();
const { slug } = router.query; // slug is an array
return <div>Slug: {slug?.join('/')}</div>;
}
🔹 Server-Side Rendering (SSR)
Fetch data on each request using getServerSideProps. Perfect for dynamic content that changes frequently or requires authentication before rendering the page.
// pages/users.js
export default function Users({ users }) {
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
// Runs on every request
export async function getServerSideProps() {
const res = await fetch('https://api.example.com/users');
const users = await res.json();
return {
props: { users }
};
}
🔹 Static Site Generation (SSG)
Pre-render pages at build time using getStaticProps. Ideal for content that doesn't change often, providing the fastest possible page loads for users.
// pages/blog.js
export default function Blog({ posts }) {
return (
<div>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
</article>
))}
</div>
);
}
// Runs at build time
export async function getStaticProps() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
return {
props: { posts },
revalidate: 60 // Revalidate every 60 seconds
};
}
🔹 API Routes
Build backend APIs directly in Next.js without a separate server. API routes run on the server and can handle database operations, authentication, and external API calls.
// pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ message: 'Hello World' });
}
// pages/api/users/[id].js
export default function handler(req, res) {
const { id } = req.query;
if (req.method === 'GET') {
res.json({ id, name: 'John Doe' });
} else if (req.method === 'POST') {
// Handle POST request
res.json({ success: true });
}
}
// Calling API from component
async function fetchData() {
const res = await fetch('/api/hello');
const data = await res.json();
console.log(data);
}
🔹 Image Optimization
Use the Next.js Image component for automatic image optimization. It lazy loads images, serves modern formats, and resizes images for different screen sizes automatically.
import Image from 'next/image';
export default function Gallery() {
return (
<div>
{/* Local image */}
<Image
src="/profile.jpg"
alt="Profile"
width={500}
height={500}
/>
{/* External image */}
<Image
src="https://example.com/photo.jpg"
alt="Photo"
width={800}
height={600}
priority // Load immediately
/>
{/* Responsive image */}
<Image
src="/banner.jpg"
alt="Banner"
fill
style={{ objectFit: 'cover' }}
/>
</div>
);
}
🔹 Custom App Component
Customize the default App component to add global layouts, styles, or state management. This component wraps all pages and persists between page navigations.
// pages/_app.js
import '../styles/globals.css';
export default function MyApp({ Component, pageProps }) {
return (
<div>
<header>My Site Header</header>
<Component {...pageProps} />
<footer>My Site Footer</footer>
</div>
);
}
// With state management
import { RecoilRoot } from 'recoil';
export default function MyApp({ Component, pageProps }) {
return (
<RecoilRoot>
<Component {...pageProps} />
</RecoilRoot>
);
}
🔹 Environment Variables
Use environment variables for API keys and configuration. Next.js automatically loads variables from .env files and makes them available in your application.
# .env.local
DATABASE_URL=your_database_url
NEXT_PUBLIC_API_URL=https://api.example.com
// Server-side only (API routes, getServerSideProps)
const dbUrl = process.env.DATABASE_URL;
// Client-side accessible (must start with NEXT_PUBLIC_)
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
// Usage in component
export default function MyComponent() {
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
return <div>API: {apiUrl}</div>;
}