storieasy-logo

Next.js Server-side API: A Comprehensive Guide

milan

Milan Patel

29 Mar 2025

|

30 min to read

NextJS

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

NextJS folder structure

NextJS folder structure

Explanation of Each Folder/File

  • /app/api/getUsers/route.tsHandles GET requests (fetch users)
  • /app/api/createUser/route.tsHandles POST requests (add a new user)
  • /app/api/updateUser/route.tsHandles PUT requests (update user details)
  • /app/api/deleteUser/route.tsHandles DELETE requests (remove user)
  • /app/users/page.tsxClient-side page to display, create, update, and delete users
  • /utils/apiHandler.tsClient-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
1import { NextResponse } from "next/server";
2
3let users = [
4{ id: 1, name: "John Doe", email: "john@example.com" },
5{ id: 2, name: "Jane Doe", email: "jane@example.com" },
6];
7
8export async function handler() {
9return NextResponse.json({ success: true, users }, { status: 200 });
10}

POST API (Create a New User)

  • app/api/createUser/route.ts
1import { NextRequest, NextResponse } from "next/server";
2
3export async function handler(req: NextRequest) {
4try {
5const { name, email } = await req.json();
6if (!name || !email) {
7return NextResponse.json({ success: false, message: "Name and email are required" }, { status: 400 });
8}
9
10const newUser = { id: Date.now(), name, email };
11return NextResponse.json({ success: true, user: newUser }, { status: 201 });
12} catch (error) {
13return NextResponse.json({ success: false, message: "Server error" }, { status: 500 });
14}
15}

PUT API (Update a User)

  • app/api/updateUser/route.ts
1import { NextRequest, NextResponse } from "next/server";
2
3export async function handler(req: NextRequest) {
4try {
5const { id, name, email } = await req.json();
6if (!id || !name || !email) {
7return NextResponse.json({ success: false, message: "ID, Name, and Email are required" }, { status: 400 });
8}
9
10return NextResponse.json({ success: true, message: "User updated successfully" }, { status: 200 });
11} catch (error) {
12return NextResponse.json({ success: false, message: "Server error" }, { status: 500 });
13}
14}

DELETE API (Delete a User)

  • app/api/deleteUser/route.ts
1import { NextRequest, NextResponse } from "next/server";
2
3export async function handler(req: NextRequest) {
4try {
5const { searchParams } = new URL(req.url);
6const id = searchParams.get("id");
7
8if (!id) return NextResponse.json({ success: false, message: "User ID is required" }, { status: 400 });
9
10return NextResponse.json({ success: true, message: "User deleted successfully" }, { status: 200 });
11} catch (error) {
12return NextResponse.json({ success: false, message: "Server error" }, { status: 500 });
13}
14}

2. Create API Call Functions (Client-Side)

1export const API_BASE_URL = "/api";
2
3// GET: Fetch all users
4export const fetchUsers = async () => {
5const res = await fetch(`${API_BASE_URL}/getUsers`);
6return res.json();
7};
8
9//  POST: Add a new user
10export const createUser = async (name: string, email: string) => {
11const res = await fetch(`${API_BASE_URL}/createUser`, {
12method: "POST",
13headers: { "Content-Type": "application/json" },
14body: JSON.stringify({ name, email }),
15});
16return res.json();
17};
18
19//  PUT: Update a user
20export const updateUser = async (id: number, name: string, email: string) => {
21const res = await fetch(`${API_BASE_URL}/updateUser`, {
22method: "PUT",
23headers: { "Content-Type": "application/json" },
24body: JSON.stringify({ id, name, email }),
25});
26return res.json();
27};
28
29//  DELETE: Remove a user
30export const deleteUser = async (id: number) => {
31const res = await fetch(`${API_BASE_URL}/deleteUser?id=${id}`, { method: "DELETE" });
32return res.json();
33};

3. Use APIs in the Next.js Page (Client-Side)

1"use client";
2import { useState, useEffect } from "react";
3import { fetchUsers, createUser, updateUser, deleteUser } from "@/utils/apiHandler";
4
5export default function UsersPage() {
6const [users, setUsers] = useState([]);
7const [name, setName] = useState("");
8const [email, setEmail] = useState("");
9
10//  Load users when the page loads
11useEffect(() => {
12fetchUsers().then((data) => setUsers(data.users));
13}, []);
14
15//  Add a new user
16const handleAddUser = async () => {
17const data = await createUser(name, email);
18if (data.success) setUsers([...users, data.user]);
19setName("");
20setEmail("");
21};
22
23//  Update user
24const handleUpdateUser = async (id: number) => {
25const newName = prompt("New Name:", "");
26const newEmail = prompt("New Email:", "");
27if (!newName || !newEmail) return;
28
29const data = await updateUser(id, newName, newEmail);
30if (data.success) {
31setUsers(users.map((user) => (user.id === id ? { ...user, name: newName, email: newEmail } : user)));
32}
33};
34
35// Delete user
36const handleDeleteUser = async (id: number) => {
37if (confirm("Delete this user?")) {
38const data = await deleteUser(id);
39if (data.success) setUsers(users.filter((user) => user.id !== id));
40}
41};
42
43return (
44<div className="p-6">
45<h1 className="text-2xl font-bold mb-4">Users</h1>
46
47{/* Form to Add User */}
48<div className="mb-4">
49<input type="text" placeholder="Name" value={name} onChange={(e) => setName(e.target.value)} className="border p-2 mr-2" />
50<input type="email" placeholder="Email" value={email} onChange={(e) => setEmail(e.target.value)} className="border p-2 mr-2" />
51<button onClick={handleAddUser} className="bg-blue-500 text-white px-4 py-2">Add</button>
52</div>
53
54{/* User List */}
55<ul>
56{users.map((user) => (
57<li key={user.id} className="flex justify-between items-center border-b p-2">
58{user.name} - {user.email}
59<div>
60<button onClick={() => handleUpdateUser(user.id)} className="bg-yellow-500 text-white px-2 py-1 mr-2">Edit</button>
61<button onClick={() => handleDeleteUser(user.id)} className="bg-red-500 text-white px-2 py-1">Delete</button>
62</div>
63</li>
64))}
65</ul>
66</div>
67);
68}

🔥 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

Newsletter

Subscribe to our newsletter and get our latest updates.

Share with your friends: