Page Middleware
Protect pages and handle authentication with middleware
Overview
Page middleware protects routes and handles authentication. Use middleware.ts files in your app directory.
Creating Middleware
Create a middleware.ts file to protect routes:
// app/middleware.ts
import { redirect, getCookie } from "@axi-js/core";
import type { MiddlewareContext } from "@axi-js/core";
export async function middleware({ request }: MiddlewareContext) {
const authToken = getCookie(request, "auth_token");
if (!authToken) {
return redirect("/auth/login");
}
// Add user to context
return {
user: { id: "123", role: "user" },
};
}This protects all routes. Unauthenticated users are redirected to /auth/login.
Accessing Context
Middleware data flows to loaders and pages:
import type { LoaderContext, PageProps } from "@axi-js/core";
export async function loader({ context }: LoaderContext) {
// Access middleware data
return {
user: context.user,
};
}
export default function Page({ data }: PageProps) {
const { user } = data as { user: User };
return <h1>Welcome, {user.name}</h1>;
}Public Routes
Override parent middleware for public routes:
// app/auth/middleware.ts
export async function middleware() {
// Return empty object to allow access
return {};
}This makes all /auth routes public, overriding the root middleware.
Role-Based Access
Restrict routes by role:
// app/admin/middleware.ts
import { redirect } from "@axi-js/core";
import type { MiddlewareContext } from "@axi-js/core";
export async function middleware({ context }: MiddlewareContext) {
const user = context.user as { role: string };
if (user.role !== "admin") {
return redirect("/dashboard");
}
return { user };
}Only admin users can access /admin routes.
Cascading Middleware
Middleware executes from child to parent:
app/admin/middleware.ts(runs first)app/middleware.ts(runs if child returns undefined)
This allows specific routes to override general protection.
Cookie Utilities
Built-in helpers for auth:
import { getCookie, setCookie, deleteCookie, redirect } from "@axi-js/core";
import type { MiddlewareContext } from "@axi-js/core";
export async function middleware({ request }: MiddlewareContext) {
// Get cookie
const token = getCookie(request, "auth_token");
// Set cookie
const response = redirect("/dashboard");
setCookie(response, "session_id", "abc123", {
httpOnly: true,
secure: true,
maxAge: 3600,
});
return response;
}Complete Example
Authentication flow:
// app/middleware.ts - Protect all routes
import { redirect, getCookie } from "@axi-js/core";
import type { MiddlewareContext } from "@axi-js/core";
export async function middleware({ request }: MiddlewareContext) {
const token = getCookie(request, "auth_token");
if (!token) {
return redirect("/auth/login");
}
const user = await validateToken(token);
return { user };
}// app/auth/middleware.ts - Allow public access
export async function middleware() {
return {};
}// app/admin/middleware.ts - Require admin
import { redirect } from "@axi-js/core";
import type { MiddlewareContext } from "@axi-js/core";
export async function middleware({ context }: MiddlewareContext) {
if (context.user?.role !== "admin") {
return redirect("/dashboard");
}
}