npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nextjs-proxy

v1.1.7

Published

Universal, secure proxy for Next.js. Centralize, audit, and control all external API calls from a single entry point.

Readme

NextJs Proxy

Universal, secure proxy for Next.js. Centralize, audit, and control all external API calls from a single entry point, with support for:

  • Security (hides credentials and backend logic)
  • Configurable CORS
  • Centralized outbound traffic
  • Structured auditing and logging
  • Request/response transformation
  • Access control and validation
  • Rate limiting (custom and in-memory included)
  • Support for relative endpoints via baseUrl

Ideal for projects with multiple external integrations or governance requirements over outbound traffic.

NextJs Proxy is designed to work seamlessly with the modern, native architecture of Next.js. For optimal performance, security, and maintainability, we recommend combining:

  • Rewrites in next.config.js for declarative route mapping
  • Middleware for global, centralized logic (auth, rate limiting, logging)
  • nextjs-proxy handler for advanced, per-endpoint proxy logic

1. Route Rewrites (next.config.js)

// next.config.js
module.exports = {
  async rewrites() {
    return [
      {
        source: "/api/proxy/:path*",
        destination: "/api/proxy", // All requests go to your handler
      },
    ];
  },
};

2. Global Middleware (middleware.ts)

Important: If your Next.js project uses the Pages Router (i.e., you have a pages/ folder), the middleware file must be located at src/middleware.ts for Next.js to detect it correctly. If you use only the App Router, it can be in the project root or in src/.

// src/middleware.ts
import { NextResponse, NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  // Example: global authentication
  const token = request.headers.get("authorization");
  if (!token) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }
  // Add logging, rate limiting, etc. here
  return NextResponse.next();
}

// Apply only to proxy routes
export const config = {
  matcher: ["/api/proxy/:path*"],
};

3. Centralized Advanced Logic (Handler)

// app/api/proxy/route.ts
import { nextProxyHandler, nextProxyHandlerAsync } from "nextjs-proxy";

// Versión síncrona (recomendada para la mayoría de casos)
export const POST = nextProxyHandler({
  // ...todas tus opciones avanzadas (logging, transform, masking, etc.)
});

// Versión asíncrona (si necesitas inicialización async)
const handlerPromise = nextProxyHandlerAsync({
  /* opciones */
});
export async function POST(req) {
  const handler = await handlerPromise;
  return handler(req);
}

With this approach you get:

  • Native performance and compatibility (serverless/edge)
  • Centralized governance and security
  • Advanced proxy logic with minimal code duplication
  • Easy maintenance and extensibility

This pattern is fully aligned with the best practices recommended by the Next.js team and the evolution of the framework.

⚠️ Warning: (No Turbopack Compatibility) NextJs Proxy is fully compatible with Next.js using Webpack. However, Turbopack (the new experimental bundler for Next.js) currently has limitations with local packages, workspaces, and some advanced module resolution patterns. If you experience issues using this package with Turbopack, consider the following options:

  • Recommended: Force the use of Webpack by adding to your next.config.js:
    experimental: {
      turbo: false;
    }
  • If you want to use Turbopack:
    • Publish the package to npm (even as private) and install it from the registry, not as a local or symlinked package.
    • Avoid cross-dependencies or indirect imports between workspaces.
  • Alternative: Bundle your module as a single JS file and consume it as a direct dependency.

Turbopack is under active development and will improve over time. For the latest status, see Vercel Turbopack GitHub.

Installation

pnpm add nextjs-proxy
# or
npm install nextjs-proxy

Quick Usage (App Router)

// app/api/proxy/route.ts
import { nextProxyHandler } from "nextjs-proxy";

export const POST = nextProxyHandler({
  baseUrl: process.env.EXTERNAL_API_BASE,
  allowOrigins: ["http://localhost:3000"],
});

Usage with Pages Router

// pages/api/proxy.ts
import type { NextApiRequest, NextApiResponse } from "next";
import { nextProxyHandler } from "nextjs-proxy";

const handler = nextProxyHandler({ baseUrl: process.env.EXTERNAL_API_BASE });

export default async function proxy(req: NextApiRequest, res: NextApiResponse) {
  // Minimal adapter
  // You may need to create a Request from NextApiRequest if needed
  // App Router is recommended for full compatibility.
  res.status(405).json({ error: "Use App Router for this package" });
}

Combined usage: App Router API + Pages Router frontend

You can use nextjs-proxy in an App Router API route and call it from a Pages Router frontend. This is a common and fully supported scenario in Next.js projects.

API route (App Router):

// src/app/api/proxy/route.ts
import { nextProxyHandler } from "nextjs-proxy";

export const POST = nextProxyHandler({
  baseUrl: "https://your-external-backend.com", // your external backend base URL
  allowOrigins: ["http://localhost:3000"], // adjust as needed
  // You can add more options: log, validate, rateLimit, etc.
});

Advanced Example

export const POST = nextProxyHandler({
  baseUrl: "https://api.my-service.com",
  allowOrigins: ["http://localhost:3000", "https://app.my-domain.com"],
  inMemoryRate: { windowMs: 60_000, max: 100 },
  log: (e) => console.log("[proxy]", e),
  validate: (req) => {
    const auth = req.headers.get("authorization");
    return !!(auth && auth.includes("Bearer "));
  },
  transformRequest: ({ method, endpoint, data }) => ({
    method: method ?? "GET",
    endpoint: endpoint.startsWith("/internal")
      ? endpoint.replace("/internal", "/v2")
      : endpoint,
    data,
  }),
  transformResponse: (res) => ({ ...res, proxiedAt: new Date().toISOString() }),
  maskSensitiveData: (data) => {
    if (!data) return data;
    if (typeof data === "object" && data !== null && "password" in data) {
      return { ...data, password: "***" };
    }
    return data;
  },
});

In a React component (e.g. src/pages/index.tsx), you should use a hook like useEffect to make the request after the component mounts:

import { useEffect } from "react";

export default function Home() {
  useEffect(() => {
    const fetchData = async () => {
      const req = await fetch("/api/proxy", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          method: "GET",
          endpoint: "/v1/health", // relative endpoint, will be resolved with baseUrl
        }),
      });
      const res = await req.json();
    };
    fetchData();
  }, []);

  return (
    <div>
      <h1>Home page</h1>
    </div>
  );
}

This pattern allows you to keep your API logic in the App Router (recommended for new Next.js projects) while using the classic Pages Router for your frontend. Both approaches work together seamlessly.

Full Options

| Option | Type | Description | | ------------------- | ----------------------------------- | ---------------------------------------------- | | log | (info) => void | Receives events: request, response, error. | | validate | (req) => boolean \| Promise | Allows to block flow (auth, permissions). | | transformRequest | ({method,endpoint,data}) => {...} | Modifies payload before fetch. | | transformResponse | (res) => any | Adjusts the response before sending to client. | | rateLimit | (req) => boolean \| Promise | Custom external rate limiting. | | inMemoryRate | { windowMs, max, key? } | Simple in-memory rate limiting. | | allowOrigins | string[] | CORS whitelist. | | onCorsDenied | (origin) => any | Custom response for denied CORS. | | maskSensitiveData | (data) => any | Sanitizes data before sending. | | baseUrl | string | Prefix for relative endpoints. |

CORS and Preflight

Automatically responds to OPTIONS with headers configured according to allowOrigins.

In-memory Rate Limiting

Minimal configuration:

inMemoryRate: { windowMs: 15_000, max: 20 }

Grouping is by IP (req.ip) or you can define key: (req) => 'user:'+id.

Common Errors

| Message | Cause | Solution | | ----------------------------------- | ---------------------------------------- | ---------------------------- | | Relative endpoint without baseUrl | Used relative endpoint without baseUrl | Define baseUrl in options | | Origin not allowed | CORS blocked | Add origin to allowOrigins | | Rate limit exceeded | Limit reached | Increase max or window |

Comparison: nextjs-proxy vs other Next.js proxy solutions

Next.js offers several ways to proxy API requests. Here’s when to use each approach:

| Solution | Use Case | Limitations | | ------------------------------- | --------------------------------------------------------- | ------------------------------------------ | | Rewrites (next.config.js) | Simple path forwarding, development, no logic needed | Cannot modify headers, no auth, no logging | | http-proxy / middleware | Custom API routes, can modify requests, more control | More boilerplate, not native to App Router | | next-http-proxy-middleware | Simplifies http-proxy usage in API routes | Still requires custom route, less flexible | | @navikt/next-api-proxy | Advanced token exchange, enterprise security | Complex setup, focused on auth scenarios | | nextjs-proxy (this package) | Centralized, configurable, minimal, works with App Router | Not for legacy custom servers |

Why use nextjs-proxy?

  • Native integration with App Router and Pages Router
  • Centralized logic: CORS, logging, rate limiting, request/response transformation, access control
  • Minimal dependencies, clean API, easy to maintain
  • Ideal for projects needing governance, security, and audit over outbound traffic

If you only need simple path forwarding for development, rewrites are enough. For production, security, and advanced logic, use nextjs-proxy.

License

MIT