Home
NextJS
Next.js: Building API Routes
December 10, 2025
2 min

Table Of Contents

01
1. Traditional Backend vs Next.js API Routes
02
2. Creating Your First API Route
03
3. Creating REST Endpoints (GET, POST, PUT, DELETE)
04
4. Dynamic API Routes (PUT & DELETE)
05
5. Using Your API on the Frontend
06
6. Why Next.js API Routes Are So Powerful
07
7. Final Thoughts

So far, we’ve explored components, routing, layouts, and data fetching in Next.js. Now it’s time to jump into something equally powerful: API Routes.

If you’re coming from a backend background — Express, Node.js, or fastify — you know how much setup is normally involved before you even see “Hello World.” Next.js simplifies all of that, making backend work ridiculously easy.

In this article, you’ll learn:

  • What API Routes are
  • How to create GET, POST, PUT, and DELETE endpoints
  • How dynamic API routes work
  • How to use your API inside the UI
  • Why Next.js API Routes are so powerful

Let’s build your first backend inside a Next.js project.


1. Traditional Backend vs Next.js API Routes

In a typical Node.js backend, you would:

  • Initialize a project
  • Install Express
  • Configure middleware
  • Open a port
  • Manage and deploy the server

Even for a simple “Hello World,” it’s quite a bit of setup.

But in Next.js?

✔ No server setup ✔ No Express ✔ No deployment configuration ✔ No port management

Instead, you just create a file, export a function, and you’re done.


2. Creating Your First API Route

To create an API route in Next.js:

  1. Make a folder inside app/
  2. Add a file named route.ts
  3. Export a named function for the HTTP verb

Example:

app/
└── hello/
└── route.ts

Inside route.ts:

export async function GET() {
return Response.json({ message: "Hello world from backend" });
}

That’s it. Visit this URL in your browser:

http://localhost:3000/hello

You’ll see the JSON response immediately.

This is your fully functional backend — but running inside your Next.js project.


3. Creating REST Endpoints (GET, POST, PUT, DELETE)

Let’s build something a bit more realistic: a “Books API.”

Step 1: Create an API folder

app/
└── api/
├── books/
│ └── route.ts (GET + POST)
└── ...

Step 2: Create a fake in-memory database

Inside api:

app/
└── api/
├── books/
│ ├── database.ts
│ └── route.ts

database.ts:

export let books = [
{ id: 1, title: "Book One" },
{ id: 2, title: "Book Two" },
];

Step 3: Implement GET and POST

route.ts:

import { books } from "./database";
export async function GET() {
return Response.json(books);
}
export async function POST(req: Request) {
const body = await req.json();
const newBook = { id: Date.now(), ...body };
books.push(newBook);
return Response.json(newBook, { status: 201 });
}

This gives you:

  • GET /api/books — list all books
  • POST /api/books — create a new book

4. Dynamic API Routes (PUT & DELETE)

Just like file-based UI routing, API Routes also support dynamic segments.

Folder structure:

app/
└── api/
└── books/
├── [id]/
│ └── route.ts
├── route.ts (GET + POST)
└── database.ts

Inside [id]/route.ts:

import { books } from "../database";
export async function PUT(req: Request, { params }: { params: { id: string } }) {
const id = Number(params.id);
const body = await req.json();
const index = books.findIndex((b) => b.id === id);
if (index === -1) return Response.json({ error: "Not found" }, { status: 404 });
books[index] = { ...books[index], ...body };
return Response.json(books[index]);
}
export async function DELETE(_: Request, { params }: { params: { id: string } }) {
const id = Number(params.id);
const updated = books.filter((b) => b.id !== id);
return Response.json(updated);
}

Now you have:

  • PUT /api/books/:id — update a book
  • DELETE /api/books/:id — remove a book

5. Using Your API on the Frontend

Using your new API inside pages or components is easy — just fetch like normal.

Example (client component):

"use client";
import { useEffect, useState } from "react";
export default function BooksPage() {
const [books, setBooks] = useState([]);
useEffect(() => {
async function loadBooks() {
const res = await fetch("/api/books");
const data = await res.json();
setBooks(data);
}
loadBooks();
}, []);
return (
<div>
{books.map(book => (
<p key={book.id}>{book.title}</p>
))}
</div>
);
}

Visit:

http://localhost:3000/books

You’ll see your books rendered — coming from your backend API.


6. Why Next.js API Routes Are So Powerful

✔ Zero server setup

Next.js handles the infra.

✔ Serverless by default

Endpoints scale automatically.

✔ Familiar routing

Same logic as UI routing.

✔ Easy local development

Everything runs on the same dev server.

✔ Tight frontend-backend integration

Fetch directly from UI components or Server Components.

✔ Built for modern React

Works seamlessly with React Server Components and Next.js 16 features.


7. Final Thoughts

API Routes in Next.js remove almost all the friction of building backend functionality. No extra setup, no servers to maintain, no routing libraries — just simple files that behave like endpoints.

You learned how to:

✔ Create basic API routes ✔ Build CRUD endpoints ✔ Use dynamic routes ✔ Fetch from the frontend ✔ Combine backend and frontend in one unified app

This ability to build both frontend and backend in the same framework is one of the reasons Next.js has become the industry standard for full-stack React development.

In the next lesson, we’ll integrate APIs with real-world features and explore authentication, forms, and server actions.



Tags

#tailwindcss

Share

Related Posts

Crash Course
Next.js: Build Adapters API
December 13, 2025
2 min
© 2025, All Rights Reserved.
Powered By

Social Media

githublinkedinyoutube