Bird
Raised Fist0
NextJSframework~10 mins

Route handlers (route.ts) in NextJS - Step-by-Step Execution

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Concept Flow - Route handlers (route.ts)
Incoming HTTP Request
Match URL & Method
Call Route Handler Function
Process Request Data
Generate Response
Send Response to Client
This flow shows how Next.js route handlers receive a request, process it, and send back a response.
Execution Sample
NextJS
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  return NextResponse.json({ message: 'Hello from GET' });
}
A simple GET route handler that responds with a JSON message.
Execution Table
StepActionInputOutputNotes
1Receive HTTP GET request/api/helloRequest object createdRequest arrives at route.ts
2Match route and methodGET /api/helloCalls GET handlerRoute handler function selected
3Execute GET handlerRequest objectNextResponse with JSON {message: 'Hello from GET'}Handler processes request
4Send responseNextResponseHTTP 200 with JSON bodyResponse sent to client
5End--Request cycle complete
💡 Request handled and response sent, no further processing.
Variable Tracker
VariableStartAfter Step 1After Step 3Final
requestundefinedRequest object with URL /api/helloSame Request objectSame Request object
responseundefinedundefinedNextResponse with JSON bodyNextResponse sent
Key Moments - 2 Insights
Why does the GET function receive a Request object?
Because in step 2 and 3 of the execution_table, the incoming HTTP request is wrapped as a Request object and passed to the GET handler to access details like URL and headers.
What happens if the route handler does not return a response?
If no response is returned, the request will hang or cause an error. The execution_table shows that the handler must return a NextResponse to complete the cycle.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the output of step 3?
ANextResponse with JSON {message: 'Hello from GET'}
BRequest object with URL /api/hello
CHTTP 404 Not Found
DUndefined
💡 Hint
Check the Output column in step 3 of the execution_table.
At which step is the route handler function selected?
AStep 1
BStep 2
CStep 4
DStep 5
💡 Hint
Look at the Action column in the execution_table for when the handler is called.
If the GET handler returned a plain string instead of NextResponse, what would change in the execution_table?
AStep 3 Output would be the string instead of NextResponse
BStep 2 would change to POST handler
CStep 4 would be skipped
DStep 1 would not receive a request
💡 Hint
Focus on the Output column in step 3 where the handler's return value is shown.
Concept Snapshot
Route handlers in Next.js (route.ts) receive HTTP requests as Request objects.
They match URL and method, then run the corresponding async function (GET, POST, etc).
Handlers return NextResponse objects to send HTTP responses.
This flow ensures clear request processing and response sending.
Always return a response to complete the request cycle.
Full Transcript
In Next.js, route handlers are functions defined in route.ts files that respond to HTTP requests. When a request arrives, Next.js matches the URL and HTTP method to the correct handler function, such as GET or POST. The handler receives a Request object containing details about the request. It processes this data and returns a NextResponse object, which Next.js sends back to the client as the HTTP response. This process ensures each request is handled clearly and efficiently. If a handler does not return a response, the request will not complete properly. This visual trace shows each step from receiving the request to sending the response.

Practice

(1/5)
1. What is the main purpose of a route.ts file in Next.js?
easy
A. To configure database connections
B. To style components using CSS modules
C. To create client-side React components
D. To define server-side code that handles HTTP requests for a specific URL

Solution

  1. Step 1: Understand the role of route.ts

    The route.ts file is used in Next.js to write server-side code that responds to HTTP requests for a specific route.
  2. Step 2: Compare with other options

    Styling, client components, and database configs are handled elsewhere, not in route.ts.
  3. Final Answer:

    To define server-side code that handles HTTP requests for a specific URL -> Option D
  4. Quick Check:

    Route handlers = server code for URLs [OK]
Hint: Route handlers handle server requests per URL [OK]
Common Mistakes:
  • Confusing route.ts with client component files
  • Thinking route.ts is for styling
  • Assuming route.ts manages database directly
2. Which of the following is the correct way to export a GET handler in route.ts?
easy
A. export async function GET(request: NextRequest) { return NextResponse.json({ message: 'Hi' }) }
B. export function Get() { return 'Hello' }
C. export async function get() { return new Response('Hello') }
D. export async function fetch() { return 'Hello' }

Solution

  1. Step 1: Recall Next.js route handler syntax

    Next.js expects exported async functions named exactly by HTTP method in uppercase, e.g., GET, with NextRequest parameter and returning NextResponse.
  2. Step 2: Check each option

    export async function GET(request: NextRequest) { return NextResponse.json({ message: 'Hi' }) } matches correct syntax: async, uppercase GET, parameter, and returns NextResponse. Others have wrong function names, casing, or return types.
  3. Final Answer:

    export async function GET(request: NextRequest) { return NextResponse.json({ message: 'Hi' }) } -> Option A
  4. Quick Check:

    Uppercase method + NextRequest + NextResponse = correct [OK]
Hint: Use uppercase HTTP method and NextRequest param [OK]
Common Mistakes:
  • Using lowercase method names like get instead of GET
  • Missing NextRequest parameter
  • Returning plain string instead of NextResponse
3. Given this route.ts code, what will be the JSON response body when a GET request is made?
import { NextResponse } from 'next/server';

export async function GET() {
  return NextResponse.json({ success: true, data: [1, 2, 3] });
}
medium
A. undefined
B. {"success":true,"data":[1,2,3]}
C. {"error":"Method not allowed"}
D. [1, 2, 3]

Solution

  1. Step 1: Analyze the GET handler return

    The GET function returns NextResponse.json with an object containing success: true and data: [1, 2, 3].
  2. Step 2: Understand JSON response format

    This creates a JSON response with the exact object serialized as a JSON string.
  3. Final Answer:

    {"success":true,"data":[1,2,3]} -> Option B
  4. Quick Check:

    NextResponse.json outputs JSON string [OK]
Hint: NextResponse.json sends exact JSON object [OK]
Common Mistakes:
  • Expecting just the array without wrapping object
  • Confusing error responses with success
  • Thinking response is undefined
4. Identify the error in this route.ts code snippet:
export async function POST(request: NextRequest) {
  const data = await request.json();
  return new Response(JSON.stringify(data));
}

export async function GET() {
  return new Response('Hello');
}
medium
A. Missing import of NextRequest
B. GET function must accept a request parameter
C. POST handler should return NextResponse, not Response
D. No error, code is correct

Solution

  1. Step 1: Check imports

    The code uses NextRequest but does not import it from 'next/server'. This causes a runtime error.
  2. Step 2: Validate other parts

    GET handler can omit request parameter if unused. Returning Response is allowed but NextResponse is preferred; not an error. So main error is missing import.
  3. Final Answer:

    Missing import of NextRequest -> Option A
  4. Quick Check:

    Using NextRequest requires import [OK]
Hint: Always import NextRequest when used [OK]
Common Mistakes:
  • Forgetting to import NextRequest
  • Thinking GET must have request param
  • Confusing Response and NextResponse as errors
5. You want to create a route handler in route.ts that responds to both GET and POST requests. The GET returns a JSON list of users, and the POST adds a user from the request body and returns the updated list. Which code snippet correctly implements this behavior?
hard
A. export async function GET(request) { return new Response(JSON.stringify(['Alice', 'Bob'])); } export async function POST(request) { const data = await request.json(); return new Response(JSON.stringify(['Alice', 'Bob'])); }
B. import { NextRequest } from 'next/server'; const users = []; export function get() { return users; } export function post(request) { users.push(request.body.name); return users; }
C. import { NextRequest, NextResponse } from 'next/server'; let users = ['Alice', 'Bob']; export async function GET() { return NextResponse.json(users); } export async function POST(request: NextRequest) { const newUser = await request.json(); users.push(newUser.name); return NextResponse.json(users); }
D. import { NextResponse } from 'next/server'; export async function GET() { return NextResponse.json(['Alice', 'Bob']); } export async function POST() { return NextResponse.json(['Alice', 'Bob', 'Charlie']); }

Solution

  1. Step 1: Check imports and state management

    import { NextRequest, NextResponse } from 'next/server'; let users = ['Alice', 'Bob']; export async function GET() { return NextResponse.json(users); } export async function POST(request: NextRequest) { const newUser = await request.json(); users.push(newUser.name); return NextResponse.json(users); } correctly imports NextRequest and NextResponse, and uses a mutable users array to store state between calls.
  2. Step 2: Verify GET and POST handlers

    GET returns current users as JSON. POST reads JSON body, adds new user, then returns updated list. This matches requirements.
  3. Step 3: Review other options

    import { NextRequest } from 'next/server'; const users = []; export function get() { return users; } export function post(request) { users.push(request.body.name); return users; } uses lowercase method names and no NextResponse, invalid in Next.js route handlers. export async function GET(request) { return new Response(JSON.stringify(['Alice', 'Bob'])); } export async function POST(request) { const data = await request.json(); return new Response(JSON.stringify(['Alice', 'Bob'])); } returns new Response but does not maintain state. import { NextResponse } from 'next/server'; export async function GET() { return NextResponse.json(['Alice', 'Bob']); } export async function POST() { return NextResponse.json(['Alice', 'Bob', 'Charlie']); } POST does not accept request or update users dynamically.
  4. Final Answer:

    import { NextRequest, NextResponse } from 'next/server'; let users = ['Alice', 'Bob']; export async function GET() { return NextResponse.json(users); } export async function POST(request: NextRequest) { const newUser = await request.json(); users.push(newUser.name); return NextResponse.json(users); } -> Option C
  5. Quick Check:

    Correct imports + state + async handlers = import { NextRequest, NextResponse } from 'next/server'; let users = ['Alice', 'Bob']; export async function GET() { return NextResponse.json(users); } export async function POST(request: NextRequest) { const newUser = await request.json(); users.push(newUser.name); return NextResponse.json(users); } [OK]
Hint: Use async GET/POST with NextRequest, NextResponse, and shared state [OK]
Common Mistakes:
  • Using lowercase method names instead of uppercase
  • Not importing NextRequest or NextResponse
  • Not maintaining state between requests
  • Ignoring async/await for request.json()