Home     /Articles     /

Building Scalable APIs with Next.js 15 App Router Using TypeScript

NextJS 15

Building Scalable APIs with Next.js 15 App Router Using TypeScript

Written by Briann     |

December 04, 2024     |

1.4k |

Next.js 15’s App Router is a powerful platform for building scalable APIs, and TypeScript ensures these APIs are type-safe and maintainable. By leveraging TypeScript’s strict type-checking and Next.js 15’s modern architecture, you can build robust and efficient APIs. In this post, we’ll explore how to create scalable APIs in Next.js 15 using TypeScript with practical examples.





1. Setting Up a Basic TypeScript API Route

In the App Router, API routes are defined as TypeScript files in the app/api folder.


Example: Basic API Route with TypeScript

// app/api/hello/route.ts

import { NextResponse } from "next/server";

export async function GET(): Promise {
  return NextResponse.json({ message: "Hello, Next.js with TypeScript!" });
}


Key Points:

  • Use NextResponse for constructing API responses.
  • Return types are explicitly defined for better type-checking.





2. Dynamic API Routes with TypeScript

Dynamic routes allow you to create endpoints based on parameters. TypeScript adds type safety for incoming parameters.


Example: Dynamic User API Route

// app/api/users/[id]/route.ts

import { NextResponse } from "next/server";

type User = {
  id: string;
  name: string;
  email: string;
};

export async function GET(
  request: Request,
  { params }: { params: { id: string }
 }): Promise {
  const { id } = params;

  const user: User = { id, name: "John Doe", email: "john@example.com" }; // Mock data
  return NextResponse.json(user);}

Requesting /api/users/123 will return user data for the ID 123.





3. Middleware for API Authentication

Middleware can preprocess requests, and TypeScript ensures that headers and responses are handled correctly.


Example: Authentication Middleware

// middleware.ts

import { NextRequest, NextResponse } from "next/server";

export function middleware(request: NextRequest): NextResponse | undefined {
  const authHeader = request.headers.get("Authorization");
    if (!authHeader || authHeader !== "Bearer my-secret-token") {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  return NextResponse.next();
}

The middleware ensures that all API routes require valid authentication.





4. API Caching with TypeScript

Next.js 15’s enhanced caching mechanisms improve scalability.


Example: API Route with Revalidation

// app/api/products/route.ts

import { NextResponse } from "next/server";

type Product = {
  id: string;
  name: string;
  price: number;
};

export async function GET(): Promise {
  const products: Product[] = [
    { id: "1", name: "Laptop", price: 1200 },
    { id: "2", name: "Phone", price: 800 },
  ];

  return NextResponse.json(products, {
    headers: {
      "Cache-Control": "s-maxage=60, stale-while-revalidate=30",
    },
  });
}

This API route caches responses for 60 seconds while allowing stale data to be served during revalidation.





5. Type-safe Error Handling

Error handling becomes clearer with TypeScript, as you can explicitly define error structures.


Example: Error Handling in API Route

// app/api/items/route.ts

import { NextResponse } from "next/server";

type ErrorResponse = {
  error: string;
  message: string;
};

export async function GET(): Promise {
  try {
    throw new Error("Something went wrong!");
  } catch (error) {
    const response: ErrorResponse = {
      error: "ServerError",
      message: (error as Error).message,
    };

    return NextResponse.json(response, { status: 500 });
  }}





6. Validating Input Data with TypeScript

Ensure incoming data adheres to expected types by validating request bodies.


Example: Validating a POST Reque

// app/api/posts/route.ts

import { NextResponse } from "next/server";

type PostRequest = {
  title: string;
  content: string;
};

export async function POST(request: Request): Promise {
  const body: PostRequest = await request.json();
  if (!body.title || !body.content) {
    return NextResponse.json(
      { error: "Invalid input" },
      { status: 400 }
    );
  }

  return NextResponse.json({ message: "Post created successfully" });
}





7. Advanced Features: Streaming Responses

Streaming data is crucial for real-time applications, and TypeScript ensures strong typing even for streams.


Example: Streaming API Response

// app/api/stream/route.ts

import { NextResponse } from "next/server";

export async function GET(): Promise {
  const encoder = new TextEncoder();
  const stream = new ReadableStream({
    start(controller) {
      controller.enqueue(encoder.encode("Hello, "));
      controller.enqueue(encoder.encode("streaming!"));
      controller.close();
    },
  });

  return new NextResponse(stream, {
    headers: { "Content-Type": "text/plain" },
  });
}





Conclusion


Next.js 15, combined with TypeScript, provides a powerful framework for building scalable and type-safe APIs. By leveraging features like dynamic routes, caching, middleware, and streaming, you can create efficient APIs tailored to modern applications.


What are your favorite TypeScript strategies in Next.js?

Powered by Froala Editor

Related Articles

What’s New with NextJs 15 RC

NextJS 15

What’s New with NextJs 15 RC

December 01, 2024