🔌 routeWrapper()

Wrap your Next.js App Router API Handlers (e.g., GET, POST) with automatic try-catch, standardized error responses, and optional authentication gating.

Setting Up Secure API Routes

If you need a traditional REST API endpoint to serve external systems or complex backend processes inside the /app/api/ layout, you can use routeWrapper() to guard against crashes and enforce that a request contains a valid Supabase Session.

// app/api/posts/route.ts
import { routeWrapper } from "next-supa-utils/server";
import { NextResponse } from "next/server";

export const POST = routeWrapper(
  async (request, { supabase, user }) => {
    const body = await request.json();
    
    // Perform database insertions knowing 'user' is guaranteed
    const { data, error } = await supabase
      .from("posts")
      .insert({ ...body, user_id: user.id })
      .single();
      
    if (error) throw error; 
    
    return NextResponse.json({ data });
  },
  { requireAuth: true } // Auto-returns a 401 HTTP response if the caller is not logged in
);

API Reference

Signature:

function routeWrapper<TContext>(
  handler: (request: NextRequest, context: RouteHandlerContext<TContext>) => Promise<NextResponse | Response>,
  options?: RouteWrapperOptions
): (request: NextRequest, context: NextRouteContext) => Promise<NextResponse>

Context (RouteHandlerContext)

The second argument handed inside the callback (context) automatically provides:

  • params: Auto-resolved dynamic route params (e.g., { id: "123" }) from your folder structure.
  • supabase: An initialized Supabase server client instance (always available).
  • user: The authenticated user (guaranteed non-null if requireAuth: true).

Options (RouteWrapperOptions)

Configuring behavior is simple using the options object:

ConfigurationTypeDescription
requireAuthbooleanIf true, returns a JSON 401 Unauthorized response if the user has no valid session token in their headers/cookies.
supabaseUrlstringExplicit Supabase URL override.
supabaseAnonKeystringExplicit Supabase Anon Key override.

[!tip] Throwing Standard Errors! You don't have to manually compose NextResponse.json({ error }, { status: 500 }) inside the body! Just throw an error or throw the Supabase error! The wrapper will pick it up and emit an isomorphic 500 automatically.