Proxy: code before the request
A proxy is a function that runs before Next.js renders a page or calls an API. It sees the request and can let it through, redirect it to another address or add headers. It is usually used for a quick login check and language selection. Before Next.js 16 this was called middleware — older articles show a middleware.ts file.
Where the file lives
The proxy is a single proxy.ts file in the project root, next to the app/ folder, not inside it. Let us start with a simple request log:
// proxy.ts
import { NextResponse, type NextRequest } from 'next/server';
export function proxy(request: NextRequest) {
console.log('Request:', request.nextUrl.pathname);
return NextResponse.next();
}The function is called proxy. NextResponse.next() lets the request through. Open a few pages — lines like "Request: /posts" appear in the npm run dev terminal.
Limiting addresses: matcher
Without settings, the proxy runs on every request, including images and script files. A config object with a matcher field keeps only the addresses you need:
// proxy.ts (fragment)
export const config = {
matcher: ['/posts/new', '/admin/:path*'],
};:path* means "and everything nested": /admin, /admin/users, /admin/users/5.
Redirecting without a login
Let us close the add-post form to visitors who have not logged in. The sign of a login is a session cookie — the next lesson covers setting it:
// proxy.ts
import { NextResponse, type NextRequest } from 'next/server';
export function proxy(request: NextRequest) {
const session = request.cookies.get('session');
if (!session) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/posts/new'],
};Open /posts/new in a private window — the browser lands on /login. The redirect method takes a full address, so it is built with new URL from the current request.
What else the proxy can do
| Task | How |
|---|---|
| Read a cookie | request.cookies.get('name') |
| Read a header | request.headers.get('accept-language') |
| Redirect | NextResponse.redirect(url) |
| Show another page without changing the address | NextResponse.rewrite(url) |
| Add a response header | response.headers.set('x-name', 'value') |
Limitations
The proxy must be fast: it runs on every matching request. In Next.js 16 it runs in the Node.js runtime, but slow database queries still do not belong here. The proxy is for a quick preliminary check such as whether a cookie exists; the full permission check happens in the page or the server action. For simple permanent redirects without conditions, the redirects setting in next.config.ts is more convenient.
Common mistake
Copying a middleware.ts file with a middleware function from an older article. In Next.js 16 that name is deprecated: the build shows a warning, and future versions will stop supporting it. Name the file proxy.ts and the function proxy, and put the file in the project root, not in app/.