Next.js Server-side API: A Comprehensive Guide
NextJS
APIRouting
ServerSideRendering
WebDevelopment
ServerSideAPI
Next.js is a powerful React framework that enables server-side rendering (SSR), static site generation (SSG), and API routes. One of its standout features is the ability to create server-side APIs within the project itself.
Mastering Next.js Server-side API: Beginner to Advanced Guide
Next.js is a powerful React framework that simplifies building full-stack applications. One of its key features is the ability to create server-side APIs using the built-in API routes. In this guide, we'll explore Next.js API routes in-depth
Folder Structure
Explanation of Each Folder/File
/app/api/getUsers/route.ts
→ Handles GET requests (fetch users)/app/api/createUser/route.ts
→ Handles POST requests (add a new user)/app/api/updateUser/route.ts
→ Handles PUT requests (update user details)/app/api/deleteUser/route.ts
→ Handles DELETE requests (remove user)/app/users/page.tsx
→ Client-side page to display, create, update, and delete users/utils/apiHandler.ts
→ Client-side API call functions (fetch, create, update, delete users)
1. Create Separate API Routes in Next.js (App Router)
GET API (Fetch Users)
- app/api/getUsers/route.ts
import { NextResponse } from "next/server";
let users = [
{ id: 1, name: "John Doe", email: "john@example.com" },
{ id: 2, name: "Jane Doe", email: "jane@example.com" },
];
export async function handler() {
return NextResponse.json({ success: true, users }, { status: 200 });
}
POST API (Create a New User)
app/api/createUser/route.ts
import { NextRequest, NextResponse } from "next/server";
export async function handler(req: NextRequest) {
try {
const { name, email } = await req.json();
if (!name || !email) {
return NextResponse.json({ success: false, message: "Name and email are required" }, { status: 400 });
}
const newUser = { id: Date.now(), name, email };
return NextResponse.json({ success: true, user: newUser }, { status: 201 });
} catch (error) {
return NextResponse.json({ success: false, message: "Server error" }, { status: 500 });
}
}
PUT API (Update a User)
app/api/updateUser/route.ts
import { NextRequest, NextResponse } from "next/server";
export async function handler(req: NextRequest) {
try {
const { id, name, email } = await req.json();
if (!id || !name || !email) {
return NextResponse.json({ success: false, message: "ID, Name, and Email are required" }, { status: 400 });
}
return NextResponse.json({ success: true, message: "User updated successfully" }, { status: 200 });
} catch (error) {
return NextResponse.json({ success: false, message: "Server error" }, { status: 500 });
}
}
DELETE API (Delete a User)
app/api/deleteUser/route.ts
import { NextRequest, NextResponse } from "next/server";
export async function handler(req: NextRequest) {
try {
const { searchParams } = new URL(req.url);
const id = searchParams.get("id");
if (!id) return NextResponse.json({ success: false, message: "User ID is required" }, { status: 400 });
return NextResponse.json({ success: true, message: "User deleted successfully" }, { status: 200 });
} catch (error) {
return NextResponse.json({ success: false, message: "Server error" }, { status: 500 });
}
}
2. Create API Call Functions (Client-Side)
export const API_BASE_URL = "/api";
// GET: Fetch all users
export const fetchUsers = async () => {
const res = await fetch(`${API_BASE_URL}/getUsers`);
return res.json();
};
// POST: Add a new user
export const createUser = async (name: string, email: string) => {
const res = await fetch(`${API_BASE_URL}/createUser`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, email }),
});
return res.json();
};
// PUT: Update a user
export const updateUser = async (id: number, name: string, email: string) => {
const res = await fetch(`${API_BASE_URL}/updateUser`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ id, name, email }),
});
return res.json();
};
// DELETE: Remove a user
export const deleteUser = async (id: number) => {
const res = await fetch(`${API_BASE_URL}/deleteUser?id=${id}`, { method: "DELETE" });
return res.json();
};
3. Use APIs in the Next.js Page (Client-Side)
"use client";
import { useState, useEffect } from "react";
import { fetchUsers, createUser, updateUser, deleteUser } from "@/utils/apiHandler";
export default function UsersPage() {
const [users, setUsers] = useState([]);
const [name, setName] = useState("");
const [email, setEmail] = useState("");
// Load users when the page loads
useEffect(() => {
fetchUsers().then((data) => setUsers(data.users));
}, []);
// Add a new user
const handleAddUser = async () => {
const data = await createUser(name, email);
if (data.success) setUsers([...users, data.user]);
setName("");
setEmail("");
};
// Update user
const handleUpdateUser = async (id: number) => {
const newName = prompt("New Name:", "");
const newEmail = prompt("New Email:", "");
if (!newName || !newEmail) return;
const data = await updateUser(id, newName, newEmail);
if (data.success) {
setUsers(users.map((user) => (user.id === id ? { ...user, name: newName, email: newEmail } : user)));
}
};
// Delete user
const handleDeleteUser = async (id: number) => {
if (confirm("Delete this user?")) {
const data = await deleteUser(id);
if (data.success) setUsers(users.filter((user) => user.id !== id));
}
};
return (
<div className="p-6">
<h1 className="text-2xl font-bold mb-4">Users</h1>
{/* Form to Add User */}
<div className="mb-4">
<input type="text" placeholder="Name" value={name} onChange={(e) => setName(e.target.value)} className="border p-2 mr-2" />
<input type="email" placeholder="Email" value={email} onChange={(e) => setEmail(e.target.value)} className="border p-2 mr-2" />
<button onClick={handleAddUser} className="bg-blue-500 text-white px-4 py-2">Add</button>
</div>
{/* User List */}
<ul>
{users.map((user) => (
<li key={user.id} className="flex justify-between items-center border-b p-2">
{user.name} - {user.email}
<div>
<button onClick={() => handleUpdateUser(user.id)} className="bg-yellow-500 text-white px-2 py-1 mr-2">Edit</button>
<button onClick={() => handleDeleteUser(user.id)} className="bg-red-500 text-white px-2 py-1">Delete</button>
</div>
</li>
))}
</ul>
</div>
);
}
🔥 Done!
✅ API routes: getUsers
, createUser
, updateUser
, deleteUser
✅ Uses proper status codes and error handling
✅ Client-side API calls are easy to manage
✅ User-friendly UI with Tailwind