Introduction
Next.js is not just a frontend framework; it's a full-stack solution. With API Routes, you can build your backend endpoints directly within your Next.js project, eliminating the need for a separate server. This powerful feature allows you to handle form submissions, fetch data from databases, manage authentication, and more, all within a unified codebase. This lesson will teach you how to create, structure, and utilize API Routes, allowing your Next.js application to perform server-side logic and interact with external services securely and efficiently.
Key Concepts
What are API Routes?
-
API Routes are serverless functions (or Node.js functions in a traditional server environment) that live within the
pages/apidirectory. -
Any file inside
pages/apiis treated as an API endpoint instead of a page. -
They are ideal for creating a backend for your Next.js frontend, handling database operations, external API calls, and authentication.
-
They provide a full Node.js environment, allowing you to use any Node.js package.
Basic API Route Structure
-
Each API Route file exports a default
handlerfunction. -
This handler receives
req(request) andres(response) objects, similar to Express.js. -
You can differentiate logic based on HTTP methods (
req.method). -
Dynamic API routes can be created using
[param].jswithinpages/api.
Example HTTP Methods:
javascript
export default function handler(req, res) {
if (req.method === 'POST') {
// Process a POST request
res.status(200).json({ message: 'POST request received' });
} else if (req.method === 'GET') {
// Handle a GET request
res.status(200).json({ name: 'API Route' });
} else {
// Method Not Allowed
res.setHeader('Allow', ['GET', 'POST']);
res.status(405).end(Method ${req.method} Not Allowed);
}
}
Advantages of API Routes
-
Full-Stack Simplicity: Build frontend and backend in one repository.
-
Zero Configuration: Automatically configured by Next.js.
-
Serverless Compatibility: Easily deployable to serverless platforms like Vercel.
-
Security: Server-side code is never exposed to the client, allowing secure handling of sensitive data (e.g., API keys).
Code Example: Simple API Route and Client-Side Usage
First, create an API route to fetch a list of users.
javascript
// pages/api/users.js
export default async function handler(req, res) {
if (req.method === 'GET') {
try {
const apiRes = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await apiRes.json();
res.status(200).json(users);
} catch (error) {
res.status(500).json({ message: 'Failed to fetch users', error: error.message });
}
} else {
res.setHeader('Allow', ['GET']);
res.status(405).end(Method ${req.method} Not Allowed);
}
}
Now, use this API route from a client-side component:
jsx // pages/client-users.js import { useState, useEffect } from 'react'; import Layout from '../components/Layout';
export default function ClientUsersPage() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null);
useEffect(() => {
async function fetchUsers() {
try {
const res = await fetch('/api/users'); // Call our own API route
if (!res.ok) {
throw new Error(Error: ${res.status});
}
const data = await res.json();
setUsers(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
fetchUsers();
}, []);
if (loading) return <Layout><p>Loading users...</p></Layout>; if (error) return <Layout><p>Error: {error}</p></Layout>;
return ( <Layout> <h1>Users from API Route</h1> <ul> {users.map((user) => ( <li key={user.id}>{user.name} - {user.email}</li> ))} </ul> </Layout> ); }
Key Takeaways
-
API Routes enable you to build backend endpoints directly within your Next.js project.
-
Files in
pages/apibecome API endpoints, exporting anasynchandlerfunction. -
The handler receives
reqandresobjects, allowing logic based on HTTP methods. -
API Routes simplify full-stack development and offer serverless compatibility.
-
They are secure for handling sensitive operations as code runs server-side.