#nextjs #api #route-handlers #backend

Day 14 β€” Route Handlers: Your Backend API

🧭 Day 14 β€” Route Handlers: Your Backend API

Zero to Hero β€” Hands-on Next.js Tutorial

We’ve been fetching data inside Components. But what if you need to build a public API for your mobile app? Or handle a webhook from Stripe? You use Route Handlers (formerly API Routes).


🟦 1. route.ts

Instead of page.tsx, you create a route.ts file in your app folder. This file exports functions named after HTTP Verbs: GET, POST, PUT, DELETE.

Example: A Hello World API

src/app/api/hello/route.ts:

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  return NextResponse.json({ message: 'Hello from Next.js!' });
}

Visit http://localhost:3000/api/hello. You get JSON!


🟩 2. Handling POST Requests

Let’s receive some data.

src/app/api/users/route.ts:

import { NextResponse } from 'next/server';

export async function POST(request: Request) {
  const body = await request.json(); // Read the JSON body
  
  if (!body.email) {
    return NextResponse.json({ error: 'Email required' }, { status: 400 });
  }

  // Simulate saving to DB
  const newUser = { id: 1, email: body.email, role: 'user' };

  return NextResponse.json(newUser, { status: 201 });
}

🟧 3. Dynamic Route Handlers

Just like pages, APIs can have params!

src/app/api/posts/[id]/route.ts:

export async function GET(
  request: Request,
  { params }: { params: { id: string } }
) {
  const id = params.id;
  // fetch post by id...
  return NextResponse.json({ id, title: `Post #${id}` });
}

Visit /api/posts/42 -> { "id": "42", "title": "Post #42" }.


πŸŸ₯ 4. Caching Behavior

By default, GET requests in Route Handlers are cached if they don’t use the Request object. If you use request (e.g., needed usage of URL search params, cookies) or other verbs (POST), it defaults to dynamic.

You can opt-out of caching:

export const dynamic = 'force-dynamic';

πŸ§ͺ Challenge: Day 14

  1. Create an API Endpoint: /api/time.
  2. Make it return the current server time: { time: new Date().toISOString() }.
  3. Set export const dynamic = 'force-dynamic' to ensure it updates on every refresh.
  4. Test it using Postman, Curl, or just your browser.

See you tomorrow for the game changer: Server Actions! πŸ’₯