Middleware
Middleware
Route-level middleware lets you intercept page requests before they reach the page handler. Use it for authentication, redirects, logging, and validation.
The _middleware.ts convention
Place a _middleware.ts file in any route directory. It runs for all routes in that directory and its subdirectories.
pages/_middleware.ts -> runs for all routesindex.tsxdashboard/_middleware.ts -> runs only for /dashboard/*settings.tsxprofile.tsxadmin/_middleware.ts -> auth check for /admin/*index.tsx
Middleware context
A middleware function receives a context object with params (dynamic route params) and request (the original Request), plus a next function as the second argument to continue the chain. It returns a Response.
import type { MiddlewareContext, MiddlewareNext } from "@thexjs/core";export async function middleware(ctx: MiddlewareContext, next: MiddlewareNext) { console.log(`[${ctx.request.method}] ${ctx.request.url}`); return next();}Auth middleware example
A common use case is checking for an auth cookie and redirecting unauthenticated users.
import type { MiddlewareContext, MiddlewareNext } from "@thexjs/core";export async function middleware(ctx: MiddlewareContext, next: MiddlewareNext) { const session = ctx.request.headers.get("cookie"); if (!session) { return new Response(null, { status: 302, headers: { Location: "/login" }, }); } const user = await validateSession(session); if (!user) { return new Response(null, { status: 302, headers: { Location: "/login" }, }); } return next();}MiddlewareNext
Call next() (no arguments) to pass control to the next middleware or the route handler. Any mutations to ctx.params you make before the call flow through to downstream handlers.
Middleware applies to page routes only. API routes (in apiDir) and content routes are dispatched without a middleware chain.
Redirect patterns
Return a Response with a 302 status and a Location header to redirect. You can also return JSON responses for API middleware validation errors.
// Redirect to loginreturn new Response(null, { status: 302, headers: { Location: "/login?redirect=" + ctx.request.url },});// Redirect back after successful authconst url = new URL(ctx.request.url);const redirectTo = url.searchParams.get("redirect") || "/";return new Response(null, { status: 302, headers: { Location: redirectTo },});